Merge branch 'backhaul-update' into 'master'

lte: New customizable backhaul

See merge request nsnam/ns-3-dev!68
This commit is contained in:
Manuel Requena
2019-06-04 16:06:26 +00:00
18 changed files with 1387 additions and 2452 deletions

View File

@@ -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

View File

@@ -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<Node> pgw = epcHelper->GetPgwNode ();
// Create a single RemoteHost
// Create a single RemoteHost
NodeContainer remoteHostContainer;
remoteHostContainer.Create (1);
Ptr<Node> 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<Ipv4StaticRouting> remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject<Ipv4> ());
remoteHostStaticRouting->AddNetworkRouteTo (epcHelper->GetEpcIpv4NetworkAddress (), Ipv4Mask ("255.255.0.0"), 1);
Ptr<Ipv4StaticRouting> remoteHostStaticRouting;
remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject<Ipv4> ());
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<Node> ue = ueNodes.Get (u);
Ptr<NetDevice> ueLteDevice = ueLteDevs.Get (u);
Ipv4InterfaceContainer ueIpIface = epcHelper->AssignUeIpv4Address (NetDeviceContainer (ueLteDevice));
// set the default gateway for the UE
Ptr<Ipv4StaticRouting> ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ue->GetObject<Ipv4> ());
ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress (), 1);
}
// assign IP address to UEs
for (uint32_t u = 0; u < ueNodes.GetN (); ++u)
{
Ptr<Node> ue = ueNodes.Get (u);
Ptr<NetDevice> ueLteDevice = ueLteDevs.Get (u);
Ipv4InterfaceContainer ueIpIface;
ueIpIface = epcHelper->AssignUeIpv4Address (NetDeviceContainer (ueLteDevice));
// set the default gateway for the UE
Ptr<Ipv4StaticRouting> ueStaticRouting;
ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ue->GetObject<Ipv4> ());
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<EpcTft> tft = Create<EpcTft> ();
EpcTft::PacketFilter pf;
pf.localPortStart = 1234;
pf.localPortEnd = 1234;
tft->Add (pf);
lteHelper->ActivateDedicatedEpsBearer (ueLteDevs, EpsBearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT), tft);
Ptr<EpcTft> tft = Create<EpcTft> ();
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> lteHelper = CreateObject<LteHelper> ();
Ptr<NoBackhaulEpcHelper> epcHelper = CreateObject<NoBackhaulEpcHelper> ();
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<Node> 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<Node> 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<NetDevice> sgwDev = sgwEnbDevices.Get (0);
Ipv4InterfaceContainer sgwEnbIpIfaces = s1uIpv4AddressHelper.Assign (sgwEnbDevices);
Ipv4Address sgwS1uAddress = sgwEnbIpIfaces.GetAddress (0);
for (uint16_t i = 0; i < enbNodes.GetN (); ++i)
{
Ptr<Node> 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:

View File

@@ -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 <manuel.requena@cttc.es>
*/
#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> lteHelper = CreateObject<LteHelper> ();
Ptr<EpcHelper> epcHelper;
if (!useHelper)
{
epcHelper = CreateObject<NoBackhaulEpcHelper> ();
}
else
{
epcHelper = CreateObject<PointToPointEpcHelper> ();
}
lteHelper->SetEpcHelper (epcHelper);
Ptr<Node> pgw = epcHelper->GetPgwNode ();
// Create a single RemoteHost
NodeContainer remoteHostContainer;
remoteHostContainer.Create (1);
Ptr<Node> 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<Ipv4StaticRouting> remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject<Ipv4> ());
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<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
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<Node> sgw = epcHelper->GetSgwNode ();
// Install Mobility Model for SGW
Ptr<ListPositionAllocator> positionAlloc2 = CreateObject<ListPositionAllocator> ();
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<Node> 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<Node> ueNode = ueNodes.Get (u);
// Set the default gateway for the UE
Ptr<Ipv4StaticRouting> ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ueNode->GetObject<Ipv4> ());
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;
}

View File

@@ -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'

View File

@@ -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 <manuel.requena@cttc.es>
*/
#include <ns3/emu-epc-helper.h>
#include <ns3/log.h>
#include <ns3/inet-socket-address.h>
#include <ns3/mac48-address.h>
#include <ns3/eps-bearer.h>
#include <ns3/ipv4-address.h>
#include <ns3/ipv6-address.h>
#include <ns3/internet-stack-helper.h>
#include <ns3/packet-socket-helper.h>
#include <ns3/packet-socket-address.h>
#include <ns3/epc-enb-application.h>
#include <ns3/epc-sgw-pgw-application.h>
#include <ns3/emu-fd-net-device-helper.h>
#include "ns3/ipv6-static-routing.h"
#include "ns3/ipv6-static-routing-helper.h"
#include <ns3/lte-enb-rrc.h>
#include <ns3/epc-x2.h>
#include <ns3/lte-enb-net-device.h>
#include <ns3/lte-ue-net-device.h>
#include <ns3/epc-mme.h>
#include <ns3/epc-ue-nas.h>
#include <ns3/string.h>
#include <ns3/abort.h>
#include <ns3/ipv4-address-generator.h>
#include <ns3/ipv6-address-generator.h>
#include <ns3/icmpv6-l4-protocol.h>
#include <iomanip>
#include <iostream>
#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<Node> sgw = GetSgwNode ();
NetDeviceContainer sgwDevices = emu.Install (sgw);
Ptr<NetDevice> 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<EpcHelper> ()
.SetGroupName("Lte")
.AddConstructor<EmuEpcHelper> ()
.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<Node> ();
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<Ipv6StaticRouting> pgwStaticRouting = ipv6RoutingHelper.GetStaticRouting (m_sgwPgw->GetObject<Ipv6> ());
pgwStaticRouting->AddNetworkRouteTo ("7777:f00d::", Ipv6Prefix (64), Ipv6Address ("::"), 1, 0);
// create S1-U socket
Ptr<Socket> 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<VirtualNetDevice> ();
// 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<EpcSgwPgwApplication> (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<EpcMme> ();
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<NetDevice> 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<bool, Ptr<Packet>, const Address&, const Address&, uint16_t> ());
m_tunDevice = 0;
m_sgwPgwApp = 0;
m_sgwPgw->Dispose ();
NoBackhaulEpcHelper::DoDispose ();
}
@@ -211,88 +118,32 @@ EmuEpcHelper::AddEnb (Ptr<Node> enb, Ptr<NetDevice> 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<Ipv4> ()->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<NetDevice> 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<Ipv4> ()->GetNInterfaces ());
NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB after installing emu dev: " << enb->GetObject<Ipv4> ()->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<Ipv4> ()->GetNInterfaces ());
Ipv4Address enbAddress = enbIpIfaces.GetAddress (0);
Ipv4Address sgwAddress = m_sgwIpIfaces.GetAddress (0);
// create S1-U socket for the ENB
Ptr<Socket> 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<Socket> 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<Socket> 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<EpcEnbApplication> enbApp = CreateObject<EpcEnbApplication> (enbLteSocket, enbLteSocket6, enbS1uSocket, enbAddress, sgwAddress, cellId);
enb->AddApplication (enbApp);
NS_ASSERT (enb->GetNApplications () == 1);
NS_ASSERT_MSG (enb->GetApplication (0)->GetObject<EpcEnbApplication> () != 0, "cannot retrieve EpcEnbApplication");
NS_LOG_LOGIC ("enb: " << enb << ", enb->GetApplication (0): " << enb->GetApplication (0));
NS_LOG_INFO ("Create EpcX2 entity");
Ptr<EpcX2> x2 = CreateObject<EpcX2> ();
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<Node> enb1, Ptr<Node> enb2)
enb2LteDev->GetRrc ()->AddX2Neighbour (enb1LteDev->GetCellId ());
}
void
EmuEpcHelper::AddUe (Ptr<NetDevice> ueDevice, uint64_t imsi)
{
NS_LOG_FUNCTION (this << imsi << ueDevice );
m_mme->AddUe (imsi);
m_sgwPgwApp->AddUe (imsi);
}
uint8_t
EmuEpcHelper::ActivateEpsBearer (Ptr<NetDevice> ueDevice, uint64_t imsi, Ptr<EpcTft> 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<Node> ueNode = ueDevice->GetNode ();
Ptr<Ipv4> ueIpv4 = ueNode->GetObject<Ipv4> ();
Ptr<Ipv6> ueIpv6 = ueNode->GetObject<Ipv6> ();
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<LteUeNetDevice> ueLteDevice = ueDevice->GetObject<LteUeNetDevice> ();
if (ueLteDevice)
{
Simulator::ScheduleNow (&EpcUeNas::ActivateEpsBearer, ueLteDevice->GetNas (), bearer, tft);
}
return bearerId;
}
Ptr<Node>
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<Icmpv6L4Protocol> icmpv6 = (*iter)->GetNode ()->GetObject<Icmpv6L4Protocol> ();
icmpv6->SetAttribute ("DAD", BooleanValue (false));
}
return m_uePgwAddressHelper6.Assign (ueDevices);
}
Ipv4Address
EmuEpcHelper::GetUeDefaultGatewayAddress ()
{
// return the address of the tun device
return m_sgwPgw->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal ();
}
Ipv6Address
EmuEpcHelper::GetUeDefaultGatewayAddress6 ()
{
// return the address of the tun device 6
return m_sgwPgw->GetObject<Ipv6> ()->GetAddress (1, 1).GetAddress ();
}
} // namespace ns3

View File

@@ -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 <ns3/object.h>
#include <ns3/ipv4-address-helper.h>
#include <ns3/ipv6-address-helper.h>
#include <ns3/data-rate.h>
#include <ns3/epc-tft.h>
#include <ns3/eps-bearer.h>
#include <ns3/epc-helper.h>
#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<Node> enbNode, Ptr<NetDevice> lteEnbNetDevice, uint16_t cellId);
virtual void AddUe (Ptr<NetDevice> ueLteDevice, uint64_t imsi);
virtual void AddX2Interface (Ptr<Node> enbNode1, Ptr<Node> enbNode2);
virtual uint8_t ActivateEpsBearer (Ptr<NetDevice> ueLteDevice, uint64_t imsi, Ptr<EpcTft> tft, EpsBearer bearer);
virtual Ptr<Node> 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<Node> m_sgwPgw;
/**
* SGW-PGW application
*/
Ptr<EpcSgwPgwApplication> m_sgwPgwApp;
/**
* TUN device containing IPv4 address and implementing tunneling of user data over GTP-U/UDP/IP
*/
Ptr<VirtualNetDevice> m_tunDevice;
/**
* MME network element
*/
Ptr<EpcMme> 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<uint64_t, Ptr<NetDevice> > 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

View File

@@ -97,6 +97,17 @@ public:
*/
virtual void AddX2Interface (Ptr<Node> enbNode1, Ptr<Node> 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<Node> 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<Node> 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<Node> GetPgwNode () const = 0;

View File

@@ -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 <manuel.requena@cttc.es>
* (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<Node> ();
m_sgw = CreateObject<Node> ();
m_mme = CreateObject<Node> ();
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<Ipv6StaticRouting> pgwStaticRouting = ipv6RoutingHelper.GetStaticRouting (m_pgw->GetObject<Ipv6> ());
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<VirtualNetDevice> ();
// 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<Ipv4> ()->GetNInterfaces ());
NS_LOG_LOGIC ("IPv4 ifaces of the SGW after installing p2p dev: " << m_sgw->GetObject<Ipv4> ()->GetNInterfaces ());
Ptr<NetDevice> pgwDev = pgwSgwDevices.Get (0);
Ptr<NetDevice> 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<Ipv4> ()->GetNInterfaces ());
NS_LOG_LOGIC ("IPv4 ifaces of the SGW after assigning Ipv4 addr to S5 dev: " << m_sgw->GetObject<Ipv4> ()->GetNInterfaces ());
Ipv4Address pgwS5Address = pgwSgwIpIfaces.GetAddress (0);
Ipv4Address sgwS5Address = pgwSgwIpIfaces.GetAddress (1);
// Create S5-U socket in the PGW
Ptr<Socket> 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<Socket> 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<EpcPgwApplication> (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<Socket> 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<Socket> 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<Socket> 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<EpcSgwApplication> (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<Ipv4> ()->GetNInterfaces ());
NS_LOG_LOGIC ("SGW's IPv4 ifaces after installing p2p dev: " << m_sgw->GetObject<Ipv4> ()->GetNInterfaces ());
Ptr<NetDevice> mmeDev = mmeSgwDevices.Get (0);
Ptr<NetDevice> 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<Ipv4> ()->GetNInterfaces ());
NS_LOG_LOGIC ("SGW's IPv4 ifaces after assigning Ipv4 addr to S11 dev: " << m_sgw->GetObject<Ipv4> ()->GetNInterfaces ());
Ipv4Address mmeS11Address = mmeSgwIpIfaces.GetAddress (0);
Ipv4Address sgwS11Address = mmeSgwIpIfaces.GetAddress (1);
// Create S11 socket in the MME
Ptr<Socket> 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<Socket> 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<EpcMmeApplication> ();
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<EpcHelper> ()
.SetGroupName("Lte")
.AddConstructor<NoBackhaulEpcHelper> ()
.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<uint16_t> ())
.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<uint16_t> ())
.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<uint16_t> ())
.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<bool, Ptr<Packet>, 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<Node> enb, Ptr<NetDevice> 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<Ipv4> ()->GetNInterfaces ());
// create LTE socket for the ENB
Ptr<Socket> 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<Socket> 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<EpcEnbApplication> enbApp = CreateObject<EpcEnbApplication> (enbLteSocket, enbLteSocket6, cellId);
enb->AddApplication (enbApp);
NS_ASSERT (enb->GetNApplications () == 1);
NS_ASSERT_MSG (enb->GetApplication (0)->GetObject<EpcEnbApplication> () != 0, "cannot retrieve EpcEnbApplication");
NS_LOG_LOGIC ("enb: " << enb << ", enb->GetApplication (0): " << enb->GetApplication (0));
NS_LOG_INFO ("Create EpcX2 entity");
Ptr<EpcX2> x2 = CreateObject<EpcX2> ();
enb->AggregateObject (x2);
}
void
NoBackhaulEpcHelper::AddX2Interface (Ptr<Node> enb1, Ptr<Node> 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<Ipv4> ()->GetNInterfaces ());
NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB #2 after installing p2p dev: " << enb2->GetObject<Ipv4> ()->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<Ipv4> ()->GetNInterfaces ());
NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB #2 after assigning Ipv4 addr to X2 dev: " << enb2->GetObject<Ipv4> ()->GetNInterfaces ());
Ipv4Address enb1X2Address = enbIpIfaces.GetAddress (0);
Ipv4Address enb2X2Address = enbIpIfaces.GetAddress (1);
// Add X2 interface to both eNBs' X2 entities
Ptr<EpcX2> enb1X2 = enb1->GetObject<EpcX2> ();
Ptr<EpcX2> enb2X2 = enb2->GetObject<EpcX2> ();
Ptr<NetDevice> enb1LteDev = enb1->GetDevice (0);
Ptr<NetDevice> enb2LteDev = enb2->GetDevice (0);
DoAddX2Interface (enb1X2, enb1LteDev, enb1X2Address, enb2X2, enb2LteDev, enb2X2Address);
}
void
NoBackhaulEpcHelper::DoAddX2Interface (const Ptr<EpcX2> &enb1X2, const Ptr<NetDevice> &enb1LteDev,
const Ipv4Address &enb1X2Address,
const Ptr<EpcX2> &enb2X2, const Ptr<NetDevice> &enb2LteDev,
const Ipv4Address &enb2X2Address) const
{
NS_LOG_FUNCTION (this);
Ptr<LteEnbNetDevice> enb1LteDevice = enb1LteDev->GetObject<LteEnbNetDevice> ();
Ptr<LteEnbNetDevice> enb2LteDevice = enb2LteDev->GetObject<LteEnbNetDevice> ();
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<NetDevice> ueDevice, uint64_t imsi)
{
NS_LOG_FUNCTION (this << imsi << ueDevice);
m_mmeApp->AddUe (imsi);
m_pgwApp->AddUe (imsi);
}
uint8_t
NoBackhaulEpcHelper::ActivateEpsBearer (Ptr<NetDevice> ueDevice, uint64_t imsi,
Ptr<EpcTft> 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<Node> ueNode = ueDevice->GetNode ();
Ptr<Ipv4> ueIpv4 = ueNode->GetObject<Ipv4> ();
Ptr<Ipv6> ueIpv6 = ueNode->GetObject<Ipv6> ();
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<NetDevice> &ueDevice,
const Ptr<EpcTft> &tft,
const EpsBearer &bearer) const
{
NS_LOG_FUNCTION (this);
Ptr<LteUeNetDevice> ueLteDevice = DynamicCast<LteUeNetDevice> (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<Node>
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<Icmpv6L4Protocol> icmpv6 = (*iter)->GetNode ()->GetObject<Icmpv6L4Protocol> ();
icmpv6->SetAttribute ("DAD", BooleanValue (false));
}
return m_uePgwAddressHelper6.Assign (ueDevices);
}
Ipv4Address
NoBackhaulEpcHelper::GetUeDefaultGatewayAddress ()
{
// return the address of the tun device
return m_pgw->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal ();
}
Ipv6Address
NoBackhaulEpcHelper::GetUeDefaultGatewayAddress6 ()
{
// return the address of the tun device
return m_pgw->GetObject<Ipv6> ()->GetAddress (1, 1).GetAddress ();
}
Ptr<Node>
NoBackhaulEpcHelper::GetSgwNode () const
{
return m_sgw;
}
void
NoBackhaulEpcHelper::AddS1Interface (Ptr<Node> enb, Ipv4Address enbAddress, Ipv4Address sgwAddress, uint16_t cellId)
{
NS_LOG_FUNCTION (this << enb << enbAddress << sgwAddress << cellId);
// create S1-U socket for the ENB
Ptr<Socket> enbS1uSocket = Socket::CreateSocket (enb, TypeId::LookupByName ("ns3::UdpSocketFactory"));
int retval = enbS1uSocket->Bind (InetSocketAddress (enbAddress, m_gtpuUdpPort));
NS_ASSERT (retval == 0);
Ptr<EpcEnbApplication> enbApp = enb->GetApplication (0)->GetObject<EpcEnbApplication> ();
NS_ASSERT_MSG (enbApp != 0, "EpcEnbApplication not available");
enbApp->AddS1Interface (enbS1uSocket, enbAddress, sgwAddress);
NS_LOG_INFO ("Connect S1-AP interface");
if (cellId == 0)
{
Ptr<LteEnbNetDevice> enbLteDev = enb->GetDevice (0)->GetObject<LteEnbNetDevice> ();
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

View File

@@ -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 <manuel.requena@cttc.es>
* (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<Node> enbNode, Ptr<NetDevice> lteEnbNetDevice, uint16_t cellId);
virtual void AddUe (Ptr<NetDevice> ueLteDevice, uint64_t imsi);
virtual void AddX2Interface (Ptr<Node> enbNode1, Ptr<Node> enbNode2);
virtual void AddS1Interface (Ptr<Node> enb, Ipv4Address enbAddress, Ipv4Address sgwAddress, uint16_t cellId = 0);
virtual uint8_t ActivateEpsBearer (Ptr<NetDevice> ueLteDevice, uint64_t imsi, Ptr<EpcTft> tft, EpsBearer bearer);
virtual Ptr<Node> GetSgwNode () const;
virtual Ptr<Node> 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<EpcX2> &enb1X2, const Ptr<NetDevice> &enb1LteDev,
const Ipv4Address &enb1X2Address,
const Ptr<EpcX2> &enb2X2, const Ptr<NetDevice> &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<NetDevice> &ueDevice,
const Ptr<EpcTft> &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<Node> m_pgw;
/**
* SGW network element
*/
Ptr<Node> m_sgw;
/**
* MME network element
*/
Ptr<Node> m_mme;
/**
* SGW application
*/
Ptr<EpcSgwApplication> m_sgwApp;
/**
* PGW application
*/
Ptr<EpcPgwApplication> m_pgwApp;
/**
* MME application
*/
Ptr<EpcMmeApplication> m_mmeApp;
/**
* TUN device implementing tunneling of user data over GTP-U/UDP/IP
*/
Ptr<VirtualNetDevice> 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<uint64_t, Ptr<NetDevice> > 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

View File

@@ -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 <jnin@cttc.es>
* Nicola Baldo <nbaldo@cttc.es>
* Manuel Requena <manuel.requena@cttc.es>
* (most of the code refactored to no-backhaul-epc-helper.cc)
*/
#include <ns3/point-to-point-epc-helper.h>
#include <ns3/log.h>
#include <ns3/inet-socket-address.h>
#include <ns3/mac48-address.h>
#include <ns3/string.h>
#include <ns3/boolean.h>
#include <ns3/eps-bearer.h>
#include <ns3/ipv4-address.h>
#include <ns3/internet-stack-helper.h>
#include <ns3/point-to-point-helper.h>
#include <ns3/packet-socket-helper.h>
#include <ns3/packet-socket-address.h>
#include <ns3/epc-enb-application.h>
#include "ns3/ipv6-static-routing.h"
#include "ns3/ipv6-static-routing-helper.h"
#include <ns3/epc-pgw-application.h>
#include <ns3/epc-sgw-application.h>
#include <ns3/epc-mme-application.h>
#include "ns3/boolean.h"
#include "ns3/string.h"
#include "ns3/log.h"
#include "ns3/point-to-point-helper.h"
#include <ns3/lte-enb-rrc.h>
#include <ns3/epc-x2.h>
#include <ns3/lte-enb-net-device.h>
#include <ns3/lte-ue-net-device.h>
#include <ns3/epc-ue-nas.h>
#include <ns3/ipv4-address-generator.h>
#include <ns3/ipv6-address-generator.h>
#include <ns3/icmpv6-l4-protocol.h>
#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<Node> ();
m_sgw = CreateObject<Node> ();
m_mme = CreateObject<Node> ();
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<Ipv6StaticRouting> pgwStaticRouting = ipv6RoutingHelper.GetStaticRouting (m_pgw->GetObject<Ipv6> ());
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<VirtualNetDevice> ();
// 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<Ipv4> ()->GetNInterfaces ());
NS_LOG_LOGIC ("IPv4 ifaces of the SGW after installing p2p dev: " << m_sgw->GetObject<Ipv4> ()->GetNInterfaces ());
Ptr<NetDevice> pgwDev = pgwSgwDevices.Get (0);
Ptr<NetDevice> 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<Ipv4> ()->GetNInterfaces ());
NS_LOG_LOGIC ("IPv4 ifaces of the SGW after assigning Ipv4 addr to S5 dev: " << m_sgw->GetObject<Ipv4> ()->GetNInterfaces ());
Ipv4Address pgwS5Address = pgwSgwIpIfaces.GetAddress (0);
Ipv4Address sgwS5Address = pgwSgwIpIfaces.GetAddress (1);
// Create S5-U socket in the PGW
Ptr<Socket> 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<Socket> 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<EpcPgwApplication> (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<Socket> 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<Socket> 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<Socket> 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<EpcSgwApplication> (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<Ipv4> ()->GetNInterfaces ());
NS_LOG_LOGIC ("SGW's IPv4 ifaces after installing p2p dev: " << m_sgw->GetObject<Ipv4> ()->GetNInterfaces ());
Ptr<NetDevice> mmeDev = mmeSgwDevices.Get (0);
Ptr<NetDevice> 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<Ipv4> ()->GetNInterfaces ());
NS_LOG_LOGIC ("SGW's IPv4 ifaces after assigning Ipv4 addr to S11 dev: " << m_sgw->GetObject<Ipv4> ()->GetNInterfaces ());
Ipv4Address mmeS11Address = mmeSgwIpIfaces.GetAddress (0);
Ipv4Address sgwS11Address = mmeSgwIpIfaces.GetAddress (1);
// Create S11 socket in the MME
Ptr<Socket> 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<Socket> 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<EpcMmeApplication> ();
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<EpcHelper> ()
.SetGroupName("Lte")
.SetParent<NoBackhaulEpcHelper> ()
.SetGroupName ("Lte")
.AddConstructor<PointToPointEpcHelper> ()
.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<uint16_t> ())
.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<uint16_t> ())
.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<uint16_t> ())
.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<uint16_t> ())
.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<bool, Ptr<Packet>, 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<Node> enb, Ptr<NetDevice> 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<Ipv4> ()->GetNInterfaces ());
// create a point to point link between the eNB and the SGW with
// the corresponding new NetDevices on each side
Ptr<Node> 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<Ipv4> ()->GetNInterfaces ());
Ptr<NetDevice> enbDev = enbSgwDevices.Get (0);
Ptr<NetDevice> 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<Ipv4> ()->GetNInterfaces ());
Ipv4Address enbS1uAddress = enbSgwIpIfaces.GetAddress (0);
Ipv4Address sgwS1uAddress = enbSgwIpIfaces.GetAddress (1);
// create S1-U socket for the ENB
Ptr<Socket> 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<Socket> 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<Socket> 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<EpcEnbApplication> enbApp = CreateObject<EpcEnbApplication> (enbLteSocket, enbLteSocket6, enbS1uSocket, enbS1uAddress, sgwS1uAddress, cellId);
enb->AddApplication (enbApp);
NS_ASSERT (enb->GetNApplications () == 1);
NS_ASSERT_MSG (enb->GetApplication (0)->GetObject<EpcEnbApplication> () != 0, "cannot retrieve EpcEnbApplication");
NS_LOG_LOGIC ("enb: " << enb << ", enb->GetApplication (0): " << enb->GetApplication (0));
NS_LOG_INFO ("Create EpcX2 entity");
Ptr<EpcX2> x2 = CreateObject<EpcX2> ();
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<Node> enb1, Ptr<Node> 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<Ipv4> ()->GetNInterfaces ());
NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB #2 after installing p2p dev: " << enb2->GetObject<Ipv4> ()->GetNInterfaces ());
Ptr<NetDevice> enb1Dev = enbDevices.Get (0);
Ptr<NetDevice> 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<Ipv4> ()->GetNInterfaces ());
NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB #2 after assigning Ipv4 addr to X2 dev: " << enb2->GetObject<Ipv4> ()->GetNInterfaces ());
Ipv4Address enb1X2Address = enbIpIfaces.GetAddress (0);
Ipv4Address enb2X2Address = enbIpIfaces.GetAddress (1);
// Add X2 interface to both eNBs' X2 entities
Ptr<EpcX2> enb1X2 = enb1->GetObject<EpcX2> ();
Ptr<EpcX2> enb2X2 = enb2->GetObject<EpcX2> ();
Ptr<NetDevice> enb1LteDev = enb1->GetDevice (0);
Ptr<NetDevice> enb2LteDev = enb2->GetDevice (0);
DoAddX2Interface (enb1X2, enb1LteDev, enb1X2Address, enb2X2, enb2LteDev, enb2X2Address);
}
void
PointToPointEpcHelper::DoAddX2Interface (const Ptr<EpcX2> &enb1X2, const Ptr<NetDevice> &enb1LteDev,
const Ipv4Address &enb1X2Address,
const Ptr<EpcX2> &enb2X2, const Ptr<NetDevice> &enb2LteDev,
const Ipv4Address &enb2X2Address) const
{
NS_LOG_FUNCTION (this);
Ptr<LteEnbNetDevice> enb1LteDevice = enb1LteDev->GetObject<LteEnbNetDevice> ();
Ptr<LteEnbNetDevice> enb2LteDevice = enb2LteDev->GetObject<LteEnbNetDevice> ();
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<NetDevice> ueDevice, uint64_t imsi)
{
NS_LOG_FUNCTION (this << imsi << ueDevice);
m_mmeApp->AddUe (imsi);
m_pgwApp->AddUe (imsi);
}
uint8_t
PointToPointEpcHelper::ActivateEpsBearer (Ptr<NetDevice> ueDevice, uint64_t imsi,
Ptr<EpcTft> 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<Node> ueNode = ueDevice->GetNode ();
Ptr<Ipv4> ueIpv4 = ueNode->GetObject<Ipv4> ();
Ptr<Ipv6> ueIpv6 = ueNode->GetObject<Ipv6> ();
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<NetDevice> &ueDevice,
const Ptr<EpcTft> &tft,
const EpsBearer &bearer) const
{
NS_LOG_FUNCTION (this);
Ptr<LteUeNetDevice> ueLteDevice = DynamicCast<LteUeNetDevice> (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<Node>
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<Icmpv6L4Protocol> icmpv6 = (*iter)->GetNode ()->GetObject<Icmpv6L4Protocol> ();
icmpv6->SetAttribute ("DAD", BooleanValue (false));
}
return m_uePgwAddressHelper6.Assign (ueDevices);
}
Ipv4Address
PointToPointEpcHelper::GetUeDefaultGatewayAddress ()
{
// return the address of the tun device
return m_pgw->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal ();
}
Ipv6Address
PointToPointEpcHelper::GetUeDefaultGatewayAddress6 ()
{
// return the address of the tun device
return m_pgw->GetObject<Ipv6> ()->GetAddress (1, 1).GetAddress ();
NoBackhaulEpcHelper::AddS1Interface (enb, enbS1uAddress, sgwS1uAddress, cellId);
}
} // namespace ns3

View File

@@ -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 <jnin@cttc.es>
* Nicola Baldo <nbaldo@cttc.es>
* Manuel Requena <manuel.requena@cttc.es>
* (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 <ns3/object.h>
#include <ns3/ipv4-address-helper.h>
#include <ns3/ipv6-address-helper.h>
#include <ns3/data-rate.h>
#include <ns3/epc-tft.h>
#include <ns3/eps-bearer.h>
#include <ns3/epc-helper.h>
#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<Node> enbNode, Ptr<NetDevice> lteEnbNetDevice, uint16_t cellId);
virtual void AddUe (Ptr<NetDevice> ueLteDevice, uint64_t imsi);
virtual void AddX2Interface (Ptr<Node> enbNode1, Ptr<Node> enbNode2);
virtual uint8_t ActivateEpsBearer (Ptr<NetDevice> ueLteDevice, uint64_t imsi, Ptr<EpcTft> tft, EpsBearer bearer);
virtual Ptr<Node> 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<EpcX2> &enb1X2, const Ptr<NetDevice> &enb1LteDev,
const Ipv4Address &enb1X2Address,
const Ptr<EpcX2> &enb2X2, const Ptr<NetDevice> &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<NetDevice> &ueDevice,
const Ptr<EpcTft> &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<Node> m_sgw;
/**
* PGW network element
*/
Ptr<Node> m_pgw;
/**
* MME network element
*/
Ptr<Node> m_mme;
/**
* SGW application
*/
Ptr<EpcSgwApplication> m_sgwApp;
/**
* PGW application
*/
Ptr<EpcPgwApplication> m_pgwApp;
/**
* MME application
*/
Ptr<EpcMmeApplication> m_mmeApp;
/**
* TUN device implementing tunneling of user data over GTP-U/UDP/IP
*/
Ptr<VirtualNetDevice> 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<uint64_t, Ptr<NetDevice> > 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

View File

@@ -87,19 +87,16 @@ EpcEnbApplication::DoDispose (void)
delete m_s1apSapEnb;
}
EpcEnbApplication::EpcEnbApplication (Ptr<Socket> lteSocket, Ptr<Socket> lteSocket6, Ptr<Socket> s1uSocket, Ipv4Address enbS1uAddress, Ipv4Address sgwS1uAddress, uint16_t cellId)
EpcEnbApplication::EpcEnbApplication (Ptr<Socket> lteSocket, Ptr<Socket> 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<EpcEnbApplication> (this);
@@ -107,6 +104,18 @@ EpcEnbApplication::EpcEnbApplication (Ptr<Socket> lteSocket, Ptr<Socket> lteSock
}
void
EpcEnbApplication::AddS1Interface (Ptr<Socket> 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);

View File

@@ -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<Socket> lteSocket, Ptr<Socket> 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<Socket> lteSocket, Ptr<Socket> lteSocket6, Ptr<Socket> s1uSocket, Ipv4Address enbS1uAddress, Ipv4Address sgwS1uAddress, uint16_t cellId);
void AddS1Interface (Ptr<Socket> s1uSocket, Ipv4Address enbAddress, Ipv4Address sgwAddress);
/**
* Destructor

View File

@@ -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 <nbaldo@cttc.es>
*/
#include <ns3/fatal-error.h>
#include <ns3/log.h>
#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<EpcMme> (this);
m_s11SapMme = new MemberEpcS11SapMme<EpcMme> (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<Object> ()
.SetGroupName("Lte")
.AddConstructor<EpcMme> ()
;
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> enbInfo = Create<EnbInfo> ();
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> ueInfo = Create<UeInfo> ();
ueInfo->imsi = imsi;
ueInfo->mmeUeS1Id = imsi;
m_ueInfoMap[imsi] = ueInfo;
ueInfo->bearerCounter = 0;
}
uint8_t
EpcMme::AddBearer (uint64_t imsi, Ptr<EpcTft> tft, EpsBearer bearer)
{
NS_LOG_FUNCTION (this << imsi);
std::map<uint64_t, Ptr<UeInfo> >::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<uint64_t, Ptr<UeInfo> >::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<BearerInfo>::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<EpcS1apSapMme::ErabSetupItem> 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<EpcS1apSapMme::ErabSwitchedInDownlinkItem> erabToBeSwitchedInDownlinkList)
{
NS_LOG_FUNCTION (this << mmeUeS1Id << enbUeS1Id << gci);
uint64_t imsi = mmeUeS1Id;
std::map<uint64_t, Ptr<UeInfo> >::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<EpcS1apSapEnb::ErabToBeSetupItem> erabToBeSetupList;
for (std::list<EpcS11SapMme::BearerContextCreated>::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<uint64_t, Ptr<UeInfo> >::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<uint16_t, Ptr<EnbInfo> >::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<uint64_t, Ptr<UeInfo> >::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<EpcS1apSapEnb::ErabSwitchedInUplinkItem> erabToBeSwitchedInUplinkList; // unused for now
std::map<uint16_t, Ptr<EnbInfo> >::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<EpcS1apSapMme::ErabToBeReleasedIndication> erabToBeReleaseIndication)
{
NS_LOG_FUNCTION (this << mmeUeS1Id << enbUeS1Id);
uint64_t imsi = mmeUeS1Id;
std::map<uint64_t, Ptr<UeInfo> >::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<EpcS1apSapMme::ErabToBeReleasedIndication>::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<uint64_t, Ptr<UeInfo> >::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<EpcS11SapMme::BearerContextRemoved>::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> ueInfo, uint8_t epsBearerId)
{
NS_LOG_FUNCTION (this << epsBearerId);
for (std::list<BearerInfo>::iterator bit = ueInfo->bearersToBeActivated.begin ();
bit != ueInfo->bearersToBeActivated.end ();
++bit)
{
if (bit->bearerId == epsBearerId)
{
ueInfo->bearersToBeActivated.erase (bit);
break;
}
}
}
} // namespace ns3

View File

@@ -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 <nbaldo@cttc.es>
*/
#ifndef EPC_MME_H
#define EPC_MME_H
#include <ns3/object.h>
#include <ns3/epc-s1ap-sap.h>
#include <ns3/epc-s11-sap.h>
#include <map>
#include <list>
namespace ns3 {
class Node;
class NetDevice;
/**
* \brief This object implements the MME functionality.
*
*/
class EpcMme : public Object
{
/// allow MemberEpcS1apSapMme<EpcMme> class friend access
friend class MemberEpcS1apSapMme<EpcMme>;
/// allow MemberEpcS11SapMme<EpcMme> class friend access
friend class MemberEpcS11SapMme<EpcMme>;
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<EpcTft> 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<EpcS1apSapMme::ErabSetupItem> 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<EpcS1apSapMme::ErabSwitchedInDownlinkItem> 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<EpcS1apSapMme::ErabToBeReleasedIndication> 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<EpcTft> tft; ///< traffic flow template
EpsBearer bearer; ///< bearer QOS characteristics
uint8_t bearerId; ///< bearer ID
};
/**
* Hold info on a UE
*
*/
struct UeInfo : public SimpleRefCount<UeInfo>
{
uint64_t mmeUeS1Id; ///< mmeUeS1Id
uint16_t enbUeS1Id; ///< enbUeS1Id
uint64_t imsi; ///< UE identifier
uint16_t cellId; ///< cell ID
std::list<BearerInfo> bearersToBeActivated; ///< list of bearers to be activated
uint16_t bearerCounter; ///< bearer counter
};
/**
* UeInfo stored by IMSI
*
*/
std::map<uint64_t, Ptr<UeInfo> > 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> ueInfo, uint8_t epsBearerId);
/**
* Hold info on a ENB
*
*/
struct EnbInfo : public SimpleRefCount<EnbInfo>
{
uint16_t gci; ///< GCI
Ipv4Address s1uAddr; ///< IP address
EpcS1apSapEnb* s1apSapEnb; ///< EpcS1apSapEnb
};
/**
* EnbInfo stored by EGCI
*
*/
std::map<uint16_t, Ptr<EnbInfo> > m_enbInfoMap;
EpcS1apSapMme* m_s1apSapMme; ///< EpcS1apSapMme
EpcS11SapMme* m_s11SapMme; ///< EpcS11SapMme
EpcS11SapSgw* m_s11SapSgw; ///< EpcS11SapSgw
};
} // namespace ns3
#endif // EPC_MME_H

View File

@@ -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 <jnin@cttc.cat>
* Nicola Baldo <nbaldo@cttc.cat>
*/
#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<EpcTft> 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<Packet> 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<Object> ()
.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<void, Ptr<Socket> > ());
m_s1uSocket = 0;
delete (m_s11SapSgw);
}
EpcSgwPgwApplication::EpcSgwPgwApplication (const Ptr<VirtualNetDevice> tunDevice, const Ptr<Socket> 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<EpcSgwPgwApplication> (this);
}
EpcSgwPgwApplication::~EpcSgwPgwApplication ()
{
NS_LOG_FUNCTION (this);
}
bool
EpcSgwPgwApplication::RecvFromTunDevice (Ptr<Packet> 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<Packet> 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<Ipv4Address, Ptr<UeInfo> >::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<Ipv6Address, Ptr<UeInfo> >::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> socket)
{
NS_LOG_FUNCTION (this << socket);
NS_ASSERT (socket == m_s1uSocket);
Ptr<Packet> 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> 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> 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> ueInfo = Create<UeInfo> ();
m_ueInfoByImsiMap[imsi] = ueInfo;
}
void
EpcSgwPgwApplication::SetUeAddress (uint64_t imsi, Ipv4Address ueAddr)
{
NS_LOG_FUNCTION (this << imsi << ueAddr);
std::map<uint64_t, Ptr<UeInfo> >::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<uint64_t, Ptr<UeInfo> >::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<uint64_t, Ptr<UeInfo> >::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<uint16_t, EnbInfo>::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<EpcS11SapSgw::BearerContextToBeCreated>::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<uint64_t, Ptr<UeInfo> >::iterator ueit = m_ueInfoByImsiMap.find (imsi);
NS_ASSERT_MSG (ueit != m_ueInfoByImsiMap.end (), "unknown IMSI " << imsi);
uint16_t cellId = req.uli.gci;
std::map<uint16_t, EnbInfo>::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<uint64_t, Ptr<UeInfo> >::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<EpcS11SapSgw::BearerContextToBeRemoved>::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<uint64_t, Ptr<UeInfo> >::iterator ueit = m_ueInfoByImsiMap.find (imsi);
NS_ASSERT_MSG (ueit != m_ueInfoByImsiMap.end (), "unknown IMSI " << imsi);
for (std::list<EpcS11SapSgw::BearerContextRemovedSgwPgw>::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

View File

@@ -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 <jnin@cttc.cat>
* Nicola Baldo <nbaldo@cttc.cat>
*/
#ifndef EPC_SGW_PGW_APPLICATION_H
#define EPC_SGW_PGW_APPLICATION_H
#include <ns3/address.h>
#include <ns3/socket.h>
#include <ns3/virtual-net-device.h>
#include <ns3/traced-callback.h>
#include <ns3/callback.h>
#include <ns3/ptr.h>
#include <ns3/object.h>
#include <ns3/eps-bearer.h>
#include <ns3/epc-tft.h>
#include <ns3/epc-tft-classifier.h>
#include <ns3/lte-common.h>
#include <ns3/application.h>
#include <ns3/epc-s1ap-sap.h>
#include <ns3/epc-s11-sap.h>
#include <map>
namespace ns3 {
/**
* \ingroup lte
*
* This application implements the SGW/PGW functionality.
*/
class EpcSgwPgwApplication : public Application
{
/// allow MemberEpcS11SapSgw<EpcSgwPgwApplication> class friend access
friend class MemberEpcS11SapSgw<EpcSgwPgwApplication>;
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<VirtualNetDevice> tunDevice, const Ptr<Socket> 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> 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> 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> 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> 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> 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<UeInfo>
{
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<EpcTft> 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<Packet> 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<uint8_t, uint32_t> m_teidByBearerIdMap; ///< TEID By bearer ID Map
};
/**
* UDP socket to send and receive GTP-U packets to and from the S1-U interface
*/
Ptr<Socket> m_s1uSocket;
/**
* TUN VirtualNetDevice used for tunneling/detunneling IP packets
* from/to the internet over GTP-U/UDP/IP on the S1 interface
*/
Ptr<VirtualNetDevice> m_tunDevice;
/**
* Map telling for each UE IPv4 address the corresponding UE info
*/
std::map<Ipv4Address, Ptr<UeInfo> > m_ueInfoByAddrMap;
/**
* Map telling for each UE IPv6 address the corresponding UE info
*/
std::map<Ipv6Address, Ptr<UeInfo> > m_ueInfoByAddrMap6;
/**
* Map telling for each IMSI the corresponding UE info
*/
std::map<uint64_t, Ptr<UeInfo> > 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<uint16_t, EnbInfo> m_enbInfoByCellId; ///< eNB info by cell ID
/**
* \brief Callback to trace RX (reception) data packets at Tun Net Device from internet.
*/
TracedCallback<Ptr<Packet> > m_rxTunPktTrace;
/**
* \brief Callback to trace RX (reception) data packets from S1-U socket.
*/
TracedCallback<Ptr<Packet> > m_rxS1uPktTrace;
};
} //namespace ns3
#endif /* EPC_SGW_PGW_APPLICATION_H */

View File

@@ -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',