diff --git a/src/lte/doc/source/lte-design.rst b/src/lte/doc/source/lte-design.rst index f347acb49..28e179019 100644 --- a/src/lte/doc/source/lte-design.rst +++ b/src/lte/doc/source/lte-design.rst @@ -4299,6 +4299,9 @@ sequence diagram of Distributed Fractional Frequency Reuse Scheme. \clearpage + +.. _sec-carrier-aggregation: + -------------------- Carrier Aggregation -------------------- @@ -4703,7 +4706,6 @@ Helpers Two helper objects are used to setup simulations and configure the various components. These objects are: - * ``LteHelper``, which takes care of the configuration of the LTE radio access network, as well as of coordinating the setup and release of EPS bearers. The ``LteHelper`` class provides both the API definition and its implementation. @@ -4711,6 +4713,9 @@ various components. These objects are: ``EpcHelper`` class is an abstract base class, which only provides the API definition; the implementation is delegated to the child classes in order to allow for different EPC network models. + +A third helper object is used to configure the :ref:`_sec-carrier-aggregation` functionality: + * ``CcHelper``, which takes care of the configuration of the ``LteEnbComponentCarrierMap``, basically, it creates a user specified number of ``LteEnbComponentCarrier``. ``LteUeComponentCarrierMap`` is currently created starting from the diff --git a/src/lte/doc/source/lte-user.rst b/src/lte/doc/source/lte-user.rst index f9acf3c81..c567c3d86 100644 --- a/src/lte/doc/source/lte-user.rst +++ b/src/lte/doc/source/lte-user.rst @@ -178,13 +178,17 @@ Supposing your simulation program is called ``src/lte/examples/lte-sim-with-input``, you can now pass these settings to the simulation program in the following way:: - ./waf --command-template="%s --ns3::ConfigStore::Filename=input-defaults.txt --ns3::ConfigStore::Mode=Load --ns3::ConfigStore::FileFormat=RawText" --run src/lte/examples/lte-sim-with-input + ./waf --command-template="%s --ns3::ConfigStore::Filename=input-defaults.txt + --ns3::ConfigStore::Mode=Load --ns3::ConfigStore::FileFormat=RawText" + --run src/lte/examples/lte-sim-with-input Furthermore, you can generate a template input file with the following command:: - ./waf --command-template="%s --ns3::ConfigStore::Filename=input-defaults.txt --ns3::ConfigStore::Mode=Save --ns3::ConfigStore::FileFormat=RawText" --run src/lte/examples/lte-sim-with-input + ./waf --command-template="%s --ns3::ConfigStore::Filename=input-defaults.txt + --ns3::ConfigStore::Mode=Save --ns3::ConfigStore::FileFormat=RawText" + --run src/lte/examples/lte-sim-with-input note that the above will put in the file ``input-defaults.txt`` *all* the default values that are registered in your particular build of the @@ -830,7 +834,7 @@ to the PGW via a point-to-point link:: Ptr pgw = epcHelper->GetPgwNode (); - // Create a single RemoteHost + // Create a single RemoteHost NodeContainer remoteHostContainer; remoteHostContainer.Create (1); Ptr remoteHost = remoteHostContainer.Get (0); @@ -841,8 +845,8 @@ to the PGW via a point-to-point link:: PointToPointHelper p2ph; p2ph.SetDeviceAttribute ("DataRate", DataRateValue (DataRate ("100Gb/s"))); p2ph.SetDeviceAttribute ("Mtu", UintegerValue (1500)); - p2ph.SetChannelAttribute ("Delay", TimeValue (Seconds (0.010))); - NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost); + p2ph.SetChannelAttribute ("Delay", TimeValue (Seconds (0.010))); + NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost); Ipv4AddressHelper ipv4h; ipv4h.SetBase ("1.0.0.0", "255.0.0.0"); Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign (internetDevices); @@ -851,8 +855,10 @@ to the PGW via a point-to-point link:: Ipv4StaticRoutingHelper ipv4RoutingHelper; - Ptr remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject ()); - remoteHostStaticRouting->AddNetworkRouteTo (epcHelper->GetEpcIpv4NetworkAddress (), Ipv4Mask ("255.255.0.0"), 1); + Ptr remoteHostStaticRouting; + remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject ()); + remoteHostStaticRouting->AddNetworkRouteTo (epcHelper->GetEpcIpv4NetworkAddress (), + Ipv4Mask ("255.255.0.0"), 1); Now, you should go on and create LTE eNBs and UEs as explained in the previous sections. You can of course configure other LTE aspects such @@ -860,52 +866,55 @@ as pathloss and fading models. Right after you created the UEs, you should also configure them for IP networking. This is done as follows. We assume you have a container for UE and eNodeB nodes like this:: - NodeContainer ueNodes; - NodeContainer enbNodes; - + NodeContainer ueNodes; + NodeContainer enbNodes; to configure an LTE-only simulation, you would then normally do something like this:: - NetDeviceContainer ueLteDevs = lteHelper->InstallUeDevice (ueNodes); - lteHelper->Attach (ueLteDevs, enbLteDevs.Get (0)); + NetDeviceContainer ueLteDevs = lteHelper->InstallUeDevice (ueNodes); + lteHelper->Attach (ueLteDevs, enbLteDevs.Get (0)); in order to configure the UEs for IP networking, you just need to additionally do like this:: - // we install the IP stack on the UEs - InternetStackHelper internet; - internet.Install (ueNodes); + // we install the IP stack on the UEs + InternetStackHelper internet; + internet.Install (ueNodes); - // assign IP address to UEs - for (uint32_t u = 0; u < ueNodes.GetN (); ++u) - { - Ptr ue = ueNodes.Get (u); - Ptr ueLteDevice = ueLteDevs.Get (u); - Ipv4InterfaceContainer ueIpIface = epcHelper->AssignUeIpv4Address (NetDeviceContainer (ueLteDevice)); - // set the default gateway for the UE - Ptr ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ue->GetObject ()); - ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress (), 1); - } + // assign IP address to UEs + for (uint32_t u = 0; u < ueNodes.GetN (); ++u) + { + Ptr ue = ueNodes.Get (u); + Ptr ueLteDevice = ueLteDevs.Get (u); + Ipv4InterfaceContainer ueIpIface; + ueIpIface = epcHelper->AssignUeIpv4Address (NetDeviceContainer (ueLteDevice)); + // set the default gateway for the UE + Ptr ueStaticRouting; + ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ue->GetObject ()); + ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress (), 1); + } The activation of bearers is done in a slightly different way with respect to what done for an LTE-only simulation. First, the method ActivateDataRadioBearer is not to be used when the EPC is used. Second, when EPC is used, the default EPS bearer will be -activated automatically when you call LteHelper::Attach (). Third, if +activated automatically when you call ``LteHelper::Attach ()``. Third, if you want to setup dedicated EPS bearer, you can do so using the method -LteHelper::ActivateDedicatedEpsBearer (). This method takes as a +``LteHelper::ActivateDedicatedEpsBearer ()``. This method takes as a parameter the Traffic Flow Template (TFT), which is a struct that identifies the type of traffic that will be mapped to the dedicated EPS bearer. Here is an example for how to setup a dedicated bearer for an application at the UE communicating on port 1234:: - Ptr tft = Create (); - EpcTft::PacketFilter pf; - pf.localPortStart = 1234; - pf.localPortEnd = 1234; - tft->Add (pf); - lteHelper->ActivateDedicatedEpsBearer (ueLteDevs, EpsBearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT), tft); + Ptr tft = Create (); + EpcTft::PacketFilter pf; + pf.localPortStart = 1234; + pf.localPortEnd = 1234; + tft->Add (pf); + lteHelper->ActivateDedicatedEpsBearer (ueLteDevs, + EpsBearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT), + tft); you can of course use custom EpsBearer and EpcTft configurations, please refer to the doxygen documentation for how to do it. @@ -918,18 +927,18 @@ remoteHost, here is how to setup downlink communication, with an UdpClient application on the remote host, and a PacketSink on the LTE UE (using the same variable names of the previous code snippets) :: - uint16_t dlPort = 1234; - PacketSinkHelper packetSinkHelper ("ns3::UdpSocketFactory", - InetSocketAddress (Ipv4Address::GetAny (), dlPort)); - ApplicationContainer serverApps = packetSinkHelper.Install (ue); - serverApps.Start (Seconds (0.01)); - UdpClientHelper client (ueIpIface.GetAddress (0), dlPort); - ApplicationContainer clientApps = client.Install (remoteHost); - clientApps.Start (Seconds (0.01)); + uint16_t dlPort = 1234; + PacketSinkHelper packetSinkHelper ("ns3::UdpSocketFactory", + InetSocketAddress (Ipv4Address::GetAny (), dlPort)); + ApplicationContainer serverApps = packetSinkHelper.Install (ue); + serverApps.Start (Seconds (0.01)); + UdpClientHelper client (ueIpIface.GetAddress (0), dlPort); + ApplicationContainer clientApps = client.Install (remoteHost); + clientApps.Start (Seconds (0.01)); That's all! You can now start your simulation as usual:: - Simulator::Stop (Seconds (10.0)); + Simulator::Stop (Seconds (10.0)); Simulator::Run (); @@ -951,8 +960,8 @@ First of all we build ns-3 appropriately:: # configure ./waf configure --enable-sudo --enable-modules=lte,fd-net-device --enable-examples - - # build + + # build ./waf @@ -960,26 +969,27 @@ Then we setup two virtual ethernet interfaces, and start wireshark to look at th # note: you need to be root - + # create two paired veth devices ip link add name veth0 type veth peer name veth1 ip link show - + # enable promiscuous mode ip link set veth0 promisc on ip link set veth1 promisc on - + # bring interfaces up ip link set veth0 up ip link set veth1 up - + # start wireshark and capture on veth0 wireshark & - + We can now run the example program with the simulated clock:: - ./waf --run lena-simple-epc-emu --command="%s --ns3::EmuEpcHelper::sgwDeviceName=veth0 --ns3::EmuEpcHelper::enbDeviceName=veth1" + ./waf --run lena-simple-epc-emu --command="%s --ns3::EmuEpcHelper::sgwDeviceName=veth0 + --ns3::EmuEpcHelper::enbDeviceName=veth1" Using wireshark, you should see ARP resolution first, then some GTP @@ -987,7 +997,8 @@ packets exchanged both in uplink and downlink. The default setting of the example program is 1 eNB and 1UE. You can change this via command line parameters, e.g.:: - ./waf --run lena-simple-epc-emu --command="%s --ns3::EmuEpcHelper::sgwDeviceName=veth0 --ns3::EmuEpcHelper::enbDeviceName=veth1 --nEnbs=2 --nUesPerEnb=2" + ./waf --run lena-simple-epc-emu --command="%s --ns3::EmuEpcHelper::sgwDeviceName=veth0 + --ns3::EmuEpcHelper::enbDeviceName=veth1 --nEnbs=2 --nUesPerEnb=2" To get a list of the available parameters:: @@ -1003,12 +1014,16 @@ with the BestEffort mode is not a good idea: something can go wrong So you need a decent hardware and the optimized build with statically linked modules:: - ./waf configure -d optimized --enable-static --enable-modules=lte --enable-examples --enable-sudo + ./waf configure -d optimized --enable-static --enable-modules=lte --enable-examples + --enable-sudo Then run the example program like this:: - ./waf --run lena-simple-epc-emu --command="%s --ns3::EmuEpcHelper::sgwDeviceName=veth0 --ns3::EmuEpcHelper::enbDeviceName=veth1 --simulatorImplementationType=ns3::RealtimeSimulatorImpl --ns3::RealtimeSimulatorImpl::SynchronizationMode=HardLimit" + ./waf --run lena-simple-epc-emu --command="%s --ns3::EmuEpcHelper::sgwDeviceName=veth0 + --ns3::EmuEpcHelper::enbDeviceName=veth1 + --SimulatorImplementationType=ns3::RealtimeSimulatorImpl + --ns3::RealtimeSimulatorImpl::SynchronizationMode=HardLimit" note the HardLimit setting, which will cause the program to terminate @@ -1021,6 +1036,111 @@ transport network. +.. _sec-custom-backhaul: + +Custom Backhaul +--------------- + +In the previous sections, :ref:`sec-evolved-packet-core`, we explained how to write a simulation +program using EPC with a predefined backhaul network between the RAN and the EPC. We used the +``PointToPointEpcHelper``. This ``EpcHelper`` creates point-to-point links between the eNBs and the SGW. + +We now explain how to write a simulation program that allows the simulator user to create any kind +of backhaul network in the simulation program. + +First of all, in addition to ``LteHelper``, you need to use the ``NoBackhaulEpcHelper`` class, which +implements an EPC but without connecting the eNBs with the core network. It just creates the network +elements of the core network:: + + Ptr lteHelper = CreateObject (); + Ptr epcHelper = CreateObject (); + + +Then, as usual, you need to tell the LTE helper that the EPC will be used:: + + lteHelper->SetEpcHelper (epcHelper); + + +Now, you should create the backhaul network. Here we create point-to-point links as it is done +by the ``PointToPointEpcHelper``. We assume you have a container for eNB nodes like this:: + + NodeContainer enbNodes; + +We get the SGW node:: + + Ptr sgw = epcHelper->GetSgwNode (); + +And we connect every eNB from the container with the SGW with a point-to-point link. We also assign +IPv4 addresses to the interfaces of eNB and SGW with ``s1uIpv4AddressHelper.Assign (sgwEnbDevices)`` +and finally we tell the EpcHelper that this ``enb`` has a new S1 interface with +``epcHelper->AddS1Interface (enb, enbS1uAddress, sgwS1uAddress)``, where ``enbS1uAddress`` and +``sgwS1uAddress`` are the IPv4 addresses of the eNB and the SGW, respectively:: + + Ipv4AddressHelper s1uIpv4AddressHelper; + + // Create networks of the S1 interfaces + s1uIpv4AddressHelper.SetBase ("10.0.0.0", "255.255.255.252"); + + for (uint16_t i = 0; i < enbNodes.GetN (); ++i) + { + Ptr enb = enbNodes.Get (i); + + // Create a point to point link between the eNB and the SGW with + // the corresponding new NetDevices on each side + PointToPointHelper p2ph; + DataRate s1uLinkDataRate = DataRate ("10Gb/s"); + uint16_t s1uLinkMtu = 2000; + Time s1uLinkDelay = Time (0); + p2ph.SetDeviceAttribute ("DataRate", DataRateValue (s1uLinkDataRate)); + p2ph.SetDeviceAttribute ("Mtu", UintegerValue (s1uLinkMtu)); + p2ph.SetChannelAttribute ("Delay", TimeValue (s1uLinkDelay)); + NetDeviceContainer sgwEnbDevices = p2ph.Install (sgw, enb); + + Ipv4InterfaceContainer sgwEnbIpIfaces = s1uIpv4AddressHelper.Assign (sgwEnbDevices); + s1uIpv4AddressHelper.NewNetwork (); + + Ipv4Address sgwS1uAddress = sgwEnbIpIfaces.GetAddress (0); + Ipv4Address enbS1uAddress = sgwEnbIpIfaces.GetAddress (1); + + // Create S1 interface between the SGW and the eNB + epcHelper->AddS1Interface (enb, enbS1uAddress, sgwS1uAddress); + } + +This is just an example how to create a custom backhaul network. In this other example, we connect +all eNBs and the SGW to the same CSMA network:: + + // Create networks of the S1 interfaces + s1uIpv4AddressHelper.SetBase ("10.0.0.0", "255.255.255.0"); + + NodeContainer sgwEnbNodes; + sgwEnbNodes.Add (sgw); + sgwEnbNodes.Add (enbNodes); + + CsmaHelper csmah; + NetDeviceContainer sgwEnbDevices = csmah.Install (sgwEnbNodes); + Ptr sgwDev = sgwEnbDevices.Get (0); + + Ipv4InterfaceContainer sgwEnbIpIfaces = s1uIpv4AddressHelper.Assign (sgwEnbDevices); + Ipv4Address sgwS1uAddress = sgwEnbIpIfaces.GetAddress (0); + + for (uint16_t i = 0; i < enbNodes.GetN (); ++i) + { + Ptr enb = enbNodes.Get (i); + Ipv4Address enbS1uAddress = sgwEnbIpIfaces.GetAddress (i + 1); + + // Create S1 interface between the SGW and the eNB + epcHelper->AddS1Interface (enb, enbS1uAddress, sgwS1uAddress); + } + +As you can see, apart from how you create the backhaul network, i.e. the point-to-point links or +the CSMA network, the important point is to tell the ``EpcHelper`` that an ``eNB`` has a new S1 interface. + +Now, you should continue configuring your simulation program as it is explained in +:ref:`sec-evolved-packet-core` subsection. This configuration includes: the internet, installing the LTE eNBs +and possibly configuring other LTE aspects, installing the LTE UEs and configuring them as IP nodes, +activation of the dedicated EPS bearers and installing applications on the LTE UEs and on the remote hosts. + + .. _sec-network-attachment: diff --git a/src/lte/examples/lena-simple-epc-backhaul.cc b/src/lte/examples/lena-simple-epc-backhaul.cc new file mode 100644 index 000000000..43b846c9b --- /dev/null +++ b/src/lte/examples/lena-simple-epc-backhaul.cc @@ -0,0 +1,248 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2019 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Manuel Requena + */ + +#include "ns3/core-module.h" +#include "ns3/network-module.h" +#include "ns3/point-to-point-module.h" +#include "ns3/internet-module.h" +#include "ns3/applications-module.h" +#include "ns3/mobility-module.h" +#include "ns3/config-store-module.h" +#include "ns3/lte-module.h" +// #include "ns3/gtk-config-store.h" + +using namespace ns3; + +/** + * Sample simulation script for LTE+EPC with different backhauls. + * + * The purpose of this example is to compare: + * + * (1) how the simulation user can use a pre-existing EpcHelper that builds + * a predefined backhaul network (e.g. the PointToPointEpcHelper) and + * + * (2) how the simulation user can build its custom backhaul network in + * the simulation program (i.e. the point-to-point links are created + * in the simulation program instead of the pre-existing PointToPointEpcHelper) + * + * The pre-existing PointToPointEpcHelper is used with option --useHelper=1 and + * the custom backhaul is built with option --useHelper=0 + */ + +NS_LOG_COMPONENT_DEFINE ("LenaSimpleEpcBackhaul"); + +int +main (int argc, char *argv[]) +{ + uint16_t numNodePairs = 2; + Time simTime = MilliSeconds (1900); + double distance = 60.0; + Time interPacketInterval = MilliSeconds (100); + bool disableDl = false; + bool disableUl = false; + bool useHelper = false; + + // Command line arguments + CommandLine cmd; + cmd.AddValue ("numNodePairs", "Number of eNodeBs + UE pairs", numNodePairs); + cmd.AddValue ("simTime", "Total duration of the simulation", simTime); + cmd.AddValue ("distance", "Distance between eNBs [m]", distance); + cmd.AddValue ("interPacketInterval", "Inter packet interval", interPacketInterval); + cmd.AddValue ("disableDl", "Disable downlink data flows", disableDl); + cmd.AddValue ("disableUl", "Disable uplink data flows", disableUl); + cmd.AddValue ("useHelper", "Build the backhaul network using the helper or " + "it is built in the example", useHelper); + cmd.Parse (argc, argv); + + ConfigStore inputConfig; + inputConfig.ConfigureDefaults (); + + // parse again so you can override default values from the command line + cmd.Parse(argc, argv); + + Ptr lteHelper = CreateObject (); + Ptr epcHelper; + if (!useHelper) + { + epcHelper = CreateObject (); + } + else + { + epcHelper = CreateObject (); + } + lteHelper->SetEpcHelper (epcHelper); + + Ptr pgw = epcHelper->GetPgwNode (); + + // Create a single RemoteHost + NodeContainer remoteHostContainer; + remoteHostContainer.Create (1); + Ptr remoteHost = remoteHostContainer.Get (0); + InternetStackHelper internet; + internet.Install (remoteHostContainer); + + // Create the Internet + PointToPointHelper p2ph; + p2ph.SetDeviceAttribute ("DataRate", DataRateValue (DataRate ("100Gb/s"))); + p2ph.SetDeviceAttribute ("Mtu", UintegerValue (1500)); + p2ph.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (10))); + NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost); + Ipv4AddressHelper ipv4h; + ipv4h.SetBase ("1.0.0.0", "255.0.0.0"); + Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign (internetDevices); + // interface 0 is localhost, 1 is the p2p device + Ipv4Address remoteHostAddr = internetIpIfaces.GetAddress (1); + + Ipv4StaticRoutingHelper ipv4RoutingHelper; + Ptr remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject ()); + remoteHostStaticRouting->AddNetworkRouteTo (Ipv4Address ("7.0.0.0"), Ipv4Mask ("255.0.0.0"), 1); + + NodeContainer ueNodes; + NodeContainer enbNodes; + enbNodes.Create (numNodePairs); + ueNodes.Create (numNodePairs); + + // Install Mobility Model for eNBs and UEs + Ptr positionAlloc = CreateObject (); + for (uint16_t i = 0; i < numNodePairs; i++) + { + positionAlloc->Add (Vector (distance * i, 0, 0)); + } + MobilityHelper mobility; + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + mobility.SetPositionAllocator (positionAlloc); + mobility.Install (enbNodes); + mobility.Install (ueNodes); + + // SGW node + Ptr sgw = epcHelper->GetSgwNode (); + + // Install Mobility Model for SGW + Ptr positionAlloc2 = CreateObject (); + positionAlloc2->Add (Vector (0.0, 50.0, 0.0)); + MobilityHelper mobility2; + mobility2.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + mobility2.SetPositionAllocator (positionAlloc2); + mobility2.Install (sgw); + + // Install LTE Devices to the nodes + NetDeviceContainer enbLteDevs = lteHelper->InstallEnbDevice (enbNodes); + NetDeviceContainer ueLteDevs = lteHelper->InstallUeDevice (ueNodes); + + if (!useHelper) + { + Ipv4AddressHelper s1uIpv4AddressHelper; + + // Create networks of the S1 interfaces + s1uIpv4AddressHelper.SetBase ("10.0.0.0", "255.255.255.252"); + + for (uint16_t i = 0; i < numNodePairs; ++i) + { + Ptr enb = enbNodes.Get (i); + + // Create a point to point link between the eNB and the SGW with + // the corresponding new NetDevices on each side + PointToPointHelper p2ph; + DataRate s1uLinkDataRate = DataRate ("10Gb/s"); + uint16_t s1uLinkMtu = 2000; + Time s1uLinkDelay = Time (0); + p2ph.SetDeviceAttribute ("DataRate", DataRateValue (s1uLinkDataRate)); + p2ph.SetDeviceAttribute ("Mtu", UintegerValue (s1uLinkMtu)); + p2ph.SetChannelAttribute ("Delay", TimeValue (s1uLinkDelay)); + NetDeviceContainer sgwEnbDevices = p2ph.Install (sgw, enb); + + Ipv4InterfaceContainer sgwEnbIpIfaces = s1uIpv4AddressHelper.Assign (sgwEnbDevices); + s1uIpv4AddressHelper.NewNetwork (); + + Ipv4Address sgwS1uAddress = sgwEnbIpIfaces.GetAddress (0); + Ipv4Address enbS1uAddress = sgwEnbIpIfaces.GetAddress (1); + + // Create S1 interface between the SGW and the eNB + epcHelper->AddS1Interface (enb, enbS1uAddress, sgwS1uAddress); + } + } + + // Install the IP stack on the UEs + internet.Install (ueNodes); + Ipv4InterfaceContainer ueIpIface; + ueIpIface = epcHelper->AssignUeIpv4Address (NetDeviceContainer (ueLteDevs)); + // Assign IP address to UEs, and install applications + for (uint32_t u = 0; u < ueNodes.GetN (); ++u) + { + Ptr ueNode = ueNodes.Get (u); + // Set the default gateway for the UE + Ptr ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ueNode->GetObject ()); + ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress (), 1); + } + + // Attach one UE per eNodeB + for (uint16_t i = 0; i < numNodePairs; i++) + { + lteHelper->Attach (ueLteDevs.Get(i), enbLteDevs.Get(i)); + // side effect: the default EPS bearer will be activated + } + + + // Install and start applications on UEs and remote host + uint16_t dlPort = 1100; + uint16_t ulPort = 2000; + ApplicationContainer clientApps; + ApplicationContainer serverApps; + for (uint32_t u = 0; u < ueNodes.GetN (); ++u) + { + if (!disableDl) + { + PacketSinkHelper dlPacketSinkHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), dlPort)); + serverApps.Add (dlPacketSinkHelper.Install (ueNodes.Get (u))); + + UdpClientHelper dlClient (ueIpIface.GetAddress (u), dlPort); + dlClient.SetAttribute ("Interval", TimeValue (interPacketInterval)); + dlClient.SetAttribute ("MaxPackets", UintegerValue (1000000)); + clientApps.Add (dlClient.Install (remoteHost)); + } + + if (!disableUl) + { + ++ulPort; + PacketSinkHelper ulPacketSinkHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), ulPort)); + serverApps.Add (ulPacketSinkHelper.Install (remoteHost)); + + UdpClientHelper ulClient (remoteHostAddr, ulPort); + ulClient.SetAttribute ("Interval", TimeValue (interPacketInterval)); + ulClient.SetAttribute ("MaxPackets", UintegerValue (1000000)); + clientApps.Add (ulClient.Install (ueNodes.Get(u))); + } + } + + serverApps.Start (MilliSeconds (500)); + clientApps.Start (MilliSeconds (500)); + lteHelper->EnableTraces (); + // Uncomment to enable PCAP tracing + //p2ph.EnablePcapAll("lena-simple-epc-backhaul"); + + Simulator::Stop (simTime); + Simulator::Run (); + + /*GtkConfigStore config; + config.ConfigureAttributes();*/ + + Simulator::Destroy (); + return 0; +} diff --git a/src/lte/examples/wscript b/src/lte/examples/wscript index 594d343a3..d1e3d3381 100644 --- a/src/lte/examples/wscript +++ b/src/lte/examples/wscript @@ -43,6 +43,9 @@ def build(bld): obj = bld.create_ns3_program('lena-simple-epc', ['lte']) obj.source = 'lena-simple-epc.cc' + obj = bld.create_ns3_program('lena-simple-epc-backhaul', + ['lte']) + obj.source = 'lena-simple-epc-backhaul.cc' obj = bld.create_ns3_program('lena-deactivate-bearer', ['lte']) obj.source = 'lena-deactivate-bearer.cc' diff --git a/src/lte/helper/emu-epc-helper.cc b/src/lte/helper/emu-epc-helper.cc index 5c113acf2..f4733dc07 100644 --- a/src/lte/helper/emu-epc-helper.cc +++ b/src/lte/helper/emu-epc-helper.cc @@ -1,6 +1,6 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* - * Copyright (c) 2011-2013 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) + * Copyright (c) 2011-2019 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -20,35 +20,15 @@ * Manuel Requena */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ns3/ipv6-static-routing.h" -#include "ns3/ipv6-static-routing-helper.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include -#include + +#include "ns3/log.h" +#include "ns3/string.h" +#include "ns3/lte-enb-net-device.h" +#include "ns3/lte-enb-rrc.h" +#include "ns3/epc-x2.h" +#include "ns3/emu-fd-net-device-helper.h" +#include "ns3/emu-epc-helper.h" namespace ns3 { @@ -57,12 +37,30 @@ NS_LOG_COMPONENT_DEFINE ("EmuEpcHelper"); NS_OBJECT_ENSURE_REGISTERED (EmuEpcHelper); -EmuEpcHelper::EmuEpcHelper () - : m_gtpuUdpPort (2152) // fixed by the standard +EmuEpcHelper::EmuEpcHelper () + : NoBackhaulEpcHelper () { NS_LOG_FUNCTION (this); // To access the attribute value within the constructor ObjectBase::ConstructSelf (AttributeConstructionList ()); + + // Create EmuFdNetDevice for SGW + EmuFdNetDeviceHelper emu; + NS_LOG_LOGIC ("SGW device: " << m_sgwDeviceName); + emu.SetDeviceName (m_sgwDeviceName); + + Ptr sgw = GetSgwNode (); + NetDeviceContainer sgwDevices = emu.Install (sgw); + Ptr sgwDevice = sgwDevices.Get (0); + NS_LOG_LOGIC ("SGW MAC address: " << m_sgwMacAddress); + sgwDevice->SetAttribute ("Address", Mac48AddressValue (m_sgwMacAddress.c_str ())); + + // Address of the SGW: 10.0.0.1 + m_epcIpv4AddressHelper.SetBase ("10.0.0.0", "255.255.255.0", "0.0.0.1"); + m_sgwIpIfaces = m_epcIpv4AddressHelper.Assign (sgwDevices); + + // Address of the first eNB: 10.0.0.101 + m_epcIpv4AddressHelper.SetBase ("10.0.0.0", "255.255.255.0", "0.0.0.101"); } EmuEpcHelper::~EmuEpcHelper () @@ -77,23 +75,23 @@ EmuEpcHelper::GetTypeId (void) .SetParent () .SetGroupName("Lte") .AddConstructor () - .AddAttribute ("sgwDeviceName", + .AddAttribute ("SgwDeviceName", "The name of the device used for the S1-U interface of the SGW", StringValue ("veth0"), MakeStringAccessor (&EmuEpcHelper::m_sgwDeviceName), MakeStringChecker ()) - .AddAttribute ("enbDeviceName", + .AddAttribute ("EnbDeviceName", "The name of the device used for the S1-U interface of the eNB", StringValue ("veth1"), MakeStringAccessor (&EmuEpcHelper::m_enbDeviceName), MakeStringChecker ()) - .AddAttribute ("SgwMacAddress", - "MAC address used for the SGW ", + .AddAttribute ("SgwMacAddress", + "MAC address used for the SGW", StringValue ("00:00:00:59:00:aa"), MakeStringAccessor (&EmuEpcHelper::m_sgwMacAddress), MakeStringChecker ()) - .AddAttribute ("EnbMacAddressBase", - "First 5 bytes of the Enb MAC address base", + .AddAttribute ("EnbMacAddressBase", + "First 5 bytes of the eNB MAC address base", StringValue ("00:00:00:eb:00"), MakeStringAccessor (&EmuEpcHelper::m_enbMacAddressBase), MakeStringChecker ()) @@ -107,102 +105,11 @@ EmuEpcHelper::GetInstanceTypeId () const return GetTypeId (); } -void -EmuEpcHelper::DoInitialize () -{ - NS_LOG_LOGIC (this); - - // we use a /8 net for all UEs - m_uePgwAddressHelper.SetBase ("7.0.0.0", "255.0.0.0"); - - // we use a /64 IPv6 net all UEs - m_uePgwAddressHelper6.SetBase ("7777:f00d::", Ipv6Prefix (64)); - - - // create SgwPgwNode - m_sgwPgw = CreateObject (); - InternetStackHelper internet; - internet.Install (m_sgwPgw); - - // The Tun device resides in different 64 bit subnet. - // We must create an unique route to tun device for all the packets destined - // to all 64 bit IPv6 prefixes of UEs, based by the unique 48 bit network prefix of this EPC network - Ipv6StaticRoutingHelper ipv6RoutingHelper; - Ptr pgwStaticRouting = ipv6RoutingHelper.GetStaticRouting (m_sgwPgw->GetObject ()); - pgwStaticRouting->AddNetworkRouteTo ("7777:f00d::", Ipv6Prefix (64), Ipv6Address ("::"), 1, 0); - - // create S1-U socket - Ptr sgwPgwS1uSocket = Socket::CreateSocket (m_sgwPgw, TypeId::LookupByName ("ns3::UdpSocketFactory")); - int retval = sgwPgwS1uSocket->Bind (InetSocketAddress (Ipv4Address::GetAny (), m_gtpuUdpPort)); - NS_ASSERT (retval == 0); - - // create TUN device containing IPv4 address and implementing tunneling of user data over GTP-U/UDP/IP - m_tunDevice = CreateObject (); - - // allow jumbo packets - m_tunDevice->SetAttribute ("Mtu", UintegerValue (30000)); - - // yes we need this - m_tunDevice->SetAddress (Mac48Address::Allocate ()); - - m_sgwPgw->AddDevice (m_tunDevice); - NetDeviceContainer tunDeviceContainer; - tunDeviceContainer.Add (m_tunDevice); - - // the TUN device is on the same subnet as the UEs, so when a packet - // addressed to an UE IPv4 address arrives at the intenet to the WAN interface of - // the PGW it will be forwarded to the TUN device. - Ipv4InterfaceContainer tunDeviceIpv4IfContainer = AssignUeIpv4Address (tunDeviceContainer); - - // the TUN device for IPv6 address is on the different subnet as the - // UEs, it will forward the UE packets as we have inserted the route - // for all UEs at the time of assigning UE addresses - Ipv6InterfaceContainer tunDeviceIpv6IfContainer = AssignUeIpv6Address (tunDeviceContainer); - - //Set Forwarding - tunDeviceIpv6IfContainer.SetForwarding (0,true); - tunDeviceIpv6IfContainer.SetDefaultRouteInAllNodes (0); - - - // create EpcSgwPgwApplication - m_sgwPgwApp = CreateObject (m_tunDevice, sgwPgwS1uSocket); - m_sgwPgw->AddApplication (m_sgwPgwApp); - - // connect SgwPgwApplication and virtual net device for tunneling - m_tunDevice->SetSendCallback (MakeCallback (&EpcSgwPgwApplication::RecvFromTunDevice, m_sgwPgwApp)); - - - // Create MME and connect with SGW via S11 interface - m_mme = CreateObject (); - m_mme->SetS11SapSgw (m_sgwPgwApp->GetS11SapSgw ()); - m_sgwPgwApp->SetS11SapMme (m_mme->GetS11SapMme ()); - - // Create EmuFdNetDevice for SGW - EmuFdNetDeviceHelper emu; - NS_LOG_LOGIC ("SGW device: " << m_sgwDeviceName); - emu.SetDeviceName (m_sgwDeviceName); - NetDeviceContainer sgwDevices = emu.Install (m_sgwPgw); - Ptr sgwDevice = sgwDevices.Get (0); - NS_LOG_LOGIC ("MAC address of SGW: " << m_sgwMacAddress); - sgwDevice->SetAttribute ("Address", Mac48AddressValue (m_sgwMacAddress.c_str ())); - - // we use a /8 subnet so the SGW and the eNBs can talk directly to each other - m_epcIpv4AddressHelper.SetBase ("10.0.0.0", "255.255.255.0", "0.0.0.1"); - m_sgwIpIfaces = m_epcIpv4AddressHelper.Assign (sgwDevices); - m_epcIpv4AddressHelper.SetBase ("10.0.0.0", "255.0.0.0", "0.0.0.101"); - - - EpcHelper::DoInitialize (); -} - void EmuEpcHelper::DoDispose () { NS_LOG_FUNCTION (this); - m_tunDevice->SetSendCallback (MakeNullCallback, const Address&, const Address&, uint16_t> ()); - m_tunDevice = 0; - m_sgwPgwApp = 0; - m_sgwPgw->Dispose (); + NoBackhaulEpcHelper::DoDispose (); } @@ -211,88 +118,32 @@ EmuEpcHelper::AddEnb (Ptr enb, Ptr lteEnbNetDevice, uint16_t ce { NS_LOG_FUNCTION (this << enb << lteEnbNetDevice << cellId); - Initialize (); - - NS_ASSERT (enb == lteEnbNetDevice->GetNode ()); - - // add an Internet stack to the previously created eNB - InternetStackHelper internet; - internet.Install (enb); - NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB after node creation: " << enb->GetObject ()->GetNInterfaces ()); - - + NoBackhaulEpcHelper::AddEnb (enb, lteEnbNetDevice, cellId); // Create an EmuFdNetDevice for the eNB to connect with the SGW and other eNBs EmuFdNetDeviceHelper emu; + NS_LOG_LOGIC ("eNB cellId: " << cellId); NS_LOG_LOGIC ("eNB device: " << m_enbDeviceName); - emu.SetDeviceName (m_enbDeviceName); + emu.SetDeviceName (m_enbDeviceName); NetDeviceContainer enbDevices = emu.Install (enb); NS_ABORT_IF ((cellId == 0) || (cellId > 255)); std::ostringstream enbMacAddress; enbMacAddress << m_enbMacAddressBase << ":" << std::hex << std::setfill ('0') << std::setw (2) << cellId; - NS_LOG_LOGIC ("MAC address of enB with cellId " << cellId << " : " << enbMacAddress.str ()); + NS_LOG_LOGIC ("eNB MAC address: " << enbMacAddress.str ()); Ptr enbDev = enbDevices.Get (0); enbDev->SetAttribute ("Address", Mac48AddressValue (enbMacAddress.str ().c_str ())); //emu.EnablePcap ("enbDevice", enbDev); - NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB after installing emu dev: " << enb->GetObject ()->GetNInterfaces ()); + NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB after installing emu dev: " << enb->GetObject ()->GetNInterfaces ()); Ipv4InterfaceContainer enbIpIfaces = m_epcIpv4AddressHelper.Assign (enbDevices); NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB after assigning Ipv4 addr to S1 dev: " << enb->GetObject ()->GetNInterfaces ()); - + Ipv4Address enbAddress = enbIpIfaces.GetAddress (0); Ipv4Address sgwAddress = m_sgwIpIfaces.GetAddress (0); - // create S1-U socket for the ENB - Ptr enbS1uSocket = Socket::CreateSocket (enb, TypeId::LookupByName ("ns3::UdpSocketFactory")); - int retval = enbS1uSocket->Bind (InetSocketAddress (enbAddress, m_gtpuUdpPort)); - NS_ASSERT (retval == 0); - - // create LTE socket for the ENB - Ptr enbLteSocket = Socket::CreateSocket (enb, TypeId::LookupByName ("ns3::PacketSocketFactory")); - PacketSocketAddress enbLteSocketBindAddress; - enbLteSocketBindAddress.SetSingleDevice (lteEnbNetDevice->GetIfIndex ()); - enbLteSocketBindAddress.SetProtocol (Ipv4L3Protocol::PROT_NUMBER); - retval = enbLteSocket->Bind (enbLteSocketBindAddress); - NS_ASSERT (retval == 0); - PacketSocketAddress enbLteSocketConnectAddress; - enbLteSocketConnectAddress.SetPhysicalAddress (Mac48Address::GetBroadcast ()); - enbLteSocketConnectAddress.SetSingleDevice (lteEnbNetDevice->GetIfIndex ()); - enbLteSocketConnectAddress.SetProtocol (Ipv4L3Protocol::PROT_NUMBER); - retval = enbLteSocket->Connect (enbLteSocketConnectAddress); - NS_ASSERT (retval == 0); - - // create LTE socket for the ENB - Ptr enbLteSocket6 = Socket::CreateSocket (enb, TypeId::LookupByName ("ns3::PacketSocketFactory")); - PacketSocketAddress enbLteSocketBindAddress6; - enbLteSocketBindAddress6.SetSingleDevice (lteEnbNetDevice->GetIfIndex ()); - enbLteSocketBindAddress6.SetProtocol (Ipv6L3Protocol::PROT_NUMBER); - retval = enbLteSocket6->Bind (enbLteSocketBindAddress6); - NS_ASSERT (retval == 0); - PacketSocketAddress enbLteSocketConnectAddress6; - enbLteSocketConnectAddress6.SetPhysicalAddress (Mac48Address::GetBroadcast ()); - enbLteSocketConnectAddress6.SetSingleDevice (lteEnbNetDevice->GetIfIndex ()); - enbLteSocketConnectAddress6.SetProtocol (Ipv6L3Protocol::PROT_NUMBER); - retval = enbLteSocket6->Connect (enbLteSocketConnectAddress6); - NS_ASSERT (retval == 0); - - NS_LOG_INFO ("create EpcEnbApplication"); - Ptr enbApp = CreateObject (enbLteSocket, enbLteSocket6, enbS1uSocket, enbAddress, sgwAddress, cellId); - enb->AddApplication (enbApp); - NS_ASSERT (enb->GetNApplications () == 1); - NS_ASSERT_MSG (enb->GetApplication (0)->GetObject () != 0, "cannot retrieve EpcEnbApplication"); - NS_LOG_LOGIC ("enb: " << enb << ", enb->GetApplication (0): " << enb->GetApplication (0)); - - - NS_LOG_INFO ("Create EpcX2 entity"); - Ptr x2 = CreateObject (); - enb->AggregateObject (x2); - - NS_LOG_INFO ("connect S1-AP interface"); - m_mme->AddEnb (cellId, enbAddress, enbApp->GetS1apSapEnb ()); - m_sgwPgwApp->AddEnb (cellId, enbAddress, sgwAddress); - enbApp->SetS1apSapMme (m_mme->GetS1apSapMme ()); + NoBackhaulEpcHelper::AddS1Interface (enb, enbAddress, sgwAddress, cellId); } @@ -345,100 +196,4 @@ EmuEpcHelper::AddX2Interface (Ptr enb1, Ptr enb2) enb2LteDev->GetRrc ()->AddX2Neighbour (enb1LteDev->GetCellId ()); } - -void -EmuEpcHelper::AddUe (Ptr ueDevice, uint64_t imsi) -{ - NS_LOG_FUNCTION (this << imsi << ueDevice ); - - m_mme->AddUe (imsi); - m_sgwPgwApp->AddUe (imsi); - -} - - -uint8_t -EmuEpcHelper::ActivateEpsBearer (Ptr ueDevice, uint64_t imsi, Ptr tft, EpsBearer bearer) -{ - NS_LOG_FUNCTION (this << ueDevice << imsi); - - // we now retrieve the IPv4/IPv6 address of the UE and notify it to the SGW; - // we couldn't do it before since address assignment is triggered by - // the user simulation program, rather than done by the EPC - Ptr ueNode = ueDevice->GetNode (); - Ptr ueIpv4 = ueNode->GetObject (); - Ptr ueIpv6 = ueNode->GetObject (); - NS_ASSERT_MSG (ueIpv4 != 0 || ueIpv6 != 0, "UEs need to have IPv4/IPv6 installed before EPS bearers can be activated"); - - if (ueIpv4) - { - int32_t interface = ueIpv4->GetInterfaceForDevice (ueDevice); - if (interface >= 0 && ueIpv4->GetNAddresses (interface) == 1) - { - Ipv4Address ueAddr = ueIpv4->GetAddress (interface, 0).GetLocal (); - NS_LOG_LOGIC (" UE IPv4 address: " << ueAddr); - m_sgwPgwApp->SetUeAddress (imsi, ueAddr); - } - } - if (ueIpv6) - { - int32_t interface6 = ueIpv6->GetInterfaceForDevice (ueDevice); - if (interface6 >= 0 && ueIpv6->GetNAddresses (interface6) == 2) - { - Ipv6Address ueAddr6 = ueIpv6->GetAddress (interface6, 1).GetAddress (); - NS_LOG_LOGIC (" UE IPv6 address: " << ueAddr6); - m_sgwPgwApp->SetUeAddress6 (imsi, ueAddr6); - } - } - - uint8_t bearerId = m_mme->AddBearer (imsi, tft, bearer); - Ptr ueLteDevice = ueDevice->GetObject (); - if (ueLteDevice) - { - Simulator::ScheduleNow (&EpcUeNas::ActivateEpsBearer, ueLteDevice->GetNas (), bearer, tft); - } - return bearerId; -} - - -Ptr -EmuEpcHelper::GetPgwNode () const -{ - return m_sgwPgw; -} - - -Ipv4InterfaceContainer -EmuEpcHelper::AssignUeIpv4Address (NetDeviceContainer ueDevices) -{ - return m_uePgwAddressHelper.Assign (ueDevices); -} - -Ipv6InterfaceContainer -EmuEpcHelper::AssignUeIpv6Address (NetDeviceContainer ueDevices) -{ - for (NetDeviceContainer::Iterator iter = ueDevices.Begin (); - iter != ueDevices.End (); - iter ++) - { - Ptr icmpv6 = (*iter)->GetNode ()->GetObject (); - icmpv6->SetAttribute ("DAD", BooleanValue (false)); - } - return m_uePgwAddressHelper6.Assign (ueDevices); -} - -Ipv4Address -EmuEpcHelper::GetUeDefaultGatewayAddress () -{ - // return the address of the tun device - return m_sgwPgw->GetObject ()->GetAddress (1, 0).GetLocal (); -} - -Ipv6Address -EmuEpcHelper::GetUeDefaultGatewayAddress6 () -{ - // return the address of the tun device 6 - return m_sgwPgw->GetObject ()->GetAddress (1, 1).GetAddress (); -} - } // namespace ns3 diff --git a/src/lte/helper/emu-epc-helper.h b/src/lte/helper/emu-epc-helper.h index 267dd737a..916853d89 100644 --- a/src/lte/helper/emu-epc-helper.h +++ b/src/lte/helper/emu-epc-helper.h @@ -1,6 +1,6 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* - * Copyright (c) 2011-2013 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) + * Copyright (c) 2011-2019 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -23,23 +23,10 @@ #ifndef EMU_EPC_HELPER_H #define EMU_EPC_HELPER_H -#include -#include -#include -#include -#include -#include -#include +#include "ns3/no-backhaul-epc-helper.h" namespace ns3 { -class Node; -class NetDevice; -class VirtualNetDevice; -class EpcSgwPgwApplication; -class EpcX2; -class EpcMme; - /** * \ingroup lte * @@ -51,20 +38,19 @@ class EpcMme; * EmuFdNetDevice; in particular, one device is used to send all the * traffic related to these interfaces. */ -class EmuEpcHelper : public EpcHelper +class EmuEpcHelper : public NoBackhaulEpcHelper { public: - - /** + /** * Constructor */ EmuEpcHelper (); - /** + /** * Destructor - */ + */ virtual ~EmuEpcHelper (); - + // inherited from Object /** * Register this type. @@ -72,71 +58,21 @@ public: */ static TypeId GetTypeId (void); TypeId GetInstanceTypeId () const; - virtual void DoInitialize (); virtual void DoDispose (); // inherited from EpcHelper virtual void AddEnb (Ptr enbNode, Ptr lteEnbNetDevice, uint16_t cellId); - virtual void AddUe (Ptr ueLteDevice, uint64_t imsi); virtual void AddX2Interface (Ptr enbNode1, Ptr enbNode2); - virtual uint8_t ActivateEpsBearer (Ptr ueLteDevice, uint64_t imsi, Ptr tft, EpsBearer bearer); - virtual Ptr GetPgwNode () const; - virtual Ipv4InterfaceContainer AssignUeIpv4Address (NetDeviceContainer ueDevices); - virtual Ipv6InterfaceContainer AssignUeIpv6Address (NetDeviceContainer ueDevices); - virtual Ipv4Address GetUeDefaultGatewayAddress (); - virtual Ipv6Address GetUeDefaultGatewayAddress6 (); - private: - /** - * helper to assign IPv4 addresses to UE devices as well as to the TUN device of the SGW/PGW + /** + * helper to assign addresses to S1-U NetDevices */ - Ipv4AddressHelper m_uePgwAddressHelper; - - /** - * helper to assign IPv6 addresses to UE devices as well as to the TUN device of the SGW/PGW - */ - Ipv6AddressHelper m_uePgwAddressHelper6; + Ipv4AddressHelper m_epcIpv4AddressHelper; /** - * SGW-PGW network element - */ - Ptr m_sgwPgw; - - /** - * SGW-PGW application - */ - Ptr m_sgwPgwApp; - - /** - * TUN device containing IPv4 address and implementing tunneling of user data over GTP-U/UDP/IP - */ - Ptr m_tunDevice; - - /** - * MME network element - */ - Ptr m_mme; - - /** - * helper to assign addresses to S1-U NetDevices - */ - Ipv4AddressHelper m_epcIpv4AddressHelper; - - /** - * UDP port where the GTP-U Socket is bound, fixed by the standard as 2152 - */ - uint16_t m_gtpuUdpPort; - - /** - * Map storing for each IMSI the corresponding eNB NetDevice - * - */ - std::map > m_imsiEnbDeviceMap; - - /** - * Container for Ipv4Interfaces of the SGW/PGW + * Container for Ipv4Interfaces of the SGW */ Ipv4InterfaceContainer m_sgwIpIfaces; @@ -159,12 +95,8 @@ private: * First 5 bytes of the Enb MAC address base */ std::string m_enbMacAddressBase; - }; - - - } // namespace ns3 #endif // EMU_EPC_HELPER_H diff --git a/src/lte/helper/epc-helper.h b/src/lte/helper/epc-helper.h index a75b626a1..6efbec2e5 100644 --- a/src/lte/helper/epc-helper.h +++ b/src/lte/helper/epc-helper.h @@ -97,6 +97,17 @@ public: */ virtual void AddX2Interface (Ptr enbNode1, Ptr enbNode2) = 0; + /** + * Add an S1 interface between an eNB and a SGW + * + * \param enb eNB peer of the S1 interface + * \param enbAddress eNB IPv4 address of the S1 interface + * \param sgwAddress SGW IPv4 address of the S1 interface + * \param cellId cellId of the eNB + */ + virtual void AddS1Interface (Ptr enb, Ipv4Address enbAddress, Ipv4Address sgwAddress, uint16_t cellId = 0) = 0; + + /** * Activate an EPS bearer, setting up the corresponding S1-U tunnel. * @@ -113,11 +124,18 @@ public: /** + * Get the SGW node + * + * \return a pointer to the SGW + */ + virtual Ptr GetSgwNode () const = 0; + + + /** + * Get the PGW node * - * \return a pointer to the node implementing PGW - * functionality. Note that in this particular implementation this - * node will also hold the SGW functionality. The primary use - * intended for this method is to allow the user to configure the Gi + * \return a pointer to the PGW node + * The primary use intended for this method is to allow the user to configure the SGi * interface of the PGW, i.e., to connect the PGW to the internet. */ virtual Ptr GetPgwNode () const = 0; diff --git a/src/lte/helper/no-backhaul-epc-helper.cc b/src/lte/helper/no-backhaul-epc-helper.cc new file mode 100644 index 000000000..adc9bfc23 --- /dev/null +++ b/src/lte/helper/no-backhaul-epc-helper.cc @@ -0,0 +1,570 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2019 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Manuel Requena + * (based on the original point-to-point-epc-helper.cc) + */ + +#include "ns3/boolean.h" +#include "ns3/string.h" +#include "ns3/log.h" +#include "ns3/packet-socket-address.h" +#include "ns3/point-to-point-helper.h" +#include "ns3/internet-stack-helper.h" +#include "ns3/ipv6-static-routing-helper.h" +#include "ns3/icmpv6-l4-protocol.h" +#include "ns3/epc-enb-application.h" +#include "ns3/epc-pgw-application.h" +#include "ns3/epc-sgw-application.h" +#include "ns3/epc-mme-application.h" +#include "ns3/epc-x2.h" +#include "ns3/lte-enb-rrc.h" +#include "ns3/epc-ue-nas.h" +#include "ns3/lte-enb-net-device.h" +#include "ns3/lte-ue-net-device.h" + +#include "ns3/no-backhaul-epc-helper.h" + +namespace ns3 { + +NS_LOG_COMPONENT_DEFINE ("NoBackhaulEpcHelper"); + +NS_OBJECT_ENSURE_REGISTERED (NoBackhaulEpcHelper); + + +NoBackhaulEpcHelper::NoBackhaulEpcHelper () + : m_gtpuUdpPort (2152), // fixed by the standard + m_s11LinkDataRate (DataRate ("10Gb/s")), + m_s11LinkDelay (Seconds (0)), + m_s11LinkMtu (3000), + m_gtpcUdpPort (2123), // fixed by the standard + m_s5LinkDataRate (DataRate ("10Gb/s")), + m_s5LinkDelay (Seconds (0)), + m_s5LinkMtu (3000) +{ + NS_LOG_FUNCTION (this); + // To access the attribute value within the constructor + ObjectBase::ConstructSelf (AttributeConstructionList ()); + + int retval; + + // since we use point-to-point links for links between the core network nodes, + // we use a /30 subnet which can hold exactly two addresses + // (remember that net broadcast and null address are not valid) + m_x2Ipv4AddressHelper.SetBase ("12.0.0.0", "255.255.255.252"); + m_s11Ipv4AddressHelper.SetBase ("13.0.0.0", "255.255.255.252"); + m_s5Ipv4AddressHelper.SetBase ("14.0.0.0", "255.255.255.252"); + + // we use a /8 net for all UEs + m_uePgwAddressHelper.SetBase ("7.0.0.0", "255.0.0.0"); + + // we use a /64 IPv6 net all UEs + m_uePgwAddressHelper6.SetBase ("7777:f00d::", Ipv6Prefix (64)); + + // Create PGW, SGW and MME nodes + m_pgw = CreateObject (); + m_sgw = CreateObject (); + m_mme = CreateObject (); + InternetStackHelper internet; + internet.Install (m_pgw); + internet.Install (m_sgw); + internet.Install (m_mme); + + // The Tun device resides in different 64 bit subnet. + // We must create an unique route to tun device for all the packets destined + // to all 64 bit IPv6 prefixes of UEs, based by the unique 48 bit network prefix of this EPC network + Ipv6StaticRoutingHelper ipv6RoutingHelper; + Ptr pgwStaticRouting = ipv6RoutingHelper.GetStaticRouting (m_pgw->GetObject ()); + pgwStaticRouting->AddNetworkRouteTo ("7777:f00d::", Ipv6Prefix (64), Ipv6Address ("::"), 1, 0); + + // create TUN device implementing tunneling of user data over GTP-U/UDP/IP in the PGW + m_tunDevice = CreateObject (); + + // allow jumbo packets + m_tunDevice->SetAttribute ("Mtu", UintegerValue (30000)); + + // yes we need this + m_tunDevice->SetAddress (Mac48Address::Allocate ()); + + m_pgw->AddDevice (m_tunDevice); + NetDeviceContainer tunDeviceContainer; + tunDeviceContainer.Add (m_tunDevice); + // the TUN device is on the same subnet as the UEs, so when a packet + // addressed to an UE arrives at the intenet to the WAN interface of + // the PGW it will be forwarded to the TUN device. + Ipv4InterfaceContainer tunDeviceIpv4IfContainer = AssignUeIpv4Address (tunDeviceContainer); + + + // the TUN device for IPv6 address is on the different subnet as the + // UEs, it will forward the UE packets as we have inserted the route + // for all UEs at the time of assigning UE addresses + Ipv6InterfaceContainer tunDeviceIpv6IfContainer = AssignUeIpv6Address (tunDeviceContainer); + + + //Set Forwarding of the IPv6 interface + tunDeviceIpv6IfContainer.SetForwarding (0,true); + tunDeviceIpv6IfContainer.SetDefaultRouteInAllNodes (0); + + // Create S5 link between PGW and SGW + PointToPointHelper p2ph; + p2ph.SetDeviceAttribute ("DataRate", DataRateValue (m_s5LinkDataRate)); + p2ph.SetDeviceAttribute ("Mtu", UintegerValue (m_s5LinkMtu)); + p2ph.SetChannelAttribute ("Delay", TimeValue (m_s5LinkDelay)); + NetDeviceContainer pgwSgwDevices = p2ph.Install (m_pgw, m_sgw); + NS_LOG_LOGIC ("IPv4 ifaces of the PGW after installing p2p dev: " << m_pgw->GetObject ()->GetNInterfaces ()); + NS_LOG_LOGIC ("IPv4 ifaces of the SGW after installing p2p dev: " << m_sgw->GetObject ()->GetNInterfaces ()); + Ptr pgwDev = pgwSgwDevices.Get (0); + Ptr sgwDev = pgwSgwDevices.Get (1); + m_s5Ipv4AddressHelper.NewNetwork (); + Ipv4InterfaceContainer pgwSgwIpIfaces = m_s5Ipv4AddressHelper.Assign (pgwSgwDevices); + NS_LOG_LOGIC ("IPv4 ifaces of the PGW after assigning Ipv4 addr to S5 dev: " << m_pgw->GetObject ()->GetNInterfaces ()); + NS_LOG_LOGIC ("IPv4 ifaces of the SGW after assigning Ipv4 addr to S5 dev: " << m_sgw->GetObject ()->GetNInterfaces ()); + + Ipv4Address pgwS5Address = pgwSgwIpIfaces.GetAddress (0); + Ipv4Address sgwS5Address = pgwSgwIpIfaces.GetAddress (1); + + // Create S5-U socket in the PGW + Ptr pgwS5uSocket = Socket::CreateSocket (m_pgw, TypeId::LookupByName ("ns3::UdpSocketFactory")); + retval = pgwS5uSocket->Bind (InetSocketAddress (pgwS5Address, m_gtpuUdpPort)); + NS_ASSERT (retval == 0); + + // Create S5-C socket in the PGW + Ptr pgwS5cSocket = Socket::CreateSocket (m_pgw, TypeId::LookupByName ("ns3::UdpSocketFactory")); + retval = pgwS5cSocket->Bind (InetSocketAddress (pgwS5Address, m_gtpcUdpPort)); + NS_ASSERT (retval == 0); + + // Create EpcPgwApplication + m_pgwApp = CreateObject (m_tunDevice, pgwS5Address, pgwS5uSocket, pgwS5cSocket); + m_pgw->AddApplication (m_pgwApp); + + // Connect EpcPgwApplication and virtual net device for tunneling + m_tunDevice->SetSendCallback (MakeCallback (&EpcPgwApplication::RecvFromTunDevice, m_pgwApp)); + + + // Create S5-U socket in the SGW + Ptr sgwS5uSocket = Socket::CreateSocket (m_sgw, TypeId::LookupByName ("ns3::UdpSocketFactory")); + retval = sgwS5uSocket->Bind (InetSocketAddress (sgwS5Address, m_gtpuUdpPort)); + NS_ASSERT (retval == 0); + + // Create S5-C socket in the SGW + Ptr sgwS5cSocket = Socket::CreateSocket (m_sgw, TypeId::LookupByName ("ns3::UdpSocketFactory")); + retval = sgwS5cSocket->Bind (InetSocketAddress (sgwS5Address, m_gtpcUdpPort)); + NS_ASSERT (retval == 0); + + // Create S1-U socket in the SGW + Ptr sgwS1uSocket = Socket::CreateSocket (m_sgw, TypeId::LookupByName ("ns3::UdpSocketFactory")); + retval = sgwS1uSocket->Bind (InetSocketAddress (Ipv4Address::GetAny (), m_gtpuUdpPort)); + NS_ASSERT (retval == 0); + + // Create EpcSgwApplication + m_sgwApp = CreateObject (sgwS1uSocket, sgwS5Address, sgwS5uSocket, sgwS5cSocket); + m_sgw->AddApplication (m_sgwApp); + m_sgwApp->AddPgw (pgwS5Address); + m_pgwApp->AddSgw (sgwS5Address); + + + // Create S11 link between MME and SGW + PointToPointHelper s11P2ph; + s11P2ph.SetDeviceAttribute ("DataRate", DataRateValue (m_s11LinkDataRate)); + s11P2ph.SetDeviceAttribute ("Mtu", UintegerValue (m_s11LinkMtu)); + s11P2ph.SetChannelAttribute ("Delay", TimeValue (m_s11LinkDelay)); + NetDeviceContainer mmeSgwDevices = s11P2ph.Install (m_mme, m_sgw); + NS_LOG_LOGIC ("MME's IPv4 ifaces after installing p2p dev: " << m_mme->GetObject ()->GetNInterfaces ()); + NS_LOG_LOGIC ("SGW's IPv4 ifaces after installing p2p dev: " << m_sgw->GetObject ()->GetNInterfaces ()); + Ptr mmeDev = mmeSgwDevices.Get (0); + Ptr sgwS11Dev = mmeSgwDevices.Get (1); + m_s11Ipv4AddressHelper.NewNetwork (); + Ipv4InterfaceContainer mmeSgwIpIfaces = m_s11Ipv4AddressHelper.Assign (mmeSgwDevices); + NS_LOG_LOGIC ("MME's IPv4 ifaces after assigning Ipv4 addr to S11 dev: " << m_mme->GetObject ()->GetNInterfaces ()); + NS_LOG_LOGIC ("SGW's IPv4 ifaces after assigning Ipv4 addr to S11 dev: " << m_sgw->GetObject ()->GetNInterfaces ()); + + Ipv4Address mmeS11Address = mmeSgwIpIfaces.GetAddress (0); + Ipv4Address sgwS11Address = mmeSgwIpIfaces.GetAddress (1); + + // Create S11 socket in the MME + Ptr mmeS11Socket = Socket::CreateSocket (m_mme, TypeId::LookupByName ("ns3::UdpSocketFactory")); + retval = mmeS11Socket->Bind (InetSocketAddress (mmeS11Address, m_gtpcUdpPort)); + NS_ASSERT (retval == 0); + + // Create S11 socket in the SGW + Ptr sgwS11Socket = Socket::CreateSocket (m_sgw, TypeId::LookupByName ("ns3::UdpSocketFactory")); + retval = sgwS11Socket->Bind (InetSocketAddress (sgwS11Address, m_gtpcUdpPort)); + NS_ASSERT (retval == 0); + + + // Create MME Application and connect with SGW via S11 interface + m_mmeApp = CreateObject (); + m_mme->AddApplication (m_mmeApp); + m_mmeApp->AddSgw (sgwS11Address, mmeS11Address, mmeS11Socket); + m_sgwApp->AddMme (mmeS11Address, sgwS11Socket); +} + +NoBackhaulEpcHelper::~NoBackhaulEpcHelper () +{ + NS_LOG_FUNCTION (this); +} + +TypeId +NoBackhaulEpcHelper::GetTypeId (void) +{ + NS_LOG_FUNCTION_NOARGS (); + static TypeId tid = TypeId ("ns3::NoBackhaulEpcHelper") + .SetParent () + .SetGroupName("Lte") + .AddConstructor () + .AddAttribute ("S5LinkDataRate", + "The data rate to be used for the next S5 link to be created", + DataRateValue (DataRate ("10Gb/s")), + MakeDataRateAccessor (&NoBackhaulEpcHelper::m_s5LinkDataRate), + MakeDataRateChecker ()) + .AddAttribute ("S5LinkDelay", + "The delay to be used for the next S5 link to be created", + TimeValue (Seconds (0)), + MakeTimeAccessor (&NoBackhaulEpcHelper::m_s5LinkDelay), + MakeTimeChecker ()) + .AddAttribute ("S5LinkMtu", + "The MTU of the next S5 link to be created", + UintegerValue (2000), + MakeUintegerAccessor (&NoBackhaulEpcHelper::m_s5LinkMtu), + MakeUintegerChecker ()) + .AddAttribute ("S11LinkDataRate", + "The data rate to be used for the next S11 link to be created", + DataRateValue (DataRate ("10Gb/s")), + MakeDataRateAccessor (&NoBackhaulEpcHelper::m_s11LinkDataRate), + MakeDataRateChecker ()) + .AddAttribute ("S11LinkDelay", + "The delay to be used for the next S11 link to be created", + TimeValue (Seconds (0)), + MakeTimeAccessor (&NoBackhaulEpcHelper::m_s11LinkDelay), + MakeTimeChecker ()) + .AddAttribute ("S11LinkMtu", + "The MTU of the next S11 link to be created.", + UintegerValue (2000), + MakeUintegerAccessor (&NoBackhaulEpcHelper::m_s11LinkMtu), + MakeUintegerChecker ()) + .AddAttribute ("X2LinkDataRate", + "The data rate to be used for the next X2 link to be created", + DataRateValue (DataRate ("10Gb/s")), + MakeDataRateAccessor (&NoBackhaulEpcHelper::m_x2LinkDataRate), + MakeDataRateChecker ()) + .AddAttribute ("X2LinkDelay", + "The delay to be used for the next X2 link to be created", + TimeValue (Seconds (0)), + MakeTimeAccessor (&NoBackhaulEpcHelper::m_x2LinkDelay), + MakeTimeChecker ()) + .AddAttribute ("X2LinkMtu", + "The MTU of the next X2 link to be created. Note that, because of some big X2 messages, you need a big MTU.", + UintegerValue (3000), + MakeUintegerAccessor (&NoBackhaulEpcHelper::m_x2LinkMtu), + MakeUintegerChecker ()) + .AddAttribute ("X2LinkPcapPrefix", + "Prefix for Pcap generated by X2 link", + StringValue ("x2"), + MakeStringAccessor (&NoBackhaulEpcHelper::m_x2LinkPcapPrefix), + MakeStringChecker ()) + .AddAttribute ("X2LinkEnablePcap", + "Enable Pcap for X2 link", + BooleanValue (false), + MakeBooleanAccessor (&NoBackhaulEpcHelper::m_x2LinkEnablePcap), + MakeBooleanChecker ()) + ; + return tid; +} + +TypeId +NoBackhaulEpcHelper::GetInstanceTypeId () const +{ + return GetTypeId (); +} + +void +NoBackhaulEpcHelper::DoDispose () +{ + NS_LOG_FUNCTION (this); + m_tunDevice->SetSendCallback (MakeNullCallback, const Address&, const Address&, uint16_t> ()); + m_tunDevice = 0; + m_sgwApp = 0; + m_sgw->Dispose (); + m_pgwApp = 0; + m_pgw->Dispose (); + m_mmeApp = 0; + m_mme->Dispose (); +} + + +void +NoBackhaulEpcHelper::AddEnb (Ptr enb, Ptr lteEnbNetDevice, uint16_t cellId) +{ + NS_LOG_FUNCTION (this << enb << lteEnbNetDevice << cellId); + NS_ASSERT (enb == lteEnbNetDevice->GetNode ()); + + int retval; + + // add an IPv4 stack to the previously created eNB + InternetStackHelper internet; + internet.Install (enb); + NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB after node creation: " << enb->GetObject ()->GetNInterfaces ()); + + // create LTE socket for the ENB + Ptr enbLteSocket = Socket::CreateSocket (enb, TypeId::LookupByName ("ns3::PacketSocketFactory")); + PacketSocketAddress enbLteSocketBindAddress; + enbLteSocketBindAddress.SetSingleDevice (lteEnbNetDevice->GetIfIndex ()); + enbLteSocketBindAddress.SetProtocol (Ipv4L3Protocol::PROT_NUMBER); + retval = enbLteSocket->Bind (enbLteSocketBindAddress); + NS_ASSERT (retval == 0); + PacketSocketAddress enbLteSocketConnectAddress; + enbLteSocketConnectAddress.SetPhysicalAddress (Mac48Address::GetBroadcast ()); + enbLteSocketConnectAddress.SetSingleDevice (lteEnbNetDevice->GetIfIndex ()); + enbLteSocketConnectAddress.SetProtocol (Ipv4L3Protocol::PROT_NUMBER); + retval = enbLteSocket->Connect (enbLteSocketConnectAddress); + NS_ASSERT (retval == 0); + + // create LTE socket for the ENB + Ptr enbLteSocket6 = Socket::CreateSocket (enb, TypeId::LookupByName ("ns3::PacketSocketFactory")); + PacketSocketAddress enbLteSocketBindAddress6; + enbLteSocketBindAddress6.SetSingleDevice (lteEnbNetDevice->GetIfIndex ()); + enbLteSocketBindAddress6.SetProtocol (Ipv6L3Protocol::PROT_NUMBER); + retval = enbLteSocket6->Bind (enbLteSocketBindAddress6); + NS_ASSERT (retval == 0); + PacketSocketAddress enbLteSocketConnectAddress6; + enbLteSocketConnectAddress6.SetPhysicalAddress (Mac48Address::GetBroadcast ()); + enbLteSocketConnectAddress6.SetSingleDevice (lteEnbNetDevice->GetIfIndex ()); + enbLteSocketConnectAddress6.SetProtocol (Ipv6L3Protocol::PROT_NUMBER); + retval = enbLteSocket6->Connect (enbLteSocketConnectAddress6); + NS_ASSERT (retval == 0); + + NS_LOG_INFO ("Create EpcEnbApplication"); + Ptr enbApp = CreateObject (enbLteSocket, enbLteSocket6, cellId); + enb->AddApplication (enbApp); + NS_ASSERT (enb->GetNApplications () == 1); + NS_ASSERT_MSG (enb->GetApplication (0)->GetObject () != 0, "cannot retrieve EpcEnbApplication"); + NS_LOG_LOGIC ("enb: " << enb << ", enb->GetApplication (0): " << enb->GetApplication (0)); + + NS_LOG_INFO ("Create EpcX2 entity"); + Ptr x2 = CreateObject (); + enb->AggregateObject (x2); +} + + +void +NoBackhaulEpcHelper::AddX2Interface (Ptr enb1, Ptr enb2) +{ + NS_LOG_FUNCTION (this << enb1 << enb2); + + // Create a point to point link between the two eNBs with + // the corresponding new NetDevices on each side + PointToPointHelper p2ph; + p2ph.SetDeviceAttribute ("DataRate", DataRateValue (m_x2LinkDataRate)); + p2ph.SetDeviceAttribute ("Mtu", UintegerValue (m_x2LinkMtu)); + p2ph.SetChannelAttribute ("Delay", TimeValue (m_x2LinkDelay)); + NetDeviceContainer enbDevices = p2ph.Install (enb1, enb2); + NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB #1 after installing p2p dev: " << enb1->GetObject ()->GetNInterfaces ()); + NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB #2 after installing p2p dev: " << enb2->GetObject ()->GetNInterfaces ()); + + if (m_x2LinkEnablePcap) + { + p2ph.EnablePcapAll (m_x2LinkPcapPrefix); + } + + m_x2Ipv4AddressHelper.NewNetwork (); + Ipv4InterfaceContainer enbIpIfaces = m_x2Ipv4AddressHelper.Assign (enbDevices); + NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB #1 after assigning Ipv4 addr to X2 dev: " << enb1->GetObject ()->GetNInterfaces ()); + NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB #2 after assigning Ipv4 addr to X2 dev: " << enb2->GetObject ()->GetNInterfaces ()); + + Ipv4Address enb1X2Address = enbIpIfaces.GetAddress (0); + Ipv4Address enb2X2Address = enbIpIfaces.GetAddress (1); + + // Add X2 interface to both eNBs' X2 entities + Ptr enb1X2 = enb1->GetObject (); + Ptr enb2X2 = enb2->GetObject (); + + Ptr enb1LteDev = enb1->GetDevice (0); + Ptr enb2LteDev = enb2->GetDevice (0); + + DoAddX2Interface (enb1X2, enb1LteDev, enb1X2Address, enb2X2, enb2LteDev, enb2X2Address); +} + +void +NoBackhaulEpcHelper::DoAddX2Interface (const Ptr &enb1X2, const Ptr &enb1LteDev, + const Ipv4Address &enb1X2Address, + const Ptr &enb2X2, const Ptr &enb2LteDev, + const Ipv4Address &enb2X2Address) const +{ + NS_LOG_FUNCTION (this); + + Ptr enb1LteDevice = enb1LteDev->GetObject (); + Ptr enb2LteDevice = enb2LteDev->GetObject (); + + NS_ABORT_MSG_IF (enb1LteDevice == nullptr , "Unable to find LteEnbNetDevice for the first eNB"); + NS_ABORT_MSG_IF (enb2LteDevice == nullptr , "Unable to find LteEnbNetDevice for the second eNB"); + + uint16_t enb1CellId = enb1LteDevice->GetCellId (); + uint16_t enb2CellId = enb2LteDevice->GetCellId (); + + NS_LOG_LOGIC ("LteEnbNetDevice #1 = " << enb1LteDev << " - CellId = " << enb1CellId); + NS_LOG_LOGIC ("LteEnbNetDevice #2 = " << enb2LteDev << " - CellId = " << enb2CellId); + + enb1X2->AddX2Interface (enb1CellId, enb1X2Address, enb2CellId, enb2X2Address); + enb2X2->AddX2Interface (enb2CellId, enb2X2Address, enb1CellId, enb1X2Address); + + enb1LteDevice->GetRrc ()->AddX2Neighbour (enb2CellId); + enb2LteDevice->GetRrc ()->AddX2Neighbour (enb1CellId); +} + + +void +NoBackhaulEpcHelper::AddUe (Ptr ueDevice, uint64_t imsi) +{ + NS_LOG_FUNCTION (this << imsi << ueDevice); + + m_mmeApp->AddUe (imsi); + m_pgwApp->AddUe (imsi); +} + +uint8_t +NoBackhaulEpcHelper::ActivateEpsBearer (Ptr ueDevice, uint64_t imsi, + Ptr tft, EpsBearer bearer) +{ + NS_LOG_FUNCTION (this << ueDevice << imsi); + + // we now retrieve the IPv4/IPv6 address of the UE and notify it to the SGW; + // we couldn't do it before since address assignment is triggered by + // the user simulation program, rather than done by the EPC + Ptr ueNode = ueDevice->GetNode (); + Ptr ueIpv4 = ueNode->GetObject (); + Ptr ueIpv6 = ueNode->GetObject (); + NS_ASSERT_MSG (ueIpv4 != 0 || ueIpv6 != 0, "UEs need to have IPv4/IPv6 installed before EPS bearers can be activated"); + + if (ueIpv4) + { + int32_t interface = ueIpv4->GetInterfaceForDevice (ueDevice); + if (interface >= 0 && ueIpv4->GetNAddresses (interface) == 1) + { + Ipv4Address ueAddr = ueIpv4->GetAddress (interface, 0).GetLocal (); + NS_LOG_LOGIC (" UE IPv4 address: " << ueAddr); + m_pgwApp->SetUeAddress (imsi, ueAddr); + } + } + if (ueIpv6) + { + int32_t interface6 = ueIpv6->GetInterfaceForDevice (ueDevice); + if (interface6 >= 0 && ueIpv6->GetNAddresses (interface6) == 2) + { + Ipv6Address ueAddr6 = ueIpv6->GetAddress (interface6, 1).GetAddress (); + NS_LOG_LOGIC (" UE IPv6 address: " << ueAddr6); + m_pgwApp->SetUeAddress6 (imsi, ueAddr6); + } + } + uint8_t bearerId = m_mmeApp->AddBearer (imsi, tft, bearer); + DoActivateEpsBearerForUe (ueDevice, tft, bearer); + + return bearerId; +} + +void +NoBackhaulEpcHelper::DoActivateEpsBearerForUe (const Ptr &ueDevice, + const Ptr &tft, + const EpsBearer &bearer) const +{ + NS_LOG_FUNCTION (this); + Ptr ueLteDevice = DynamicCast (ueDevice); + if (ueLteDevice == nullptr) + { + // You may wonder why this is not an assert. Well, take a look in epc-test-s1u-downlink + // and -uplink: we are using CSMA to simulate UEs. + NS_LOG_WARN ("Unable to find LteUeNetDevice while activating the EPS bearer"); + } + else + { + Simulator::ScheduleNow (&EpcUeNas::ActivateEpsBearer, ueLteDevice->GetNas (), bearer, tft); + } +} + +Ptr +NoBackhaulEpcHelper::GetPgwNode () const +{ + return m_pgw; +} + +Ipv4InterfaceContainer +NoBackhaulEpcHelper::AssignUeIpv4Address (NetDeviceContainer ueDevices) +{ + return m_uePgwAddressHelper.Assign (ueDevices); +} + +Ipv6InterfaceContainer +NoBackhaulEpcHelper::AssignUeIpv6Address (NetDeviceContainer ueDevices) +{ + for (NetDeviceContainer::Iterator iter = ueDevices.Begin (); + iter != ueDevices.End (); + iter ++) + { + Ptr icmpv6 = (*iter)->GetNode ()->GetObject (); + icmpv6->SetAttribute ("DAD", BooleanValue (false)); + } + return m_uePgwAddressHelper6.Assign (ueDevices); +} + +Ipv4Address +NoBackhaulEpcHelper::GetUeDefaultGatewayAddress () +{ + // return the address of the tun device + return m_pgw->GetObject ()->GetAddress (1, 0).GetLocal (); +} + +Ipv6Address +NoBackhaulEpcHelper::GetUeDefaultGatewayAddress6 () +{ + // return the address of the tun device + return m_pgw->GetObject ()->GetAddress (1, 1).GetAddress (); +} + + +Ptr +NoBackhaulEpcHelper::GetSgwNode () const +{ + return m_sgw; +} + + +void +NoBackhaulEpcHelper::AddS1Interface (Ptr enb, Ipv4Address enbAddress, Ipv4Address sgwAddress, uint16_t cellId) +{ + NS_LOG_FUNCTION (this << enb << enbAddress << sgwAddress << cellId); + + // create S1-U socket for the ENB + Ptr enbS1uSocket = Socket::CreateSocket (enb, TypeId::LookupByName ("ns3::UdpSocketFactory")); + int retval = enbS1uSocket->Bind (InetSocketAddress (enbAddress, m_gtpuUdpPort)); + NS_ASSERT (retval == 0); + + Ptr enbApp = enb->GetApplication (0)->GetObject (); + NS_ASSERT_MSG (enbApp != 0, "EpcEnbApplication not available"); + enbApp->AddS1Interface (enbS1uSocket, enbAddress, sgwAddress); + + NS_LOG_INFO ("Connect S1-AP interface"); + if (cellId == 0) + { + Ptr enbLteDev = enb->GetDevice (0)->GetObject (); + NS_ASSERT_MSG (enbLteDev, "LteEnbNetDevice is missing"); + cellId = enbLteDev->GetCellId (); + } + m_mmeApp->AddEnb (cellId, enbAddress, enbApp->GetS1apSapEnb ()); + m_sgwApp->AddEnb (cellId, enbAddress, sgwAddress); + enbApp->SetS1apSapMme (m_mmeApp->GetS1apSapMme ()); +} + +} // namespace ns3 diff --git a/src/lte/helper/no-backhaul-epc-helper.h b/src/lte/helper/no-backhaul-epc-helper.h new file mode 100644 index 000000000..27ce32b6a --- /dev/null +++ b/src/lte/helper/no-backhaul-epc-helper.h @@ -0,0 +1,247 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2019 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Manuel Requena + * (based on the original point-to-point-epc-helper.h) + */ + +#ifndef NO_BACKHAUL_EPC_HELPER_H +#define NO_BACKHAUL_EPC_HELPER_H + +#include "ns3/epc-helper.h" + +namespace ns3 { + +class EpcSgwApplication; +class EpcPgwApplication; +class EpcMmeApplication; + +/** + * \ingroup lte + * \brief Create an EPC network with PointToPoint links between the core network nodes. + * + * This Helper will create an EPC network topology comprising of + * three nodes: SGW, PGW and MME. + * The X2-U, X2-C, S5 and S11 interfaces are realized over PointToPoint links. + * + * The S1 interface is not created. So, no backhaul network is built. + * You have to build your own backhaul network in the simulation program. + * Or you can use PointToPointEpcHelper or CsmaEpcHelper + * (instead of this NoBackhaulEpcHelper) to use reference backhaul networks. + */ +class NoBackhaulEpcHelper : public EpcHelper +{ +public: + /** + * Constructor + */ + NoBackhaulEpcHelper (); + + /** + * Destructor + */ + virtual ~NoBackhaulEpcHelper (); + + // inherited from Object + /** + * Register this type. + * \return The object TypeId. + */ + static TypeId GetTypeId (void); + TypeId GetInstanceTypeId () const; + virtual void DoDispose (); + + // inherited from EpcHelper + virtual void AddEnb (Ptr enbNode, Ptr lteEnbNetDevice, uint16_t cellId); + virtual void AddUe (Ptr ueLteDevice, uint64_t imsi); + virtual void AddX2Interface (Ptr enbNode1, Ptr enbNode2); + virtual void AddS1Interface (Ptr enb, Ipv4Address enbAddress, Ipv4Address sgwAddress, uint16_t cellId = 0); + virtual uint8_t ActivateEpsBearer (Ptr ueLteDevice, uint64_t imsi, Ptr tft, EpsBearer bearer); + virtual Ptr GetSgwNode () const; + virtual Ptr GetPgwNode () const; + virtual Ipv4InterfaceContainer AssignUeIpv4Address (NetDeviceContainer ueDevices); + virtual Ipv6InterfaceContainer AssignUeIpv6Address (NetDeviceContainer ueDevices); + virtual Ipv4Address GetUeDefaultGatewayAddress (); + virtual Ipv6Address GetUeDefaultGatewayAddress6 (); + +protected: + /** + * \brief DoAddX2Interface: Call AddX2Interface on top of the Enb device pointers + * + * \param enb1X2 EPCX2 of ENB1 + * \param enb1LteDev LTE device of ENB1 + * \param enb1X2Address Address for ENB1 + * \param enb2X2 EPCX2 of ENB2 + * \param enb2LteDev LTE device of ENB2 + * \param enb2X2Address Address for ENB2 + */ + virtual void DoAddX2Interface(const Ptr &enb1X2, const Ptr &enb1LteDev, + const Ipv4Address &enb1X2Address, + const Ptr &enb2X2, const Ptr &enb2LteDev, + const Ipv4Address &enb2X2Address) const; + + /** + * \brief DoActivateEpsBearerForUe: Schedule ActivateEpsBearer on the UE + * \param ueDevice LTE device for the UE + * \param tft TFT + * \param bearer Bearer + */ + virtual void DoActivateEpsBearerForUe (const Ptr &ueDevice, + const Ptr &tft, + const EpsBearer &bearer) const; + +private: + + /** + * helper to assign IPv4 addresses to UE devices as well as to the TUN device of the SGW/PGW + */ + Ipv4AddressHelper m_uePgwAddressHelper; + /** + * helper to assign IPv6 addresses to UE devices as well as to the TUN device of the SGW/PGW + */ + Ipv6AddressHelper m_uePgwAddressHelper6; + + /** + * PGW network element + */ + Ptr m_pgw; + + /** + * SGW network element + */ + Ptr m_sgw; + + /** + * MME network element + */ + Ptr m_mme; + + /** + * SGW application + */ + Ptr m_sgwApp; + + /** + * PGW application + */ + Ptr m_pgwApp; + + /** + * MME application + */ + Ptr m_mmeApp; + + /** + * TUN device implementing tunneling of user data over GTP-U/UDP/IP + */ + Ptr m_tunDevice; + + /** + * UDP port where the GTP-U Socket is bound, fixed by the standard as 2152 + */ + uint16_t m_gtpuUdpPort; + + /** + * Helper to assign addresses to S11 NetDevices + */ + Ipv4AddressHelper m_s11Ipv4AddressHelper; + + /** + * The data rate to be used for the next S11 link to be created + */ + DataRate m_s11LinkDataRate; + + /** + * The delay to be used for the next S11 link to be created + */ + Time m_s11LinkDelay; + + /** + * The MTU of the next S11 link to be created + */ + uint16_t m_s11LinkMtu; + + /** + * UDP port where the GTPv2-C Socket is bound, fixed by the standard as 2123 + */ + uint16_t m_gtpcUdpPort; + + /** + * S5 interfaces + */ + + /** + * Helper to assign addresses to S5 NetDevices + */ + Ipv4AddressHelper m_s5Ipv4AddressHelper; + + /** + * The data rate to be used for the next S5 link to be created + */ + DataRate m_s5LinkDataRate; + + /** + * The delay to be used for the next S5 link to be created + */ + Time m_s5LinkDelay; + + /** + * The MTU of the next S5 link to be created + */ + uint16_t m_s5LinkMtu; + + /** + * Map storing for each IMSI the corresponding eNB NetDevice + */ + std::map > m_imsiEnbDeviceMap; + + /** + * helper to assign addresses to X2 NetDevices + */ + Ipv4AddressHelper m_x2Ipv4AddressHelper; + + /** + * The data rate to be used for the next X2 link to be created + */ + DataRate m_x2LinkDataRate; + + /** + * The delay to be used for the next X2 link to be created + */ + Time m_x2LinkDelay; + + /** + * The MTU of the next X2 link to be created. Note that, + * because of some big X2 messages, you need a big MTU. + */ + uint16_t m_x2LinkMtu; + + /** + * Enable PCAP generation for X2 link + */ + bool m_x2LinkEnablePcap; + + /** + * Prefix for the PCAP file for the X2 link + */ + std::string m_x2LinkPcapPrefix; + +}; + +} // namespace ns3 + +#endif // NO_BACKHAUL_EPC_HELPER_H diff --git a/src/lte/helper/point-to-point-epc-helper.cc b/src/lte/helper/point-to-point-epc-helper.cc index 1e438780b..dde1f0761 100644 --- a/src/lte/helper/point-to-point-epc-helper.cc +++ b/src/lte/helper/point-to-point-epc-helper.cc @@ -1,6 +1,6 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* - * Copyright (c) 2011-2018 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) + * Copyright (c) 2011-2019 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -18,35 +18,15 @@ * Author: Jaume Nin * Nicola Baldo * Manuel Requena + * (most of the code refactored to no-backhaul-epc-helper.cc) */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ns3/ipv6-static-routing.h" -#include "ns3/ipv6-static-routing-helper.h" -#include -#include -#include +#include "ns3/boolean.h" +#include "ns3/string.h" +#include "ns3/log.h" +#include "ns3/point-to-point-helper.h" -#include -#include -#include -#include -#include -#include -#include -#include +#include "ns3/point-to-point-epc-helper.h" namespace ns3 { @@ -55,181 +35,18 @@ NS_LOG_COMPONENT_DEFINE ("PointToPointEpcHelper"); NS_OBJECT_ENSURE_REGISTERED (PointToPointEpcHelper); -PointToPointEpcHelper::PointToPointEpcHelper () - : m_gtpuUdpPort (2152), // fixed by the standard - m_s11LinkDataRate (DataRate ("10Gb/s")), - m_s11LinkDelay (Seconds (0)), - m_s11LinkMtu (3000), - m_gtpcUdpPort (2123), // fixed by the standard - m_s5LinkDataRate (DataRate ("10Gb/s")), - m_s5LinkDelay (Seconds (0)), - m_s5LinkMtu (3000) +PointToPointEpcHelper::PointToPointEpcHelper () + : NoBackhaulEpcHelper () { NS_LOG_FUNCTION (this); // To access the attribute value within the constructor ObjectBase::ConstructSelf (AttributeConstructionList ()); - int retval; - // since we use point-to-point links for all links, - // we use a /30 subnet which can hold exactly two addresses + // since we use point-to-point links for the backhaul links, + // we use a /30 subnet which can hold exactly two addresses // (remember that net broadcast and null address are not valid) m_s1uIpv4AddressHelper.SetBase ("10.0.0.0", "255.255.255.252"); - m_s1apIpv4AddressHelper.SetBase ("11.0.0.0", "255.255.255.252"); - m_x2Ipv4AddressHelper.SetBase ("12.0.0.0", "255.255.255.252"); - m_s11Ipv4AddressHelper.SetBase ("13.0.0.0", "255.255.255.252"); - m_s5Ipv4AddressHelper.SetBase ("14.0.0.0", "255.255.255.252"); - - // we use a /8 net for all UEs - m_uePgwAddressHelper.SetBase ("7.0.0.0", "255.0.0.0"); - - // we use a /64 IPv6 net all UEs - m_uePgwAddressHelper6.SetBase ("7777:f00d::", Ipv6Prefix (64)); - - // Create PGW, SGW and MME nodes - m_pgw = CreateObject (); - m_sgw = CreateObject (); - m_mme = CreateObject (); - InternetStackHelper internet; - internet.Install (m_pgw); - internet.Install (m_sgw); - internet.Install (m_mme); - - // The Tun device resides in different 64 bit subnet. - // We must create an unique route to tun device for all the packets destined - // to all 64 bit IPv6 prefixes of UEs, based by the unique 48 bit network prefix of this EPC network - Ipv6StaticRoutingHelper ipv6RoutingHelper; - Ptr pgwStaticRouting = ipv6RoutingHelper.GetStaticRouting (m_pgw->GetObject ()); - pgwStaticRouting->AddNetworkRouteTo ("7777:f00d::", Ipv6Prefix (64), Ipv6Address ("::"), 1, 0); - - // create TUN device implementing tunneling of user data over GTP-U/UDP/IP in the PGW - m_tunDevice = CreateObject (); - - // allow jumbo packets - m_tunDevice->SetAttribute ("Mtu", UintegerValue (30000)); - - // yes we need this - m_tunDevice->SetAddress (Mac48Address::Allocate ()); - - m_pgw->AddDevice (m_tunDevice); - NetDeviceContainer tunDeviceContainer; - tunDeviceContainer.Add (m_tunDevice); - // the TUN device is on the same subnet as the UEs, so when a packet - // addressed to an UE arrives at the intenet to the WAN interface of - // the PGW it will be forwarded to the TUN device. - Ipv4InterfaceContainer tunDeviceIpv4IfContainer = AssignUeIpv4Address (tunDeviceContainer); - - - // the TUN device for IPv6 address is on the different subnet as the - // UEs, it will forward the UE packets as we have inserted the route - // for all UEs at the time of assigning UE addresses - Ipv6InterfaceContainer tunDeviceIpv6IfContainer = AssignUeIpv6Address (tunDeviceContainer); - - - //Set Forwarding of the IPv6 interface - tunDeviceIpv6IfContainer.SetForwarding (0,true); - tunDeviceIpv6IfContainer.SetDefaultRouteInAllNodes (0); - - // Create S5 link between PGW and SGW - NodeContainer pgwSgwNodes; - pgwSgwNodes.Add (m_pgw); - pgwSgwNodes.Add (m_sgw); - PointToPointHelper p2ph; - p2ph.SetDeviceAttribute ("DataRate", DataRateValue (m_s5LinkDataRate)); - p2ph.SetDeviceAttribute ("Mtu", UintegerValue (m_s5LinkMtu)); - p2ph.SetChannelAttribute ("Delay", TimeValue (m_s5LinkDelay)); - NetDeviceContainer pgwSgwDevices = p2ph.Install (m_pgw, m_sgw); - NS_LOG_LOGIC ("IPv4 ifaces of the PGW after installing p2p dev: " << m_pgw->GetObject ()->GetNInterfaces ()); - NS_LOG_LOGIC ("IPv4 ifaces of the SGW after installing p2p dev: " << m_sgw->GetObject ()->GetNInterfaces ()); - Ptr pgwDev = pgwSgwDevices.Get (0); - Ptr sgwDev = pgwSgwDevices.Get (1); - m_s5Ipv4AddressHelper.NewNetwork (); - Ipv4InterfaceContainer pgwSgwIpIfaces = m_s5Ipv4AddressHelper.Assign (pgwSgwDevices); - NS_LOG_LOGIC ("IPv4 ifaces of the PGW after assigning Ipv4 addr to S5 dev: " << m_pgw->GetObject ()->GetNInterfaces ()); - NS_LOG_LOGIC ("IPv4 ifaces of the SGW after assigning Ipv4 addr to S5 dev: " << m_sgw->GetObject ()->GetNInterfaces ()); - - Ipv4Address pgwS5Address = pgwSgwIpIfaces.GetAddress (0); - Ipv4Address sgwS5Address = pgwSgwIpIfaces.GetAddress (1); - - // Create S5-U socket in the PGW - Ptr pgwS5uSocket = Socket::CreateSocket (m_pgw, TypeId::LookupByName ("ns3::UdpSocketFactory")); - retval = pgwS5uSocket->Bind (InetSocketAddress (pgwS5Address, m_gtpuUdpPort)); - NS_ASSERT (retval == 0); - - // Create S5-C socket in the PGW - Ptr pgwS5cSocket = Socket::CreateSocket (m_pgw, TypeId::LookupByName ("ns3::UdpSocketFactory")); - retval = pgwS5cSocket->Bind (InetSocketAddress (pgwS5Address, m_gtpcUdpPort)); - NS_ASSERT (retval == 0); - - // Create EpcPgwApplication - m_pgwApp = CreateObject (m_tunDevice, pgwS5Address, pgwS5uSocket, pgwS5cSocket); - m_pgw->AddApplication (m_pgwApp); - - // Connect EpcPgwApplication and virtual net device for tunneling - m_tunDevice->SetSendCallback (MakeCallback (&EpcPgwApplication::RecvFromTunDevice, m_pgwApp)); - - - // Create S5-U socket in the SGW - Ptr sgwS5uSocket = Socket::CreateSocket (m_sgw, TypeId::LookupByName ("ns3::UdpSocketFactory")); - retval = sgwS5uSocket->Bind (InetSocketAddress (sgwS5Address, m_gtpuUdpPort)); - NS_ASSERT (retval == 0); - - // Create S5-C socket in the SGW - Ptr sgwS5cSocket = Socket::CreateSocket (m_sgw, TypeId::LookupByName ("ns3::UdpSocketFactory")); - retval = sgwS5cSocket->Bind (InetSocketAddress (sgwS5Address, m_gtpcUdpPort)); - NS_ASSERT (retval == 0); - - // Create S1-U socket in the SGW - Ptr sgwS1uSocket = Socket::CreateSocket (m_sgw, TypeId::LookupByName ("ns3::UdpSocketFactory")); - retval = sgwS1uSocket->Bind (InetSocketAddress (Ipv4Address::GetAny (), m_gtpuUdpPort)); - NS_ASSERT (retval == 0); - - // Create EpcSgwApplication - m_sgwApp = CreateObject (sgwS1uSocket, sgwS5Address, sgwS5uSocket, sgwS5cSocket); - m_sgw->AddApplication (m_sgwApp); - m_sgwApp->AddPgw (pgwS5Address); - m_pgwApp->AddSgw (sgwS5Address); - - - // Create S11 link between MME and SGW - NodeContainer mmeSgwNodes; - mmeSgwNodes.Add (m_mme); - mmeSgwNodes.Add (m_sgw); - PointToPointHelper s11P2ph; - s11P2ph.SetDeviceAttribute ("DataRate", DataRateValue (m_s11LinkDataRate)); - s11P2ph.SetDeviceAttribute ("Mtu", UintegerValue (m_s11LinkMtu)); - s11P2ph.SetChannelAttribute ("Delay", TimeValue (m_s11LinkDelay)); - NetDeviceContainer mmeSgwDevices = s11P2ph.Install (m_mme, m_sgw); - NS_LOG_LOGIC ("MME's IPv4 ifaces after installing p2p dev: " << m_mme->GetObject ()->GetNInterfaces ()); - NS_LOG_LOGIC ("SGW's IPv4 ifaces after installing p2p dev: " << m_sgw->GetObject ()->GetNInterfaces ()); - Ptr mmeDev = mmeSgwDevices.Get (0); - Ptr sgwS11Dev = mmeSgwDevices.Get (1); - m_s11Ipv4AddressHelper.NewNetwork (); - Ipv4InterfaceContainer mmeSgwIpIfaces = m_s11Ipv4AddressHelper.Assign (mmeSgwDevices); - NS_LOG_LOGIC ("MME's IPv4 ifaces after assigning Ipv4 addr to S11 dev: " << m_mme->GetObject ()->GetNInterfaces ()); - NS_LOG_LOGIC ("SGW's IPv4 ifaces after assigning Ipv4 addr to S11 dev: " << m_sgw->GetObject ()->GetNInterfaces ()); - - Ipv4Address mmeS11Address = mmeSgwIpIfaces.GetAddress (0); - Ipv4Address sgwS11Address = mmeSgwIpIfaces.GetAddress (1); - - // Create S11 socket in the MME - Ptr mmeS11Socket = Socket::CreateSocket (m_mme, TypeId::LookupByName ("ns3::UdpSocketFactory")); - retval = mmeS11Socket->Bind (InetSocketAddress (mmeS11Address, m_gtpcUdpPort)); - NS_ASSERT (retval == 0); - - // Create S11 socket in the SGW - Ptr sgwS11Socket = Socket::CreateSocket (m_sgw, TypeId::LookupByName ("ns3::UdpSocketFactory")); - retval = sgwS11Socket->Bind (InetSocketAddress (sgwS11Address, m_gtpcUdpPort)); - NS_ASSERT (retval == 0); - - - // Create MME Application and connect with SGW via S11 interface - m_mmeApp = CreateObject (); - m_mme->AddApplication (m_mmeApp); -// // m_mmeApp->SetS11SapSgw (m_sgwApp->GetS11SapSgw ()); -// // m_sgwApp->SetS11SapMme (m_mmeApp->GetS11SapMme ()); - m_mmeApp->AddSgw (sgwS11Address, mmeS11Address, mmeS11Socket); - m_sgwApp->AddMme (mmeS11Address, sgwS11Socket); } PointToPointEpcHelper::~PointToPointEpcHelper () @@ -242,88 +59,33 @@ PointToPointEpcHelper::GetTypeId (void) { NS_LOG_FUNCTION_NOARGS (); static TypeId tid = TypeId ("ns3::PointToPointEpcHelper") - .SetParent () - .SetGroupName("Lte") + .SetParent () + .SetGroupName ("Lte") .AddConstructor () - .AddAttribute ("S1uLinkDataRate", + .AddAttribute ("S1uLinkDataRate", "The data rate to be used for the next S1-U link to be created", DataRateValue (DataRate ("10Gb/s")), MakeDataRateAccessor (&PointToPointEpcHelper::m_s1uLinkDataRate), MakeDataRateChecker ()) - .AddAttribute ("S1uLinkDelay", + .AddAttribute ("S1uLinkDelay", "The delay to be used for the next S1-U link to be created", TimeValue (Seconds (0)), MakeTimeAccessor (&PointToPointEpcHelper::m_s1uLinkDelay), MakeTimeChecker ()) - .AddAttribute ("S1uLinkMtu", + .AddAttribute ("S1uLinkMtu", "The MTU of the next S1-U link to be created. Note that, because of the additional GTP/UDP/IP tunneling overhead, you need a MTU larger than the end-to-end MTU that you want to support.", UintegerValue (2000), MakeUintegerAccessor (&PointToPointEpcHelper::m_s1uLinkMtu), MakeUintegerChecker ()) - .AddAttribute ("S5LinkDataRate", - "The data rate to be used for the next S5 link to be created", - DataRateValue (DataRate ("10Gb/s")), - MakeDataRateAccessor (&PointToPointEpcHelper::m_s5LinkDataRate), - MakeDataRateChecker ()) - .AddAttribute ("S5LinkDelay", - "The delay to be used for the next S5 link to be created", - TimeValue (Seconds (0)), - MakeTimeAccessor (&PointToPointEpcHelper::m_s5LinkDelay), - MakeTimeChecker ()) - .AddAttribute ("S5LinkMtu", - "The MTU of the next S5 link to be created", - UintegerValue (2000), - MakeUintegerAccessor (&PointToPointEpcHelper::m_s5LinkMtu), - MakeUintegerChecker ()) - .AddAttribute ("S11LinkDataRate", - "The data rate to be used for the next S11 link to be created", - DataRateValue (DataRate ("10Gb/s")), - MakeDataRateAccessor (&PointToPointEpcHelper::m_s11LinkDataRate), - MakeDataRateChecker ()) - .AddAttribute ("S11LinkDelay", - "The delay to be used for the next S11 link to be created", - TimeValue (Seconds (0)), - MakeTimeAccessor (&PointToPointEpcHelper::m_s11LinkDelay), - MakeTimeChecker ()) - .AddAttribute ("S11LinkMtu", - "The MTU of the next S11 link to be created.", - UintegerValue (2000), - MakeUintegerAccessor (&PointToPointEpcHelper::m_s11LinkMtu), - MakeUintegerChecker ()) - .AddAttribute ("X2LinkDataRate", - "The data rate to be used for the next X2 link to be created", - DataRateValue (DataRate ("10Gb/s")), - MakeDataRateAccessor (&PointToPointEpcHelper::m_x2LinkDataRate), - MakeDataRateChecker ()) - .AddAttribute ("X2LinkDelay", - "The delay to be used for the next X2 link to be created", - TimeValue (Seconds (0)), - MakeTimeAccessor (&PointToPointEpcHelper::m_x2LinkDelay), - MakeTimeChecker ()) - .AddAttribute ("X2LinkMtu", - "The MTU of the next X2 link to be created. Note that, because of some big X2 messages, you need a big MTU.", - UintegerValue (3000), - MakeUintegerAccessor (&PointToPointEpcHelper::m_x2LinkMtu), - MakeUintegerChecker ()) .AddAttribute ("S1uLinkPcapPrefix", "Prefix for Pcap generated by S1-U link", - StringValue ("s1-u"), + StringValue ("s1u"), MakeStringAccessor (&PointToPointEpcHelper::m_s1uLinkPcapPrefix), MakeStringChecker ()) - .AddAttribute ("X2LinkPcapPrefix", - "Prefix for Pcap generated by X2 link", - StringValue ("x2"), - MakeStringAccessor (&PointToPointEpcHelper::m_x2LinkPcapPrefix), - MakeStringChecker ()) - .AddAttribute ("X2LinkEnablePcap", - "Enable Pcap for X2 link", - BooleanValue (false), - MakeBooleanAccessor (&PointToPointEpcHelper::m_enablePcapOverX2), - MakeBooleanChecker ()) .AddAttribute ("S1uLinkEnablePcap", "Enable Pcap for X2 link", BooleanValue (false), - MakeBooleanAccessor (&PointToPointEpcHelper::m_enablePcapOverS1U), + MakeBooleanAccessor (&PointToPointEpcHelper::m_s1uLinkEnablePcap), MakeBooleanChecker ()) ; return tid; @@ -339,14 +101,7 @@ void PointToPointEpcHelper::DoDispose () { NS_LOG_FUNCTION (this); - m_tunDevice->SetSendCallback (MakeNullCallback, const Address&, const Address&, uint16_t> ()); - m_tunDevice = 0; - m_sgwApp = 0; - m_sgw->Dispose (); - m_pgwApp = 0; - m_pgw->Dispose (); - m_mmeApp = 0; - m_mme->Dispose (); + NoBackhaulEpcHelper::DoDispose (); } @@ -355,267 +110,32 @@ PointToPointEpcHelper::AddEnb (Ptr enb, Ptr lteEnbNetDevice, ui { NS_LOG_FUNCTION (this << enb << lteEnbNetDevice << cellId); - NS_ASSERT (enb == lteEnbNetDevice->GetNode ()); + NoBackhaulEpcHelper::AddEnb (enb, lteEnbNetDevice, cellId); - // add an IPv4 stack to the previously created eNB - InternetStackHelper internet; - internet.Install (enb); - NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB after node creation: " << enb->GetObject ()->GetNInterfaces ()); + // create a point to point link between the eNB and the SGW with + // the corresponding new NetDevices on each side + Ptr sgw = GetSgwNode (); - // create a point to point link between the new eNB and the SGW with - // the corresponding new NetDevices on each side - NodeContainer enbSgwNodes; - enbSgwNodes.Add (m_sgw); - enbSgwNodes.Add (enb); PointToPointHelper p2ph; p2ph.SetDeviceAttribute ("DataRate", DataRateValue (m_s1uLinkDataRate)); p2ph.SetDeviceAttribute ("Mtu", UintegerValue (m_s1uLinkMtu)); p2ph.SetChannelAttribute ("Delay", TimeValue (m_s1uLinkDelay)); - NetDeviceContainer enbSgwDevices = p2ph.Install (enb, m_sgw); + NetDeviceContainer enbSgwDevices = p2ph.Install (enb, sgw); NS_LOG_LOGIC ("Ipv4 ifaces of the eNB after installing p2p dev: " << enb->GetObject ()->GetNInterfaces ()); - Ptr enbDev = enbSgwDevices.Get (0); - Ptr sgwDev = enbSgwDevices.Get (1); - if (m_enablePcapOverS1U) + if (m_s1uLinkEnablePcap) { - p2ph.EnablePcapAll(m_s1uLinkPcapPrefix); + p2ph.EnablePcapAll (m_s1uLinkPcapPrefix); } m_s1uIpv4AddressHelper.NewNetwork (); Ipv4InterfaceContainer enbSgwIpIfaces = m_s1uIpv4AddressHelper.Assign (enbSgwDevices); NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB after assigning Ipv4 addr to S1 dev: " << enb->GetObject ()->GetNInterfaces ()); - + Ipv4Address enbS1uAddress = enbSgwIpIfaces.GetAddress (0); Ipv4Address sgwS1uAddress = enbSgwIpIfaces.GetAddress (1); - // create S1-U socket for the ENB - Ptr enbS1uSocket = Socket::CreateSocket (enb, TypeId::LookupByName ("ns3::UdpSocketFactory")); - int retval = enbS1uSocket->Bind (InetSocketAddress (enbS1uAddress, m_gtpuUdpPort)); - NS_ASSERT (retval == 0); - - // give PacketSocket powers to the eNB - //PacketSocketHelper packetSocket; - //packetSocket.Install (enb); - // create LTE socket for the ENB - Ptr enbLteSocket = Socket::CreateSocket (enb, TypeId::LookupByName ("ns3::PacketSocketFactory")); - PacketSocketAddress enbLteSocketBindAddress; - enbLteSocketBindAddress.SetSingleDevice (lteEnbNetDevice->GetIfIndex ()); - enbLteSocketBindAddress.SetProtocol (Ipv4L3Protocol::PROT_NUMBER); - retval = enbLteSocket->Bind (enbLteSocketBindAddress); - NS_ASSERT (retval == 0); - PacketSocketAddress enbLteSocketConnectAddress; - enbLteSocketConnectAddress.SetPhysicalAddress (Mac48Address::GetBroadcast ()); - enbLteSocketConnectAddress.SetSingleDevice (lteEnbNetDevice->GetIfIndex ()); - enbLteSocketConnectAddress.SetProtocol (Ipv4L3Protocol::PROT_NUMBER); - retval = enbLteSocket->Connect (enbLteSocketConnectAddress); - NS_ASSERT (retval == 0); - - // create LTE socket for the ENB - Ptr enbLteSocket6 = Socket::CreateSocket (enb, TypeId::LookupByName ("ns3::PacketSocketFactory")); - PacketSocketAddress enbLteSocketBindAddress6; - enbLteSocketBindAddress6.SetSingleDevice (lteEnbNetDevice->GetIfIndex ()); - enbLteSocketBindAddress6.SetProtocol (Ipv6L3Protocol::PROT_NUMBER); - retval = enbLteSocket6->Bind (enbLteSocketBindAddress6); - NS_ASSERT (retval == 0); - PacketSocketAddress enbLteSocketConnectAddress6; - enbLteSocketConnectAddress6.SetPhysicalAddress (Mac48Address::GetBroadcast ()); - enbLteSocketConnectAddress6.SetSingleDevice (lteEnbNetDevice->GetIfIndex ()); - enbLteSocketConnectAddress6.SetProtocol (Ipv6L3Protocol::PROT_NUMBER); - retval = enbLteSocket6->Connect (enbLteSocketConnectAddress6); - NS_ASSERT (retval == 0); - - NS_LOG_INFO ("Create EpcEnbApplication"); - Ptr enbApp = CreateObject (enbLteSocket, enbLteSocket6, enbS1uSocket, enbS1uAddress, sgwS1uAddress, cellId); - enb->AddApplication (enbApp); - NS_ASSERT (enb->GetNApplications () == 1); - NS_ASSERT_MSG (enb->GetApplication (0)->GetObject () != 0, "cannot retrieve EpcEnbApplication"); - NS_LOG_LOGIC ("enb: " << enb << ", enb->GetApplication (0): " << enb->GetApplication (0)); - - NS_LOG_INFO ("Create EpcX2 entity"); - Ptr x2 = CreateObject (); - enb->AggregateObject (x2); - - NS_LOG_INFO ("Connect S1-AP interface"); - m_mmeApp->AddEnb (cellId, enbS1uAddress, enbApp->GetS1apSapEnb ()); - m_sgwApp->AddEnb (cellId, enbS1uAddress, sgwS1uAddress); - enbApp->SetS1apSapMme (m_mmeApp->GetS1apSapMme ()); -} - - -void -PointToPointEpcHelper::AddX2Interface (Ptr enb1, Ptr enb2) -{ - NS_LOG_FUNCTION (this << enb1 << enb2); - - // Create a point to point link between the two eNBs with - // the corresponding new NetDevices on each side - PointToPointHelper p2ph; - p2ph.SetDeviceAttribute ("DataRate", DataRateValue (m_x2LinkDataRate)); - p2ph.SetDeviceAttribute ("Mtu", UintegerValue (m_x2LinkMtu)); - p2ph.SetChannelAttribute ("Delay", TimeValue (m_x2LinkDelay)); - NetDeviceContainer enbDevices = p2ph.Install (enb1, enb2); - NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB #1 after installing p2p dev: " << enb1->GetObject ()->GetNInterfaces ()); - NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB #2 after installing p2p dev: " << enb2->GetObject ()->GetNInterfaces ()); - Ptr enb1Dev = enbDevices.Get (0); - Ptr enb2Dev = enbDevices.Get (1); - - if (m_enablePcapOverX2) - { - p2ph.EnablePcapAll(m_x2LinkPcapPrefix); - } - - m_x2Ipv4AddressHelper.NewNetwork (); - Ipv4InterfaceContainer enbIpIfaces = m_x2Ipv4AddressHelper.Assign (enbDevices); - NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB #1 after assigning Ipv4 addr to X2 dev: " << enb1->GetObject ()->GetNInterfaces ()); - NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB #2 after assigning Ipv4 addr to X2 dev: " << enb2->GetObject ()->GetNInterfaces ()); - - Ipv4Address enb1X2Address = enbIpIfaces.GetAddress (0); - Ipv4Address enb2X2Address = enbIpIfaces.GetAddress (1); - - // Add X2 interface to both eNBs' X2 entities - Ptr enb1X2 = enb1->GetObject (); - Ptr enb2X2 = enb2->GetObject (); - - Ptr enb1LteDev = enb1->GetDevice (0); - Ptr enb2LteDev = enb2->GetDevice (0); - - DoAddX2Interface (enb1X2, enb1LteDev, enb1X2Address, enb2X2, enb2LteDev, enb2X2Address); -} - -void -PointToPointEpcHelper::DoAddX2Interface (const Ptr &enb1X2, const Ptr &enb1LteDev, - const Ipv4Address &enb1X2Address, - const Ptr &enb2X2, const Ptr &enb2LteDev, - const Ipv4Address &enb2X2Address) const -{ - NS_LOG_FUNCTION (this); - - Ptr enb1LteDevice = enb1LteDev->GetObject (); - Ptr enb2LteDevice = enb2LteDev->GetObject (); - - NS_ABORT_MSG_IF (enb1LteDevice == nullptr , "Unable to find LteEnbNetDevice for the first eNB"); - NS_ABORT_MSG_IF (enb2LteDevice == nullptr , "Unable to find LteEnbNetDevice for the second eNB"); - - uint16_t enb1CellId = enb1LteDevice->GetCellId (); - uint16_t enb2CellId = enb2LteDevice->GetCellId (); - - NS_LOG_LOGIC ("LteEnbNetDevice #1 = " << enb1LteDev << " - CellId = " << enb1CellId); - NS_LOG_LOGIC ("LteEnbNetDevice #2 = " << enb2LteDev << " - CellId = " << enb2CellId); - - enb1X2->AddX2Interface (enb1CellId, enb1X2Address, enb2CellId, enb2X2Address); - enb2X2->AddX2Interface (enb2CellId, enb2X2Address, enb1CellId, enb1X2Address); - - enb1LteDevice->GetRrc ()->AddX2Neighbour (enb2CellId); - enb2LteDevice->GetRrc ()->AddX2Neighbour (enb1CellId); -} - - -void -PointToPointEpcHelper::AddUe (Ptr ueDevice, uint64_t imsi) -{ - NS_LOG_FUNCTION (this << imsi << ueDevice); - - m_mmeApp->AddUe (imsi); - m_pgwApp->AddUe (imsi); -} - -uint8_t -PointToPointEpcHelper::ActivateEpsBearer (Ptr ueDevice, uint64_t imsi, - Ptr tft, EpsBearer bearer) -{ - NS_LOG_FUNCTION (this << ueDevice << imsi); - - // we now retrieve the IPv4/IPv6 address of the UE and notify it to the SGW; - // we couldn't do it before since address assignment is triggered by - // the user simulation program, rather than done by the EPC - Ptr ueNode = ueDevice->GetNode (); - Ptr ueIpv4 = ueNode->GetObject (); - Ptr ueIpv6 = ueNode->GetObject (); - NS_ASSERT_MSG (ueIpv4 != 0 || ueIpv6 != 0, "UEs need to have IPv4/IPv6 installed before EPS bearers can be activated"); - - if (ueIpv4) - { - int32_t interface = ueIpv4->GetInterfaceForDevice (ueDevice); - if (interface >= 0 && ueIpv4->GetNAddresses (interface) == 1) - { - Ipv4Address ueAddr = ueIpv4->GetAddress (interface, 0).GetLocal (); - NS_LOG_LOGIC (" UE IPv4 address: " << ueAddr); - m_pgwApp->SetUeAddress (imsi, ueAddr); - } - } - if (ueIpv6) - { - int32_t interface6 = ueIpv6->GetInterfaceForDevice (ueDevice); - if (interface6 >= 0 && ueIpv6->GetNAddresses (interface6) == 2) - { - Ipv6Address ueAddr6 = ueIpv6->GetAddress (interface6, 1).GetAddress (); - NS_LOG_LOGIC (" UE IPv6 address: " << ueAddr6); - m_pgwApp->SetUeAddress6 (imsi, ueAddr6); - } - } - uint8_t bearerId = m_mmeApp->AddBearer (imsi, tft, bearer); - - DoActivateEpsBearerForUe (ueDevice, tft, bearer); - - return bearerId; -} - -void -PointToPointEpcHelper::DoActivateEpsBearerForUe (const Ptr &ueDevice, - const Ptr &tft, - const EpsBearer &bearer) const -{ - NS_LOG_FUNCTION (this); - Ptr ueLteDevice = DynamicCast (ueDevice); - if (ueLteDevice == nullptr) - { - // You may wonder why this is not an assert. Well, take a look in epc-test-s1u-downlink - // and -uplink: we are using CSMA to simulate UEs. - NS_LOG_WARN ("Unable to find LteUeNetDevice while activating the EPS bearer"); - } - else - { - Simulator::ScheduleNow (&EpcUeNas::ActivateEpsBearer, ueLteDevice->GetNas (), bearer, tft); - } -} - -Ptr -PointToPointEpcHelper::GetPgwNode () const -{ - return m_pgw; -} - -Ipv4InterfaceContainer -PointToPointEpcHelper::AssignUeIpv4Address (NetDeviceContainer ueDevices) -{ - return m_uePgwAddressHelper.Assign (ueDevices); -} - -Ipv6InterfaceContainer -PointToPointEpcHelper::AssignUeIpv6Address (NetDeviceContainer ueDevices) -{ - for (NetDeviceContainer::Iterator iter = ueDevices.Begin (); - iter != ueDevices.End (); - iter ++) - { - Ptr icmpv6 = (*iter)->GetNode ()->GetObject (); - icmpv6->SetAttribute ("DAD", BooleanValue (false)); - } - return m_uePgwAddressHelper6.Assign (ueDevices); -} - -Ipv4Address -PointToPointEpcHelper::GetUeDefaultGatewayAddress () -{ - // return the address of the tun device - return m_pgw->GetObject ()->GetAddress (1, 0).GetLocal (); -} - -Ipv6Address -PointToPointEpcHelper::GetUeDefaultGatewayAddress6 () -{ - // return the address of the tun device - return m_pgw->GetObject ()->GetAddress (1, 1).GetAddress (); + NoBackhaulEpcHelper::AddS1Interface (enb, enbS1uAddress, sgwS1uAddress, cellId); } } // namespace ns3 diff --git a/src/lte/helper/point-to-point-epc-helper.h b/src/lte/helper/point-to-point-epc-helper.h index 9d60c2513..ad545521b 100644 --- a/src/lte/helper/point-to-point-epc-helper.h +++ b/src/lte/helper/point-to-point-epc-helper.h @@ -1,6 +1,6 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* - * Copyright (c) 2011-2018 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) + * Copyright (c) 2011-2019 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -18,39 +18,24 @@ * Author: Jaume Nin * Nicola Baldo * Manuel Requena + * (most of the code refactored to no-backhaul-epc-helper.h) */ #ifndef POINT_TO_POINT_EPC_HELPER_H #define POINT_TO_POINT_EPC_HELPER_H -#include -#include -#include -#include -#include -#include -#include +#include "ns3/no-backhaul-epc-helper.h" namespace ns3 { -class Node; -class NetDevice; -class VirtualNetDevice; -class EpcSgwApplication; -class EpcPgwApplication; -class EpcMmeApplication; -class EpcX2; - /** * \ingroup lte - * \brief Create an EPC network with PointToPoint links + * \brief Create an EPC network with PointToPoint links in the backhaul network. * - * This Helper will create an EPC network topology comprising of - * three nodes: SGW, PGW and MME. - * The S1-U, X2-U, X2-C, S5 and S11 interfaces are realized over - * PointToPoint links. + * This Helper extends NoBackhaulEpcHelper creating PointToPoint links in the + * backhaul network (i.e. in the S1-U and S1-MME interfaces) */ -class PointToPointEpcHelper : public EpcHelper +class PointToPointEpcHelper : public NoBackhaulEpcHelper { public: /** @@ -62,7 +47,7 @@ public: * Destructor */ virtual ~PointToPointEpcHelper (); - + // inherited from Object /** * Register this type. @@ -74,87 +59,10 @@ public: // inherited from EpcHelper virtual void AddEnb (Ptr enbNode, Ptr lteEnbNetDevice, uint16_t cellId); - virtual void AddUe (Ptr ueLteDevice, uint64_t imsi); - virtual void AddX2Interface (Ptr enbNode1, Ptr enbNode2); - virtual uint8_t ActivateEpsBearer (Ptr ueLteDevice, uint64_t imsi, Ptr tft, EpsBearer bearer); - virtual Ptr GetPgwNode () const; - virtual Ipv4InterfaceContainer AssignUeIpv4Address (NetDeviceContainer ueDevices); - virtual Ipv6InterfaceContainer AssignUeIpv6Address (NetDeviceContainer ueDevices); - virtual Ipv4Address GetUeDefaultGatewayAddress (); - virtual Ipv6Address GetUeDefaultGatewayAddress6 (); -protected: - /** - * \brief DoAddX2Interface: Call AddX2Interface on top of the Enb device pointers - * - * \param enb1X2 EPCX2 of ENB1 - * \param enb1LteDev LTE device of ENB1 - * \param enb1X2Address Address for ENB1 - * \param enb2X2 EPCX2 of ENB2 - * \param enb2LteDev LTE device of ENB2 - * \param enb2X2Address Address for ENB2 - */ - virtual void DoAddX2Interface(const Ptr &enb1X2, const Ptr &enb1LteDev, - const Ipv4Address &enb1X2Address, - const Ptr &enb2X2, const Ptr &enb2LteDev, - const Ipv4Address &enb2X2Address) const; - - /** - * \brief DoActivateEpsBearerForUe: Schedule ActivateEpsBearer on the UE - * \param ueDevice LTE device for the UE - * \param tft TFT - * \param bearer Bearer - */ - virtual void DoActivateEpsBearerForUe (const Ptr &ueDevice, - const Ptr &tft, - const EpsBearer &bearer) const; private: - /** - * helper to assign IPv4 addresses to UE devices as well as to the TUN device of the SGW/PGW - */ - Ipv4AddressHelper m_uePgwAddressHelper; - /** - * helper to assign IPv6 addresses to UE devices as well as to the TUN device of the SGW/PGW - */ - Ipv6AddressHelper m_uePgwAddressHelper6; - - /** - * SGW network element - */ - Ptr m_sgw; - - /** - * PGW network element - */ - Ptr m_pgw; - - /** - * MME network element - */ - Ptr m_mme; - - /** - * SGW application - */ - Ptr m_sgwApp; - - /** - * PGW application - */ - Ptr m_pgwApp; - - /** - * MME application - */ - Ptr m_mmeApp; - - /** - * TUN device implementing tunneling of user data over GTP-U/UDP/IP - */ - Ptr m_tunDevice; - /** * S1-U interfaces */ @@ -182,103 +90,15 @@ private: */ uint16_t m_s1uLinkMtu; - /** - * UDP port where the GTP-U Socket is bound, fixed by the standard as 2152 - */ - uint16_t m_gtpuUdpPort; /** * Helper to assign addresses to S1-MME NetDevices */ Ipv4AddressHelper m_s1apIpv4AddressHelper; /** - * Helper to assign addresses to S11 NetDevices + * Enable PCAP generation for S1 link */ - Ipv4AddressHelper m_s11Ipv4AddressHelper; - - /** - * The data rate to be used for the next S11 link to be created - */ - DataRate m_s11LinkDataRate; - - /** - * The delay to be used for the next S11 link to be created - */ - Time m_s11LinkDelay; - - /** - * The MTU of the next S11 link to be created - */ - uint16_t m_s11LinkMtu; - - /** - * UDP port where the GTPv2-C Socket is bound, fixed by the standard as 2123 - */ - uint16_t m_gtpcUdpPort; - - /** - * S5 interfaces - */ - - /** - * Helper to assign addresses to S5 NetDevices - */ - Ipv4AddressHelper m_s5Ipv4AddressHelper; - - /** - * The data rate to be used for the next S5 link to be created - */ - DataRate m_s5LinkDataRate; - - /** - * The delay to be used for the next S5 link to be created - */ - Time m_s5LinkDelay; - - /** - * The MTU of the next S5 link to be created - */ - uint16_t m_s5LinkMtu; - - /** - * Map storing for each IMSI the corresponding eNB NetDevice - */ - std::map > m_imsiEnbDeviceMap; - - /** - * helper to assign addresses to X2 NetDevices - */ - Ipv4AddressHelper m_x2Ipv4AddressHelper; - - /** - * The data rate to be used for the next X2 link to be created - */ - DataRate m_x2LinkDataRate; - - /** - * The delay to be used for the next X2 link to be created - */ - Time m_x2LinkDelay; - - /** - * The MTU of the next X2 link to be created. Note that, - * because of some big X2 messages, you need a big MTU. - */ - uint16_t m_x2LinkMtu; - - /** - * Enable PCAP generation for X2 link - */ - bool m_enablePcapOverX2; - /** - * Prefix for the PCAP file for the X2 link - */ - std::string m_x2LinkPcapPrefix; - - /** - * Enable PCAP generation for S1U link - */ - bool m_enablePcapOverS1U; + bool m_s1uLinkEnablePcap; /** * Prefix for the PCAP file for the S1 link @@ -286,9 +106,6 @@ private: std::string m_s1uLinkPcapPrefix; }; - - - } // namespace ns3 #endif // POINT_TO_POINT_EPC_HELPER_H diff --git a/src/lte/model/epc-enb-application.cc b/src/lte/model/epc-enb-application.cc index becae00ec..cb746374d 100644 --- a/src/lte/model/epc-enb-application.cc +++ b/src/lte/model/epc-enb-application.cc @@ -87,19 +87,16 @@ EpcEnbApplication::DoDispose (void) delete m_s1apSapEnb; } -EpcEnbApplication::EpcEnbApplication (Ptr lteSocket, Ptr lteSocket6, Ptr s1uSocket, Ipv4Address enbS1uAddress, Ipv4Address sgwS1uAddress, uint16_t cellId) +EpcEnbApplication::EpcEnbApplication (Ptr lteSocket, Ptr lteSocket6, uint16_t cellId) : m_lteSocket (lteSocket), m_lteSocket6 (lteSocket6), - m_s1uSocket (s1uSocket), - m_enbS1uAddress (enbS1uAddress), - m_sgwS1uAddress (sgwS1uAddress), m_gtpuUdpPort (2152), // fixed by the standard m_s1SapUser (0), m_s1apSapMme (0), m_cellId (cellId) { - NS_LOG_FUNCTION (this << lteSocket << s1uSocket << sgwS1uAddress); - m_s1uSocket->SetRecvCallback (MakeCallback (&EpcEnbApplication::RecvFromS1uSocket, this)); + NS_LOG_FUNCTION (this << lteSocket << lteSocket6 << cellId); + m_lteSocket->SetRecvCallback (MakeCallback (&EpcEnbApplication::RecvFromLteSocket, this)); m_lteSocket6->SetRecvCallback (MakeCallback (&EpcEnbApplication::RecvFromLteSocket, this)); m_s1SapProvider = new MemberEpcEnbS1SapProvider (this); @@ -107,6 +104,18 @@ EpcEnbApplication::EpcEnbApplication (Ptr lteSocket, Ptr lteSock } +void +EpcEnbApplication::AddS1Interface (Ptr s1uSocket, Ipv4Address enbAddress, Ipv4Address sgwAddress) +{ + NS_LOG_FUNCTION (this << s1uSocket << enbAddress << sgwAddress); + + m_s1uSocket = s1uSocket; + m_s1uSocket->SetRecvCallback (MakeCallback (&EpcEnbApplication::RecvFromS1uSocket, this)); + m_enbS1uAddress = enbAddress; + m_sgwS1uAddress = sgwAddress; +} + + EpcEnbApplication::~EpcEnbApplication (void) { NS_LOG_FUNCTION (this); diff --git a/src/lte/model/epc-enb-application.h b/src/lte/model/epc-enb-application.h index f8397b0d1..ba69bc533 100644 --- a/src/lte/model/epc-enb-application.h +++ b/src/lte/model/epc-enb-application.h @@ -73,12 +73,19 @@ public: * * \param lteSocket the socket to be used to send/receive IPv4 packets to/from the LTE radio interface * \param lteSocket6 the socket to be used to send/receive IPv6 packets to/from the LTE radio interface + * \param cellId the identifier of the eNB + */ + EpcEnbApplication (Ptr lteSocket, Ptr lteSocket6, uint16_t cellId); + + /** + * Add a S1-U interface to the eNB + * * \param s1uSocket the socket to be used to send/receive packets to/from the S1-U interface connected with the SGW * \param enbS1uAddress the IPv4 address of the S1-U interface of this eNB * \param sgwS1uAddress the IPv4 address at which this eNB will be able to reach its SGW for S1-U communications - * \param cellId the identifier of the eNB */ - EpcEnbApplication (Ptr lteSocket, Ptr lteSocket6, Ptr s1uSocket, Ipv4Address enbS1uAddress, Ipv4Address sgwS1uAddress, uint16_t cellId); + void AddS1Interface (Ptr s1uSocket, Ipv4Address enbAddress, Ipv4Address sgwAddress); + /** * Destructor diff --git a/src/lte/model/epc-mme.cc b/src/lte/model/epc-mme.cc deleted file mode 100644 index 0c99ea8c3..000000000 --- a/src/lte/model/epc-mme.cc +++ /dev/null @@ -1,286 +0,0 @@ -/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Nicola Baldo - */ - -#include -#include - -#include "epc-s1ap-sap.h" -#include "epc-s11-sap.h" - -#include "epc-mme.h" - -namespace ns3 { - -NS_LOG_COMPONENT_DEFINE ("EpcMme"); - -NS_OBJECT_ENSURE_REGISTERED (EpcMme); - -EpcMme::EpcMme () - : m_s11SapSgw (0) -{ - NS_LOG_FUNCTION (this); - m_s1apSapMme = new MemberEpcS1apSapMme (this); - m_s11SapMme = new MemberEpcS11SapMme (this); -} - - -EpcMme::~EpcMme () -{ - NS_LOG_FUNCTION (this); -} - -void -EpcMme::DoDispose () -{ - NS_LOG_FUNCTION (this); - delete m_s1apSapMme; - delete m_s11SapMme; -} - -TypeId -EpcMme::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::EpcMme") - .SetParent () - .SetGroupName("Lte") - .AddConstructor () - ; - return tid; -} - -EpcS1apSapMme* -EpcMme::GetS1apSapMme () -{ - return m_s1apSapMme; -} - -void -EpcMme::SetS11SapSgw (EpcS11SapSgw * s) -{ - m_s11SapSgw = s; -} - -EpcS11SapMme* -EpcMme::GetS11SapMme () -{ - return m_s11SapMme; -} - -void -EpcMme::AddEnb (uint16_t gci, Ipv4Address enbS1uAddr, EpcS1apSapEnb* enbS1apSap) -{ - NS_LOG_FUNCTION (this << gci << enbS1uAddr); - Ptr enbInfo = Create (); - enbInfo->gci = gci; - enbInfo->s1uAddr = enbS1uAddr; - enbInfo->s1apSapEnb = enbS1apSap; - m_enbInfoMap[gci] = enbInfo; -} - -void -EpcMme::AddUe (uint64_t imsi) -{ - NS_LOG_FUNCTION (this << imsi); - Ptr ueInfo = Create (); - ueInfo->imsi = imsi; - ueInfo->mmeUeS1Id = imsi; - m_ueInfoMap[imsi] = ueInfo; - ueInfo->bearerCounter = 0; -} - -uint8_t -EpcMme::AddBearer (uint64_t imsi, Ptr tft, EpsBearer bearer) -{ - NS_LOG_FUNCTION (this << imsi); - std::map >::iterator it = m_ueInfoMap.find (imsi); - NS_ASSERT_MSG (it != m_ueInfoMap.end (), "could not find any UE with IMSI " << imsi); - NS_ASSERT_MSG (it->second->bearerCounter < 11, "too many bearers already! " << it->second->bearerCounter); - BearerInfo bearerInfo; - bearerInfo.bearerId = ++(it->second->bearerCounter); - bearerInfo.tft = tft; - bearerInfo.bearer = bearer; - it->second->bearersToBeActivated.push_back (bearerInfo); - return bearerInfo.bearerId; -} - - -// S1-AP SAP MME forwarded methods - -void -EpcMme::DoInitialUeMessage (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, uint64_t imsi, uint16_t gci) -{ - NS_LOG_FUNCTION (this << mmeUeS1Id << enbUeS1Id << imsi << gci); - std::map >::iterator it = m_ueInfoMap.find (imsi); - NS_ASSERT_MSG (it != m_ueInfoMap.end (), "could not find any UE with IMSI " << imsi); - it->second->cellId = gci; - EpcS11SapSgw::CreateSessionRequestMessage msg; - msg.imsi = imsi; - msg.uli.gci = gci; - msg.teid = 0; - for (std::list::iterator bit = it->second->bearersToBeActivated.begin (); - bit != it->second->bearersToBeActivated.end (); - ++bit) - { - EpcS11SapSgw::BearerContextToBeCreated bearerContext; - bearerContext.epsBearerId = bit->bearerId; - bearerContext.bearerLevelQos = bit->bearer; - bearerContext.tft = bit->tft; - msg.bearerContextsToBeCreated.push_back (bearerContext); - } - m_s11SapSgw->CreateSessionRequest (msg); -} - -void -EpcMme::DoInitialContextSetupResponse (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list erabSetupList) -{ - NS_LOG_FUNCTION (this << mmeUeS1Id << enbUeS1Id); - NS_FATAL_ERROR ("unimplemented"); -} - -void -EpcMme::DoPathSwitchRequest (uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t gci, std::list erabToBeSwitchedInDownlinkList) -{ - NS_LOG_FUNCTION (this << mmeUeS1Id << enbUeS1Id << gci); - - uint64_t imsi = mmeUeS1Id; - std::map >::iterator it = m_ueInfoMap.find (imsi); - NS_ASSERT_MSG (it != m_ueInfoMap.end (), "could not find any UE with IMSI " << imsi); - NS_LOG_INFO ("IMSI " << imsi << " old eNB: " << it->second->cellId << ", new eNB: " << gci); - it->second->cellId = gci; - it->second->enbUeS1Id = enbUeS1Id; - - EpcS11SapSgw::ModifyBearerRequestMessage msg; - msg.teid = imsi; // trick to avoid the need for allocating TEIDs on the S11 interface - msg.uli.gci = gci; - // bearer modification is not supported for now - m_s11SapSgw->ModifyBearerRequest (msg); -} - - -// S11 SAP MME forwarded methods - -void -EpcMme::DoCreateSessionResponse (EpcS11SapMme::CreateSessionResponseMessage msg) -{ - NS_LOG_FUNCTION (this << msg.teid); - uint64_t imsi = msg.teid; - std::list erabToBeSetupList; - for (std::list::iterator bit = msg.bearerContextsCreated.begin (); - bit != msg.bearerContextsCreated.end (); - ++bit) - { - EpcS1apSapEnb::ErabToBeSetupItem erab; - erab.erabId = bit->epsBearerId; - erab.erabLevelQosParameters = bit->bearerLevelQos; - erab.transportLayerAddress = bit->sgwFteid.address; - erab.sgwTeid = bit->sgwFteid.teid; - erabToBeSetupList.push_back (erab); - } - std::map >::iterator it = m_ueInfoMap.find (imsi); - NS_ASSERT_MSG (it != m_ueInfoMap.end (), "could not find any UE with IMSI " << imsi); - uint16_t cellId = it->second->cellId; - uint16_t enbUeS1Id = it->second->enbUeS1Id; - uint64_t mmeUeS1Id = it->second->mmeUeS1Id; - std::map >::iterator jt = m_enbInfoMap.find (cellId); - NS_ASSERT_MSG (jt != m_enbInfoMap.end (), "could not find any eNB with CellId " << cellId); - jt->second->s1apSapEnb->InitialContextSetupRequest (mmeUeS1Id, enbUeS1Id, erabToBeSetupList); -} - - -void -EpcMme::DoModifyBearerResponse (EpcS11SapMme::ModifyBearerResponseMessage msg) -{ - NS_LOG_FUNCTION (this << msg.teid); - NS_ASSERT (msg.cause == EpcS11SapMme::ModifyBearerResponseMessage::REQUEST_ACCEPTED); - uint64_t imsi = msg.teid; - std::map >::iterator it = m_ueInfoMap.find (imsi); - NS_ASSERT_MSG (it != m_ueInfoMap.end (), "could not find any UE with IMSI " << imsi); - uint64_t enbUeS1Id = it->second->enbUeS1Id; - uint64_t mmeUeS1Id = it->second->mmeUeS1Id; - uint16_t cgi = it->second->cellId; - std::list erabToBeSwitchedInUplinkList; // unused for now - std::map >::iterator jt = m_enbInfoMap.find (it->second->cellId); - NS_ASSERT_MSG (jt != m_enbInfoMap.end (), "could not find any eNB with CellId " << it->second->cellId); - jt->second->s1apSapEnb->PathSwitchRequestAcknowledge (enbUeS1Id, mmeUeS1Id, cgi, erabToBeSwitchedInUplinkList); -} - -void -EpcMme::DoErabReleaseIndication (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list erabToBeReleaseIndication) -{ - NS_LOG_FUNCTION (this << mmeUeS1Id << enbUeS1Id); - uint64_t imsi = mmeUeS1Id; - std::map >::iterator it = m_ueInfoMap.find (imsi); - NS_ASSERT_MSG (it != m_ueInfoMap.end (), "could not find any UE with IMSI " << imsi); - - EpcS11SapSgw::DeleteBearerCommandMessage msg; - // trick to avoid the need for allocating TEIDs on the S11 interface - msg.teid = imsi; - - for (std::list::iterator bit = erabToBeReleaseIndication.begin (); bit != erabToBeReleaseIndication.end (); ++bit) - { - EpcS11SapSgw::BearerContextToBeRemoved bearerContext; - bearerContext.epsBearerId = bit->erabId; - msg.bearerContextsToBeRemoved.push_back (bearerContext); - } - //Delete Bearer command towards epc-sgw-pgw-application - m_s11SapSgw->DeleteBearerCommand (msg); -} - -void -EpcMme::DoDeleteBearerRequest (EpcS11SapMme::DeleteBearerRequestMessage msg) -{ - NS_LOG_FUNCTION (this); - uint64_t imsi = msg.teid; - std::map >::iterator it = m_ueInfoMap.find (imsi); - NS_ASSERT_MSG (it != m_ueInfoMap.end (), "could not find any UE with IMSI " << imsi); - EpcS11SapSgw::DeleteBearerResponseMessage res; - - res.teid = imsi; - - for (std::list::iterator bit = msg.bearerContextsRemoved.begin (); - bit != msg.bearerContextsRemoved.end (); - ++bit) - { - EpcS11SapSgw::BearerContextRemovedSgwPgw bearerContext; - bearerContext.epsBearerId = bit->epsBearerId; - res.bearerContextsRemoved.push_back (bearerContext); - - RemoveBearer (it->second, bearerContext.epsBearerId); //schedules function to erase, context of de-activated bearer - } - //schedules Delete Bearer Response towards epc-sgw-pgw-application - m_s11SapSgw->DeleteBearerResponse (res); -} - -void EpcMme::RemoveBearer (Ptr ueInfo, uint8_t epsBearerId) -{ - NS_LOG_FUNCTION (this << epsBearerId); - for (std::list::iterator bit = ueInfo->bearersToBeActivated.begin (); - bit != ueInfo->bearersToBeActivated.end (); - ++bit) - { - if (bit->bearerId == epsBearerId) - { - ueInfo->bearersToBeActivated.erase (bit); - break; - } - } -} - -} // namespace ns3 diff --git a/src/lte/model/epc-mme.h b/src/lte/model/epc-mme.h deleted file mode 100644 index dc7d1dfce..000000000 --- a/src/lte/model/epc-mme.h +++ /dev/null @@ -1,241 +0,0 @@ -/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Nicola Baldo - */ - -#ifndef EPC_MME_H -#define EPC_MME_H - -#include -#include -#include - -#include -#include - -namespace ns3 { - -class Node; -class NetDevice; - -/** - * \brief This object implements the MME functionality. - * - */ -class EpcMme : public Object -{ - - /// allow MemberEpcS1apSapMme class friend access - friend class MemberEpcS1apSapMme; - /// allow MemberEpcS11SapMme class friend access - friend class MemberEpcS11SapMme; - -public: - - /** - * Constructor - */ - EpcMme (); - - /** - * Destructor - */ - virtual ~EpcMme (); - - /** - * \brief Get the type ID. - * \return the object TypeId - */ - static TypeId GetTypeId (void); -protected: - virtual void DoDispose (); - -public: - - - /** - * - * \return the MME side of the S1-AP SAP - */ - EpcS1apSapMme* GetS1apSapMme (); - - /** - * Set the SGW side of the S11 SAP - * - * \param s the SGW side of the S11 SAP - */ - void SetS11SapSgw (EpcS11SapSgw * s); - - /** - * - * \return the MME side of the S11 SAP - */ - EpcS11SapMme* GetS11SapMme (); - - /** - * Add a new ENB to the MME. - * \param ecgi E-UTRAN Cell Global ID, the unique identifier of the eNodeB - * \param enbS1UAddr address of the eNB for S1-U communications - * \param enbS1apSap the ENB side of the S1-AP SAP - */ - void AddEnb (uint16_t ecgi, Ipv4Address enbS1UAddr, EpcS1apSapEnb* enbS1apSap); - - /** - * Add a new UE to the MME. This is the equivalent of storing the UE - * credentials before the UE is ever turned on. - * - * \param imsi the unique identifier of the UE - */ - void AddUe (uint64_t imsi); - - /** - * Add an EPS bearer to the list of bearers to be activated for this - * UE. The bearer will be activated when the UE enters the ECM - * connected state. - * - * \param imsi UE identifier - * \param tft traffic flow template of the bearer - * \param bearer QoS characteristics of the bearer - * \returns bearer ID - */ - uint8_t AddBearer (uint64_t imsi, Ptr tft, EpsBearer bearer); - - -private: - - // S1-AP SAP MME forwarded methods - /** - * Initial UE Message function - * \param mmeUeS1Id the MME UE S1 ID - * \param enbUeS1Id the ENB UE S1 ID - * \param imsi the IMSI - * \param ecgi the ECGI - */ - void DoInitialUeMessage (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, uint64_t imsi, uint16_t ecgi); - /** - * Initial Context Setup Response function - * \param mmeUeS1Id the MME UE S1 ID - * \param enbUeS1Id the ENB UE S1 ID - * \param erabSetupList the ERAB setup list - */ - void DoInitialContextSetupResponse (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list erabSetupList); - /** - * Path Switch Request function - * \param mmeUeS1Id the MME UE S1 ID - * \param enbUeS1Id the ENB UE S1 ID - * \param cgi the CGI - * \param erabToBeSwitchedInDownlinkList the ERAB to be switched in downlink list - */ - void DoPathSwitchRequest (uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t cgi, std::list erabToBeSwitchedInDownlinkList); - /** - * ERAB Release Indication function - * \param mmeUeS1Id the MME UE S1 ID - * \param enbUeS1Id the ENB UE S1 ID - * \param erabToBeReleaseIndication the ERAB to be release indication list - */ - void DoErabReleaseIndication (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list erabToBeReleaseIndication); - - // S11 SAP MME forwarded methods - /** - * Create Session Response function - * \param msg EpcS11SapMme::CreateSessionResponseMessage - */ - void DoCreateSessionResponse (EpcS11SapMme::CreateSessionResponseMessage msg); - /** - * Modify Bearer Response function - * \param msg EpcS11SapMme::ModifyBearerResponseMessage - */ - void DoModifyBearerResponse (EpcS11SapMme::ModifyBearerResponseMessage msg); - /** - * Delete Bearer Request function - * \param msg EpcS11SapMme::DeleteBearerRequestMessage - */ - void DoDeleteBearerRequest (EpcS11SapMme::DeleteBearerRequestMessage msg); - - - /** - * Hold info on an EPS bearer to be activated - * - */ - struct BearerInfo - { - Ptr tft; ///< traffic flow template - EpsBearer bearer; ///< bearer QOS characteristics - uint8_t bearerId; ///< bearer ID - }; - - /** - * Hold info on a UE - * - */ - struct UeInfo : public SimpleRefCount - { - uint64_t mmeUeS1Id; ///< mmeUeS1Id - uint16_t enbUeS1Id; ///< enbUeS1Id - uint64_t imsi; ///< UE identifier - uint16_t cellId; ///< cell ID - std::list bearersToBeActivated; ///< list of bearers to be activated - uint16_t bearerCounter; ///< bearer counter - }; - - /** - * UeInfo stored by IMSI - * - */ - std::map > m_ueInfoMap; - - /** - * \brief This Function erases all contexts of bearer from MME side - * \param ueInfo UE information pointer - * \param epsBearerId Bearer Id which need to be removed corresponding to UE - */ - void RemoveBearer (Ptr ueInfo, uint8_t epsBearerId); - - /** - * Hold info on a ENB - * - */ - struct EnbInfo : public SimpleRefCount - { - uint16_t gci; ///< GCI - Ipv4Address s1uAddr; ///< IP address - EpcS1apSapEnb* s1apSapEnb; ///< EpcS1apSapEnb - }; - - /** - * EnbInfo stored by EGCI - * - */ - std::map > m_enbInfoMap; - - - - - EpcS1apSapMme* m_s1apSapMme; ///< EpcS1apSapMme - - EpcS11SapMme* m_s11SapMme; ///< EpcS11SapMme - EpcS11SapSgw* m_s11SapSgw; ///< EpcS11SapSgw - -}; - - - - -} // namespace ns3 - -#endif // EPC_MME_H diff --git a/src/lte/model/epc-sgw-pgw-application.cc b/src/lte/model/epc-sgw-pgw-application.cc deleted file mode 100644 index 626d9422f..000000000 --- a/src/lte/model/epc-sgw-pgw-application.cc +++ /dev/null @@ -1,436 +0,0 @@ -/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Jaume Nin - * Nicola Baldo - */ - - -#include "epc-sgw-pgw-application.h" -#include "ns3/log.h" -#include "ns3/mac48-address.h" -#include "ns3/ipv4.h" -#include "ns3/ipv4-l3-protocol.h" -#include "ns3/ipv6.h" -#include "ns3/ipv6-header.h" -#include "ns3/ipv6-l3-protocol.h" -#include "ns3/inet-socket-address.h" -#include "ns3/epc-gtpu-header.h" -#include "ns3/abort.h" - -namespace ns3 { - -NS_LOG_COMPONENT_DEFINE ("EpcSgwPgwApplication"); - -///////////////////////// -// UeInfo -///////////////////////// - - -EpcSgwPgwApplication::UeInfo::UeInfo () -{ - NS_LOG_FUNCTION (this); -} - -void -EpcSgwPgwApplication::UeInfo::AddBearer (Ptr tft, uint8_t bearerId, uint32_t teid) -{ - NS_LOG_FUNCTION (this << tft << teid); - m_teidByBearerIdMap[bearerId] = teid; - return m_tftClassifier.Add (tft, teid); -} - -void -EpcSgwPgwApplication::UeInfo::RemoveBearer (uint8_t bearerId) -{ - NS_LOG_FUNCTION (this << bearerId); - m_teidByBearerIdMap.erase (bearerId); -} - -uint32_t -EpcSgwPgwApplication::UeInfo::Classify (Ptr p, uint16_t protocolNumber) -{ - NS_LOG_FUNCTION (this << p); - // we hardcode DOWNLINK direction since the PGW is expected to - // classify only downlink packets (uplink packets will go to the - // internet without any classification). - return m_tftClassifier.Classify (p, EpcTft::DOWNLINK, protocolNumber); -} - -Ipv4Address -EpcSgwPgwApplication::UeInfo::GetEnbAddr () -{ - return m_enbAddr; -} - -void -EpcSgwPgwApplication::UeInfo::SetEnbAddr (Ipv4Address enbAddr) -{ - m_enbAddr = enbAddr; -} - -Ipv4Address -EpcSgwPgwApplication::UeInfo::GetUeAddr () -{ - return m_ueAddr; -} - -void -EpcSgwPgwApplication::UeInfo::SetUeAddr (Ipv4Address ueAddr) -{ - m_ueAddr = ueAddr; -} - -Ipv6Address -EpcSgwPgwApplication::UeInfo::GetUeAddr6 () -{ - return m_ueAddr6; -} - -void -EpcSgwPgwApplication::UeInfo::SetUeAddr6 (Ipv6Address ueAddr) -{ - m_ueAddr6 = ueAddr; -} - -///////////////////////// -// EpcSgwPgwApplication -///////////////////////// - - -TypeId -EpcSgwPgwApplication::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::EpcSgwPgwApplication") - .SetParent () - .SetGroupName("Lte") - .AddTraceSource ("RxFromTun", - "Receive data packets from internet in Tunnel net device", - MakeTraceSourceAccessor (&EpcSgwPgwApplication::m_rxTunPktTrace), - "ns3::EpcSgwPgwApplication::RxTracedCallback") - .AddTraceSource ("RxFromS1u", - "Receive data packets from S1 U Socket", - MakeTraceSourceAccessor (&EpcSgwPgwApplication::m_rxS1uPktTrace), - "ns3::EpcSgwPgwApplication::RxTracedCallback") - ; - return tid; -} - -void -EpcSgwPgwApplication::DoDispose () -{ - NS_LOG_FUNCTION (this); - m_s1uSocket->SetRecvCallback (MakeNullCallback > ()); - m_s1uSocket = 0; - delete (m_s11SapSgw); -} - - -EpcSgwPgwApplication::EpcSgwPgwApplication (const Ptr tunDevice, const Ptr s1uSocket) - : m_s1uSocket (s1uSocket), - m_tunDevice (tunDevice), - m_gtpuUdpPort (2152), // fixed by the standard - m_teidCount (0), - m_s11SapMme (0) -{ - NS_LOG_FUNCTION (this << tunDevice << s1uSocket); - m_s1uSocket->SetRecvCallback (MakeCallback (&EpcSgwPgwApplication::RecvFromS1uSocket, this)); - m_s11SapSgw = new MemberEpcS11SapSgw (this); -} - - -EpcSgwPgwApplication::~EpcSgwPgwApplication () -{ - NS_LOG_FUNCTION (this); -} - - -bool -EpcSgwPgwApplication::RecvFromTunDevice (Ptr packet, const Address& source, const Address& dest, uint16_t protocolNumber) -{ - NS_LOG_FUNCTION (this << source << dest << protocolNumber << packet << packet->GetSize ()); - m_rxTunPktTrace (packet->Copy ()); - Ptr pCopy = packet->Copy (); - - // get IP address of UE - if (protocolNumber == Ipv4L3Protocol::PROT_NUMBER) - { - Ipv4Header ipv4Header; - pCopy->RemoveHeader (ipv4Header); - Ipv4Address ueAddr = ipv4Header.GetDestination (); - NS_LOG_LOGIC ("packet addressed to UE " << ueAddr); - // find corresponding UeInfo address - std::map >::iterator it = m_ueInfoByAddrMap.find (ueAddr); - if (it == m_ueInfoByAddrMap.end ()) - { - NS_LOG_WARN ("unknown UE address " << ueAddr); - } - else - { - Ipv4Address enbAddr = it->second->GetEnbAddr (); - uint32_t teid = it->second->Classify (packet, protocolNumber); - if (teid == 0) - { - NS_LOG_WARN ("no matching bearer for this packet"); - } - else - { - SendToS1uSocket (packet, enbAddr, teid); - } - } - } - else if (protocolNumber == Ipv6L3Protocol::PROT_NUMBER) - { - Ipv6Header ipv6Header; - pCopy->RemoveHeader (ipv6Header); - Ipv6Address ueAddr = ipv6Header.GetDestinationAddress (); - NS_LOG_LOGIC ("packet addressed to UE " << ueAddr); - // find corresponding UeInfo address - std::map >::iterator it = m_ueInfoByAddrMap6.find (ueAddr); - if (it == m_ueInfoByAddrMap6.end ()) - { - NS_LOG_WARN ("unknown UE address " << ueAddr); - } - else - { - Ipv4Address enbAddr = it->second->GetEnbAddr (); - uint32_t teid = it->second->Classify (packet, protocolNumber); - if (teid == 0) - { - NS_LOG_WARN ("no matching bearer for this packet"); - } - else - { - SendToS1uSocket (packet, enbAddr, teid); - } - } - } - else - { - NS_ABORT_MSG ("EpcSgwPgwApplication::RecvFromTunDevice - Unknown IP type..."); - } - - // there is no reason why we should notify the TUN - // VirtualNetDevice that he failed to send the packet: if we receive - // any bogus packet, it will just be silently discarded. - const bool succeeded = true; - return succeeded; -} - -void -EpcSgwPgwApplication::RecvFromS1uSocket (Ptr socket) -{ - NS_LOG_FUNCTION (this << socket); - NS_ASSERT (socket == m_s1uSocket); - Ptr packet = socket->Recv (); - GtpuHeader gtpu; - packet->RemoveHeader (gtpu); - uint32_t teid = gtpu.GetTeid (); - - SendToTunDevice (packet, teid); - - m_rxS1uPktTrace (packet->Copy ()); -} - -void -EpcSgwPgwApplication::SendToTunDevice (Ptr packet, uint32_t teid) -{ - NS_LOG_FUNCTION (this << packet << teid); - NS_LOG_LOGIC (" packet size: " << packet->GetSize () << " bytes"); - - uint8_t ipType; - packet->CopyData (&ipType, 1); - ipType = (ipType>>4) & 0x0f; - - if (ipType == 0x04) - { - m_tunDevice->Receive (packet, 0x0800, m_tunDevice->GetAddress (), m_tunDevice->GetAddress (), NetDevice::PACKET_HOST); - } - else if (ipType == 0x06) - { - m_tunDevice->Receive (packet, 0x86DD, m_tunDevice->GetAddress (), m_tunDevice->GetAddress (), NetDevice::PACKET_HOST); - } - else - { - NS_ABORT_MSG ("EpcSgwPgwApplication::SendToTunDevice - Unknown IP type..."); - } -} - -void -EpcSgwPgwApplication::SendToS1uSocket (Ptr packet, Ipv4Address enbAddr, uint32_t teid) -{ - NS_LOG_FUNCTION (this << packet << enbAddr << teid); - - GtpuHeader gtpu; - gtpu.SetTeid (teid); - // From 3GPP TS 29.281 v10.0.0 Section 5.1 - // Length of the payload + the non obligatory GTP-U header - gtpu.SetLength (packet->GetSize () + gtpu.GetSerializedSize () - 8); - packet->AddHeader (gtpu); - uint32_t flags = 0; - m_s1uSocket->SendTo (packet, flags, InetSocketAddress (enbAddr, m_gtpuUdpPort)); -} - - -void -EpcSgwPgwApplication::SetS11SapMme (EpcS11SapMme * s) -{ - m_s11SapMme = s; -} - -EpcS11SapSgw* -EpcSgwPgwApplication::GetS11SapSgw () -{ - return m_s11SapSgw; -} - -void -EpcSgwPgwApplication::AddEnb (uint16_t cellId, Ipv4Address enbAddr, Ipv4Address sgwAddr) -{ - NS_LOG_FUNCTION (this << cellId << enbAddr << sgwAddr); - EnbInfo enbInfo; - enbInfo.enbAddr = enbAddr; - enbInfo.sgwAddr = sgwAddr; - m_enbInfoByCellId[cellId] = enbInfo; -} - -void -EpcSgwPgwApplication::AddUe (uint64_t imsi) -{ - NS_LOG_FUNCTION (this << imsi); - Ptr ueInfo = Create (); - m_ueInfoByImsiMap[imsi] = ueInfo; -} - -void -EpcSgwPgwApplication::SetUeAddress (uint64_t imsi, Ipv4Address ueAddr) -{ - NS_LOG_FUNCTION (this << imsi << ueAddr); - std::map >::iterator ueit = m_ueInfoByImsiMap.find (imsi); - NS_ASSERT_MSG (ueit != m_ueInfoByImsiMap.end (), "unknown IMSI " << imsi); - m_ueInfoByAddrMap[ueAddr] = ueit->second; - ueit->second->SetUeAddr (ueAddr); -} - -void -EpcSgwPgwApplication::SetUeAddress6 (uint64_t imsi, Ipv6Address ueAddr) -{ - NS_LOG_FUNCTION (this << imsi << ueAddr); - std::map >::iterator ueit = m_ueInfoByImsiMap.find (imsi); - NS_ASSERT_MSG (ueit != m_ueInfoByImsiMap.end (), "unknown IMSI " << imsi); - m_ueInfoByAddrMap6[ueAddr] = ueit->second; - ueit->second->SetUeAddr6 (ueAddr); -} - -void -EpcSgwPgwApplication::DoCreateSessionRequest (EpcS11SapSgw::CreateSessionRequestMessage req) -{ - NS_LOG_FUNCTION (this << req.imsi); - std::map >::iterator ueit = m_ueInfoByImsiMap.find (req.imsi); - NS_ASSERT_MSG (ueit != m_ueInfoByImsiMap.end (), "unknown IMSI " << req.imsi); - uint16_t cellId = req.uli.gci; - std::map::iterator enbit = m_enbInfoByCellId.find (cellId); - NS_ASSERT_MSG (enbit != m_enbInfoByCellId.end (), "unknown CellId " << cellId); - Ipv4Address enbAddr = enbit->second.enbAddr; - ueit->second->SetEnbAddr (enbAddr); - - EpcS11SapMme::CreateSessionResponseMessage res; - res.teid = req.imsi; // trick to avoid the need for allocating TEIDs on the S11 interface - - for (std::list::iterator bit = req.bearerContextsToBeCreated.begin (); - bit != req.bearerContextsToBeCreated.end (); - ++bit) - { - // simple sanity check. If you ever need more than 4M teids - // throughout your simulation, you'll need to implement a smarter teid - // management algorithm. - NS_ABORT_IF (m_teidCount == 0xFFFFFFFF); - uint32_t teid = ++m_teidCount; - ueit->second->AddBearer (bit->tft, bit->epsBearerId, teid); - - EpcS11SapMme::BearerContextCreated bearerContext; - bearerContext.sgwFteid.teid = teid; - bearerContext.sgwFteid.address = enbit->second.sgwAddr; - bearerContext.epsBearerId = bit->epsBearerId; - bearerContext.bearerLevelQos = bit->bearerLevelQos; - bearerContext.tft = bit->tft; - res.bearerContextsCreated.push_back (bearerContext); - } - m_s11SapMme->CreateSessionResponse (res); - -} - -void -EpcSgwPgwApplication::DoModifyBearerRequest (EpcS11SapSgw::ModifyBearerRequestMessage req) -{ - NS_LOG_FUNCTION (this << req.teid); - uint64_t imsi = req.teid; // trick to avoid the need for allocating TEIDs on the S11 interface - std::map >::iterator ueit = m_ueInfoByImsiMap.find (imsi); - NS_ASSERT_MSG (ueit != m_ueInfoByImsiMap.end (), "unknown IMSI " << imsi); - uint16_t cellId = req.uli.gci; - std::map::iterator enbit = m_enbInfoByCellId.find (cellId); - NS_ASSERT_MSG (enbit != m_enbInfoByCellId.end (), "unknown CellId " << cellId); - Ipv4Address enbAddr = enbit->second.enbAddr; - ueit->second->SetEnbAddr (enbAddr); - // no actual bearer modification: for now we just support the minimum needed for path switch request (handover) - EpcS11SapMme::ModifyBearerResponseMessage res; - res.teid = imsi; // trick to avoid the need for allocating TEIDs on the S11 interface - res.cause = EpcS11SapMme::ModifyBearerResponseMessage::REQUEST_ACCEPTED; - m_s11SapMme->ModifyBearerResponse (res); -} - -void -EpcSgwPgwApplication::DoDeleteBearerCommand (EpcS11SapSgw::DeleteBearerCommandMessage req) -{ - NS_LOG_FUNCTION (this << req.teid); - uint64_t imsi = req.teid; // trick to avoid the need for allocating TEIDs on the S11 interface - std::map >::iterator ueit = m_ueInfoByImsiMap.find (imsi); - NS_ASSERT_MSG (ueit != m_ueInfoByImsiMap.end (), "unknown IMSI " << imsi); - - EpcS11SapMme::DeleteBearerRequestMessage res; - res.teid = imsi; - - for (std::list::iterator bit = req.bearerContextsToBeRemoved.begin (); - bit != req.bearerContextsToBeRemoved.end (); - ++bit) - { - EpcS11SapMme::BearerContextRemoved bearerContext; - bearerContext.epsBearerId = bit->epsBearerId; - res.bearerContextsRemoved.push_back (bearerContext); - } - //schedules Delete Bearer Request towards MME - m_s11SapMme->DeleteBearerRequest (res); -} - -void -EpcSgwPgwApplication::DoDeleteBearerResponse (EpcS11SapSgw::DeleteBearerResponseMessage req) -{ - NS_LOG_FUNCTION (this << req.teid); - uint64_t imsi = req.teid; // trick to avoid the need for allocating TEIDs on the S11 interface - std::map >::iterator ueit = m_ueInfoByImsiMap.find (imsi); - NS_ASSERT_MSG (ueit != m_ueInfoByImsiMap.end (), "unknown IMSI " << imsi); - - for (std::list::iterator bit = req.bearerContextsRemoved.begin (); - bit != req.bearerContextsRemoved.end (); - ++bit) - { - //Function to remove de-activated bearer contexts from S-Gw and P-Gw side - ueit->second->RemoveBearer (bit->epsBearerId); - } -} - -} // namespace ns3 diff --git a/src/lte/model/epc-sgw-pgw-application.h b/src/lte/model/epc-sgw-pgw-application.h deleted file mode 100644 index 45be08a92..000000000 --- a/src/lte/model/epc-sgw-pgw-application.h +++ /dev/null @@ -1,351 +0,0 @@ -/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Jaume Nin - * Nicola Baldo - */ - -#ifndef EPC_SGW_PGW_APPLICATION_H -#define EPC_SGW_PGW_APPLICATION_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace ns3 { - -/** - * \ingroup lte - * - * This application implements the SGW/PGW functionality. - */ -class EpcSgwPgwApplication : public Application -{ - /// allow MemberEpcS11SapSgw class friend access - friend class MemberEpcS11SapSgw; - -public: - - /** - * \brief Get the type ID. - * \return the object TypeId - */ - static TypeId GetTypeId (void); - virtual void DoDispose (); - - /** - * Constructor that binds the tap device to the callback methods. - * - * \param tunDevice TUN VirtualNetDevice used to tunnel IP packets from - * the Gi interface of the PGW/SGW over the - * internet over GTP-U/UDP/IP on the S1-U interface - * \param s1uSocket socket used to send GTP-U packets to the eNBs - */ - - EpcSgwPgwApplication (const Ptr tunDevice, const Ptr s1uSocket); - - /** - * Destructor - */ - virtual ~EpcSgwPgwApplication (void); - - /** - * Method to be assigned to the callback of the Gi TUN VirtualNetDevice. It - * is called when the SGW/PGW receives a data packet from the - * internet (including IP headers) that is to be sent to the UE via - * its associated eNB, tunneling IP over GTP-U/UDP/IP. - * - * \param packet - * \param source - * \param dest - * \param protocolNumber - * \return true always - */ - bool RecvFromTunDevice (Ptr packet, const Address& source, const Address& dest, uint16_t protocolNumber); - - - /** - * Method to be assigned to the recv callback of the S1-U socket. It - * is called when the SGW/PGW receives a data packet from the eNB - * that is to be forwarded to the internet. - * - * \param socket pointer to the S1-U socket - */ - void RecvFromS1uSocket (Ptr socket); - - /** - * Send a packet to the internet via the Gi interface of the SGW/PGW - * - * \param packet - * \param teid the Tunnel Enpoint Identifier - */ - void SendToTunDevice (Ptr packet, uint32_t teid); - - - /** - * Send a packet to the SGW via the S1-U interface - * - * \param packet packet to be sent - * \param enbS1uAddress the address of the eNB - * \param teid the Tunnel Enpoint IDentifier - */ - void SendToS1uSocket (Ptr packet, Ipv4Address enbS1uAddress, uint32_t teid); - - - /** - * Set the MME side of the S11 SAP - * - * \param s the MME side of the S11 SAP - */ - void SetS11SapMme (EpcS11SapMme * s); - - /** - * - * \return the SGW side of the S11 SAP - */ - EpcS11SapSgw* GetS11SapSgw (); - - - /** - * Let the SGW be aware of a new eNB - * - * \param cellId the cell identifier - * \param enbAddr the address of the eNB - * \param sgwAddr the address of the SGW - */ - void AddEnb (uint16_t cellId, Ipv4Address enbAddr, Ipv4Address sgwAddr); - - /** - * Let the SGW be aware of a new UE - * - * \param imsi the unique identifier of the UE - */ - void AddUe (uint64_t imsi); - - /** - * set the address of a previously added UE - * - * \param imsi the unique identifier of the UE - * \param ueAddr the IPv4 address of the UE - */ - void SetUeAddress (uint64_t imsi, Ipv4Address ueAddr); - - /** - * set the address of a previously added UE - * - * \param imsi the unique identifier of the UE - * \param ueAddr the IPv6 address of the UE - */ - void SetUeAddress6 (uint64_t imsi, Ipv6Address ueAddr); - - /** - * TracedCallback signature for data Packet reception event. - * - * \param [in] packet The data packet sent from the internet. - */ - typedef void (* RxTracedCallback) - (Ptr packet); - -private: - - // S11 SAP SGW methods - /** - * Create session request function - * \param msg EpcS11SapSgw::CreateSessionRequestMessage - */ - void DoCreateSessionRequest (EpcS11SapSgw::CreateSessionRequestMessage msg); - /** - * Modify bearer request function - * \param msg EpcS11SapSgw::ModifyBearerRequestMessage - */ - void DoModifyBearerRequest (EpcS11SapSgw::ModifyBearerRequestMessage msg); - - /** - * Delete bearer command function - * \param req EpcS11SapSgw::DeleteBearerCommandMessage - */ - void DoDeleteBearerCommand (EpcS11SapSgw::DeleteBearerCommandMessage req); - /** - * Delete bearer response function - * \param req EpcS11SapSgw::DeleteBearerResponseMessage - */ - void DoDeleteBearerResponse (EpcS11SapSgw::DeleteBearerResponseMessage req); - - - /** - * store info for each UE connected to this SGW - */ - class UeInfo : public SimpleRefCount - { -public: - UeInfo (); - - /** - * - * \param tft the Traffic Flow Template of the new bearer to be added - * \param epsBearerId the ID of the EPS Bearer to be activated - * \param teid the TEID of the new bearer - */ - void AddBearer (Ptr tft, uint8_t epsBearerId, uint32_t teid); - - /** - * \brief Function, deletes contexts of bearer on SGW and PGW side - * \param bearerId the Bearer Id whose contexts to be removed - */ - void RemoveBearer (uint8_t bearerId); - - /** - * - * - * \param p the IP packet from the internet to be classified - * \param protocolNumber the protocol number of the IP packet - * - * \return the corresponding bearer ID > 0 identifying the bearer - * among all the bearers of this UE; returns 0 if no bearers - * matches with the previously declared TFTs - */ - uint32_t Classify (Ptr p, uint16_t protocolNumber); - - /** - * \return the address of the eNB to which the UE is connected - */ - Ipv4Address GetEnbAddr (); - - /** - * set the address of the eNB to which the UE is connected - * - * \param addr the address of the eNB - */ - void SetEnbAddr (Ipv4Address addr); - - /** - * \return the IPv4 address of the UE - */ - Ipv4Address GetUeAddr (); - - /** - * set the IPv4 address of the UE - * - * \param addr the IPv4 address of the UE - */ - void SetUeAddr (Ipv4Address addr); - - /** - * \return the IPv6 address of the UE - */ - Ipv6Address GetUeAddr6 (); - - /** - * set the IPv6 address of the UE - * - * \param addr the IPv6 address of the UE - */ - void SetUeAddr6 (Ipv6Address addr); - - private: - EpcTftClassifier m_tftClassifier; ///< TFT classifier - Ipv4Address m_enbAddr; ///< ENB IPv4 address - Ipv4Address m_ueAddr; ///< UE IPv4 address - Ipv6Address m_ueAddr6; ///< UE IPv6 address - std::map m_teidByBearerIdMap; ///< TEID By bearer ID Map - }; - - - /** - * UDP socket to send and receive GTP-U packets to and from the S1-U interface - */ - Ptr m_s1uSocket; - - /** - * TUN VirtualNetDevice used for tunneling/detunneling IP packets - * from/to the internet over GTP-U/UDP/IP on the S1 interface - */ - Ptr m_tunDevice; - - /** - * Map telling for each UE IPv4 address the corresponding UE info - */ - std::map > m_ueInfoByAddrMap; - - /** - * Map telling for each UE IPv6 address the corresponding UE info - */ - std::map > m_ueInfoByAddrMap6; - - /** - * Map telling for each IMSI the corresponding UE info - */ - std::map > m_ueInfoByImsiMap; - - /** - * UDP port to be used for GTP - */ - uint16_t m_gtpuUdpPort; - - /** - * TEID count - */ - uint32_t m_teidCount; - - /** - * MME side of the S11 SAP - * - */ - EpcS11SapMme* m_s11SapMme; - - /** - * SGW side of the S11 SAP - * - */ - EpcS11SapSgw* m_s11SapSgw; - - /// EnbInfo structure - struct EnbInfo - { - Ipv4Address enbAddr; ///< eNB IPv4 address - Ipv4Address sgwAddr; ///< SGW IPV4 address - }; - - std::map m_enbInfoByCellId; ///< eNB info by cell ID - - /** - * \brief Callback to trace RX (reception) data packets at Tun Net Device from internet. - */ - TracedCallback > m_rxTunPktTrace; - - /** - * \brief Callback to trace RX (reception) data packets from S1-U socket. - */ - TracedCallback > m_rxS1uPktTrace; -}; - -} //namespace ns3 - -#endif /* EPC_SGW_PGW_APPLICATION_H */ - diff --git a/src/lte/wscript b/src/lte/wscript index b40f717e7..19b88811b 100644 --- a/src/lte/wscript +++ b/src/lte/wscript @@ -43,6 +43,7 @@ def build(bld): 'helper/lte-helper.cc', 'helper/lte-stats-calculator.cc', 'helper/epc-helper.cc', + 'helper/no-backhaul-epc-helper.cc', 'helper/point-to-point-epc-helper.cc', 'helper/radio-bearer-stats-calculator.cc', 'helper/radio-bearer-stats-connector.cc', @@ -86,7 +87,6 @@ def build(bld): 'model/epc-gtpu-header.cc', 'model/epc-gtpc-header.cc', 'model/epc-enb-application.cc', - 'model/epc-sgw-pgw-application.cc', 'model/epc-sgw-application.cc', 'model/epc-pgw-application.cc', 'model/epc-mme-application.cc', @@ -103,7 +103,6 @@ def build(bld): 'model/lte-as-sap.cc', 'model/epc-ue-nas.cc', 'model/lte-harq-phy.cc', - 'model/epc-mme.cc', 'model/lte-asn1-header.cc', 'model/lte-rrc-header.cc', 'model/lte-handover-management-sap.cc', @@ -238,6 +237,7 @@ def build(bld): 'helper/lte-helper.h', 'helper/lte-stats-calculator.h', 'helper/epc-helper.h', + 'helper/no-backhaul-epc-helper.h', 'helper/point-to-point-epc-helper.h', 'helper/phy-stats-calculator.h', 'helper/mac-stats-calculator.h', @@ -281,7 +281,6 @@ def build(bld): 'model/epc-gtpu-header.h', 'model/epc-gtpc-header.h', 'model/epc-enb-application.h', - 'model/epc-sgw-pgw-application.h', 'model/epc-sgw-application.h', 'model/epc-pgw-application.h', 'model/epc-mme-application.h', @@ -298,7 +297,6 @@ def build(bld): 'model/lte-as-sap.h', 'model/epc-ue-nas.h', 'model/lte-harq-phy.h', - 'model/epc-mme.h', 'model/lte-asn1-header.h', 'model/lte-rrc-header.h', 'model/lte-handover-management-sap.h',