182 changes: 182 additions & 0 deletions src/lte/examples/lena-ipv6-ue-rh.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2017 Jadavpur University, India
*
* 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: Manoj Kumar Rana <manoj24.rana@gmail.com>
*/

#include "ns3/lte-helper.h"
#include "ns3/epc-helper.h"
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/ipv4-global-routing-helper.h"
#include "ns3/ipv6-static-routing.h"
#include "ns3/internet-module.h"
#include "ns3/mobility-module.h"
#include "ns3/lte-module.h"
#include "ns3/applications-module.h"
#include "ns3/point-to-point-helper.h"
#include "ns3/config-store.h"

using namespace ns3;

/**
* Sample simulation script for LTE+EPC. It instantiates several eNodeB,
* attaches one UE per eNodeB starts a flow for each UE to and from a remote host.
*/

NS_LOG_COMPONENT_DEFINE ("EpcFirstExampleForIpv6");

int
main (int argc, char *argv[])
{
CommandLine cmd;
cmd.Parse (argc, argv);

Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
Ptr<PointToPointEpcHelper> 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 (Seconds (0.010)));
NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost);

NodeContainer ueNodes;
NodeContainer enbNodes;
enbNodes.Create (2);
ueNodes.Create (2);

// Install Mobility Model
Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
for (uint16_t i = 0; i < 2; i++)
{
positionAlloc->Add (Vector (60.0 * i, 0, 0));
}
MobilityHelper mobility;
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
mobility.SetPositionAllocator (positionAlloc);
mobility.Install (enbNodes);
mobility.Install (ueNodes);

// Install the IP stack on the UEs
internet.Install (ueNodes);

// Install LTE Devices to the nodes
NetDeviceContainer enbLteDevs = lteHelper->InstallEnbDevice (enbNodes);
NetDeviceContainer ueLteDevs = lteHelper->InstallUeDevice (ueNodes);

Ipv6InterfaceContainer ueIpIface;

for (NetDeviceContainer::Iterator it = ueLteDevs.Begin (); it != ueLteDevs.End (); ++it)
(*it)->SetAddress (Mac48Address::Allocate ());

// Assign IP address to UEs
ueIpIface = epcHelper->AssignUeIpv6Address (NetDeviceContainer (ueLteDevs));


Ipv6StaticRoutingHelper ipv6RoutingHelper;

for (uint32_t u = 0; u < ueNodes.GetN (); ++u)
{
Ptr<Node> ueNode = ueNodes.Get (u);
// Set the default gateway for the UEs
Ptr<Ipv6StaticRouting> ueStaticRouting = ipv6RoutingHelper.GetStaticRouting (ueNode->GetObject<Ipv6> ());
ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress6 (), 1);
}


// Attach one UE per eNodeB
for (uint16_t i = 0; i < 2; i++)
{
lteHelper->Attach (ueLteDevs.Get (i), enbLteDevs.Get (i));
// side effect: the default EPS bearer will be activated
}

Ipv6AddressHelper ipv6h;
ipv6h.SetBase (Ipv6Address ("6001:db80::"), Ipv6Prefix (64));
Ipv6InterfaceContainer internetIpIfaces = ipv6h.Assign (internetDevices);

internetIpIfaces.SetForwarding (0, true);
internetIpIfaces.SetDefaultRouteInAllNodes (0);

Ptr<Ipv6StaticRouting> remoteHostStaticRouting = ipv6RoutingHelper.GetStaticRouting (remoteHost->GetObject<Ipv6> ());
remoteHostStaticRouting->AddNetworkRouteTo (epcHelper->GetEpcIpv6NetworkAddress (), Ipv6Prefix (48), internetIpIfaces.GetAddress (0, 1), 1, 0);


// interface 0 is localhost, 1 is the p2p device
Ipv6Address remoteHostAddr = internetIpIfaces.GetAddress (1, 1);


// Start applications on UEs and remote host

UdpEchoServerHelper echoServer (9);

ApplicationContainer serverApps = echoServer.Install (remoteHost);


serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (50.0));


UdpEchoClientHelper echoClient1 (remoteHostAddr, 9);
UdpEchoClientHelper echoClient2 (remoteHostAddr, 9);

echoClient1.SetAttribute ("MaxPackets", UintegerValue (1000));
echoClient1.SetAttribute ("Interval", TimeValue (Seconds (1.0)));
echoClient1.SetAttribute ("PacketSize", UintegerValue (1024));

echoClient2.SetAttribute ("MaxPackets", UintegerValue (1000));
echoClient2.SetAttribute ("Interval", TimeValue (Seconds (1.0)));
echoClient2.SetAttribute ("PacketSize", UintegerValue (1024));

ApplicationContainer clientApps1 = echoClient1.Install (ueNodes.Get(0));
ApplicationContainer clientApps2 = echoClient2.Install (ueNodes.Get(1));


clientApps1.Start (Seconds (1.0));
clientApps1.Stop (Seconds (50.0));

clientApps2.Start (Seconds (1.5));
clientApps2.Stop (Seconds (50.0));

LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_ALL);
LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_ALL);

internet.EnablePcapIpv6 ("lena1", ueNodes.Get (0));
internet.EnablePcapIpv6 ("lena2", ueNodes.Get (1));
internet.EnablePcapIpv6 ("lena3", remoteHostContainer.Get (0));
internet.EnablePcapIpv6 ("lena4", pgw);

Simulator::Stop (Seconds (50));
Simulator::Run ();

Simulator::Destroy ();
return 0;

}

178 changes: 178 additions & 0 deletions src/lte/examples/lena-ipv6-ue-ue.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2017 Jadavpur University, India
*
* 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: Manoj Kumar Rana <manoj24.rana@gmail.com>
*/

#include "ns3/lte-helper.h"
#include "ns3/epc-helper.h"
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/ipv4-global-routing-helper.h"
#include "ns3/ipv6-static-routing.h"
#include "ns3/internet-module.h"
#include "ns3/mobility-module.h"
#include "ns3/lte-module.h"
#include "ns3/applications-module.h"
#include "ns3/point-to-point-helper.h"
#include "ns3/config-store.h"

using namespace ns3;

/**
* Sample simulation script for LTE+EPC. It instantiates several eNodeB,
* attaches one UE per eNodeB starts a flow for remote host to and from the first UE.
* It also starts yet another flow between other UE pair.
*/

NS_LOG_COMPONENT_DEFINE ("EpcSecondExampleForIpv6");

int
main (int argc, char *argv[])
{
CommandLine cmd;
cmd.Parse(argc, argv);

Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
Ptr<PointToPointEpcHelper> 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 (Seconds (0.010)));
NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost);

NodeContainer ueNodes;
NodeContainer enbNodes;
enbNodes.Create (2);
ueNodes.Create (2);

// Install Mobility Model
Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
for (uint16_t i = 0; i < 2; i++)
{
positionAlloc->Add (Vector(60.0 * i, 0, 0));
}
MobilityHelper mobility;
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
mobility.SetPositionAllocator (positionAlloc);
mobility.Install (enbNodes);
mobility.Install (ueNodes);

// Install the IP stack on the UEs
internet.Install (ueNodes);

// Install LTE Devices to the nodes
NetDeviceContainer enbLteDevs = lteHelper->InstallEnbDevice (enbNodes);
NetDeviceContainer ueLteDevs = lteHelper->InstallUeDevice (ueNodes);

Ipv6InterfaceContainer ueIpIface;

for (NetDeviceContainer::Iterator it = ueLteDevs.Begin (); it != ueLteDevs.End (); ++it)
(*it)->SetAddress (Mac48Address::Allocate ());

// Assign IP address to UEs
ueIpIface = epcHelper->AssignUeIpv6Address (NetDeviceContainer (ueLteDevs));


Ipv6StaticRoutingHelper ipv6RoutingHelper;

for (uint32_t u = 0; u < ueNodes.GetN (); ++u)
{
Ptr<Node> ueNode = ueNodes.Get (u);
// Set the default gateway for the UE
Ptr<Ipv6StaticRouting> ueStaticRouting = ipv6RoutingHelper.GetStaticRouting (ueNode->GetObject<Ipv6> ());
ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress6 (), 1);
}

// Attach one UE per eNodeB
for (uint16_t i = 0; i < 2; i++)
{
lteHelper->Attach (ueLteDevs.Get (i), enbLteDevs.Get (i));
// side effect: the default EPS bearer will be activated
}

Ipv6AddressHelper ipv6h;
ipv6h.SetBase (Ipv6Address ("6001:db80::"), Ipv6Prefix (64));
Ipv6InterfaceContainer internetIpIfaces = ipv6h.Assign (internetDevices);

internetIpIfaces.SetForwarding (0, true);
internetIpIfaces.SetDefaultRouteInAllNodes (0);

Ptr<Ipv6StaticRouting> remoteHostStaticRouting = ipv6RoutingHelper.GetStaticRouting (remoteHost->GetObject<Ipv6> ());
remoteHostStaticRouting->AddNetworkRouteTo (epcHelper->GetEpcIpv6NetworkAddress (), Ipv6Prefix (48), internetIpIfaces.GetAddress (0, 1), 1, 0);


// Start applications on UEs and remote host

UdpEchoServerHelper echoServer (9);

ApplicationContainer serverApps = echoServer.Install (ueNodes.Get (0));


serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (50.0));


UdpEchoClientHelper echoClient1 (ueIpIface.GetAddress (0,1), 9);
UdpEchoClientHelper echoClient2 (ueIpIface.GetAddress (0,1), 9);

echoClient1.SetAttribute ("MaxPackets", UintegerValue (1000));
echoClient1.SetAttribute ("Interval", TimeValue (Seconds (1.0)));
echoClient1.SetAttribute ("PacketSize", UintegerValue (1024));

echoClient2.SetAttribute ("MaxPackets", UintegerValue (1000));
echoClient2.SetAttribute ("Interval", TimeValue (Seconds (1.0)));
echoClient2.SetAttribute ("PacketSize", UintegerValue (1024));

ApplicationContainer clientApps1 = echoClient1.Install (remoteHost);
ApplicationContainer clientApps2 = echoClient2.Install (ueNodes.Get (1));


clientApps1.Start (Seconds (1.0));
clientApps1.Stop (Seconds (50.0));

clientApps2.Start (Seconds (1.5));
clientApps2.Stop (Seconds (50.0));

LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_ALL);
LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_ALL);

internet.EnablePcapIpv6 ("lena5", ueNodes.Get (0));
internet.EnablePcapIpv6 ("lena6", ueNodes.Get (1));
internet.EnablePcapIpv6 ("lena7", remoteHostContainer.Get (0));
internet.EnablePcapIpv6 ("lena8", pgw);

Simulator::Stop (Seconds (50));
Simulator::Run ();

Simulator::Destroy ();
return 0;

}

9 changes: 9 additions & 0 deletions src/lte/examples/wscript
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ def build(bld):
obj = bld.create_ns3_program('lena-intercell-interference',
['lte'])
obj.source = 'lena-intercell-interference.cc'
obj = bld.create_ns3_program('lena-ipv6-addr-conf',
['lte'])
obj.source = 'lena-ipv6-addr-conf.cc'
obj = bld.create_ns3_program('lena-ipv6-ue-rh',
['lte'])
obj.source = 'lena-ipv6-ue-rh.cc'
obj = bld.create_ns3_program('lena-ipv6-ue-ue',
['lte'])
obj.source = 'lena-ipv6-ue-ue.cc'
obj = bld.create_ns3_program('lena-pathloss-traces',
['lte'])
obj.source = 'lena-pathloss-traces.cc'
Expand Down
157 changes: 137 additions & 20 deletions src/lte/helper/emu-epc-helper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@
#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>
Expand All @@ -41,6 +43,8 @@
#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 <iomanip>
#include <iostream>
Expand All @@ -56,7 +60,8 @@ EmuEpcHelper::EmuEpcHelper ()
: m_gtpuUdpPort (2152) // fixed by the standard
{
NS_LOG_FUNCTION (this);

// To access the attribute value within the constructor
ObjectBase::ConstructSelf (AttributeConstructionList ());
}

EmuEpcHelper::~EmuEpcHelper ()
Expand Down Expand Up @@ -91,34 +96,70 @@ EmuEpcHelper::GetTypeId (void)
StringValue ("00:00:00:eb:00"),
MakeStringAccessor (&EmuEpcHelper::m_enbMacAddressBase),
MakeStringChecker ())
.AddAttribute ("BaseIpv4Prefix",
"The 8 bit IPv4 prefix to be used for the assignment of IPv4 addresses to pgw and ue.",
Ipv4AddressValue (Ipv4Address ("7.0.0.0")),
MakeIpv4AddressAccessor (&EmuEpcHelper::m_uePgwbaseipv4prefix8),
MakeIpv4AddressChecker ())
.AddAttribute ("BaseIpv6Prefix",
"The 48 bit IPv6 prefix to be used for the assignment of IPv6 addresses to pgw and ue.",
Ipv6AddressValue (Ipv6Address ("7777:f00d:cafe::")),
MakeIpv6AddressAccessor (&EmuEpcHelper::m_uePgwbaseipv6prefix32),
MakeIpv6AddressChecker ())
;
return tid;
}

TypeId
EmuEpcHelper::GetInstanceTypeId () const
{
return GetTypeId ();
}

void
EmuEpcHelper::DoInitialize ()
{
NS_LOG_LOGIC (this);

// we use a /16 bit IPv4 net for an EPC network
m_uePgwbaseipv4prefix16 = m_uePgwbaseipv4prefix8.CombineMask (Ipv4Mask ("255.0.0.0")); //Initialize
Ipv4AddressGenerator::Init (m_uePgwbaseipv4prefix16, Ipv4Mask ("255.255.0.0"));

Ipv4AddressGenerator::TestMode ();
while (!(Ipv4AddressGenerator::AddAllocated (Ipv4AddressGenerator::GetNetwork (Ipv4Mask ("255.255.0.0")))))
m_uePgwbaseipv4prefix16 = Ipv4AddressGenerator::NextNetwork (Ipv4Mask ("255.255.0.0"));
m_uePgwAddressHelper.SetBase (m_uePgwbaseipv4prefix16, "255.255.0.0"); //The helper will assign IPv4 addresses using this 16 bit prefix
//Now we get an unique 16 bit IPv4 prefix for this EPC, which not used by any other EPC


// we use a /48 IPv6 net for an EPC network
m_uePgwbaseipv6prefix48 = m_uePgwbaseipv6prefix32.CombinePrefix (Ipv6Prefix (32)); //Initialize
Ipv6AddressGenerator::Init (m_uePgwbaseipv6prefix48, Ipv6Prefix (48));
Ipv6AddressGenerator::TestMode ();

while (!(Ipv6AddressGenerator::AddAllocated (Ipv6AddressGenerator::GetNetwork (Ipv6Prefix (48)))))
m_uePgwbaseipv6prefix48 = Ipv6AddressGenerator::NextNetwork (Ipv6Prefix (48));
//Now we get an unique 48 bit IPv6 prefix for this EPC, which not used by any other EPC

// we use a /8 net for all UEs
m_ueAddressHelper.SetBase ("7.0.0.0", "255.0.0.0");



// create SgwPgwNode
m_sgwPgw = CreateObject<Node> ();
InternetStackHelper internet;
internet.SetIpv4StackInstall (true);
internet.Install (m_sgwPgw);

//The Tun device resides in different 64 bit subnet and so, 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 (m_uePgwbaseipv6prefix48, Ipv6Prefix (48), 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 implementing tunneling of user data over GTP-U/UDP/IP
// create TUN device containg 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));

Expand All @@ -130,9 +171,19 @@ EmuEpcHelper::DoInitialize ()
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
// 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 = m_ueAddressHelper.Assign (tunDeviceContainer);
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);
Expand All @@ -141,6 +192,7 @@ EmuEpcHelper::DoInitialize ()
// 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 ());
Expand Down Expand Up @@ -184,7 +236,7 @@ EmuEpcHelper::AddEnb (Ptr<Node> enb, Ptr<NetDevice> lteEnbNetDevice, uint16_t ce

NS_ASSERT (enb == lteEnbNetDevice->GetNode ());

// add an IPv4 stack to the previously created eNB
// 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 ());
Expand Down Expand Up @@ -231,10 +283,24 @@ EmuEpcHelper::AddEnb (Ptr<Node> enb, Ptr<NetDevice> lteEnbNetDevice, uint16_t ce
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, enbS1uSocket, enbAddress, sgwAddress, cellId);
enbApp->SetLTESocket6(enbLteSocket6);
enb->AddApplication (enbApp);
NS_ASSERT (enb->GetNApplications () == 1);
NS_ASSERT_MSG (enb->GetApplication (0)->GetObject<EpcEnbApplication> () != 0, "cannot retrieve EpcEnbApplication");
Expand Down Expand Up @@ -312,23 +378,35 @@ EmuEpcHelper::AddUe (Ptr<NetDevice> ueDevice, uint64_t 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 address of the UE and notify it to the SGW;
// 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> ();
NS_ASSERT_MSG (ueIpv4 != 0, "UEs need to have IPv4 installed before EPS bearers can be activated");
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");
int32_t interface = ueIpv4->GetInterfaceForDevice (ueDevice);
NS_ASSERT (interface >= 0);
NS_ASSERT (ueIpv4->GetNAddresses (interface) == 1);
Ipv4Address ueAddr = ueIpv4->GetAddress (interface, 0).GetLocal ();
NS_LOG_LOGIC (" UE IP address: " << ueAddr); m_sgwPgwApp->SetUeAddress (imsi, ueAddr);

int32_t interface6 = ueIpv6->GetInterfaceForDevice (ueDevice);
//NS_ASSERT (interface >= 0 || interface6 >= 0);
//NS_ASSERT (ueIpv4->GetNAddresses (interface) == 1 || ueIpv6->GetNAddresses (interface6) == 1);

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);
}
else
{
Ipv6Address ueAddr6 = ueIpv6->GetAddress (interface6, 0).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)
Expand All @@ -349,10 +427,31 @@ EmuEpcHelper::GetPgwNode ()
Ipv4InterfaceContainer
EmuEpcHelper::AssignUeIpv4Address (NetDeviceContainer ueDevices)
{
return m_ueAddressHelper.Assign (ueDevices);
return m_uePgwAddressHelper.Assign (ueDevices);
}

Ipv6InterfaceContainer
EmuEpcHelper::AssignUeIpv6Address (NetDeviceContainer ueDevices)
{
Ipv6InterfaceContainer iifc;
Ptr<NetDevice> device;

// Assign unique 64 bit prefixes to each UE

Ipv6AddressGenerator::Init (m_uePgwbaseipv6prefix48, Ipv6Prefix (64));

for (uint32_t i = 0; i < ueDevices.GetN (); ++i)
{
NetDeviceContainer dc;
device = ueDevices.Get (i);
dc.Add (device);
while (!(Ipv6AddressGenerator::AddAllocated (Ipv6AddressGenerator::GetNetwork (Ipv6Prefix (64)))))
Ipv6AddressGenerator::NextNetwork (Ipv6Prefix (64));
iifc.Add (m_uePgwAddressHelper6.Assign (dc));
}

return iifc;
}

Ipv4Address
EmuEpcHelper::GetUeDefaultGatewayAddress ()
Expand All @@ -361,5 +460,23 @@ EmuEpcHelper::GetUeDefaultGatewayAddress ()
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 ();
}

Ipv4Address EmuEpcHelper::GetEpcIpv4NetworkAddress ()
{
// return the network address of this EPC
return m_uePgwbaseipv4prefix16;
}

Ipv6Address EmuEpcHelper::GetEpcIpv6NetworkAddress ()
{
// return the network address of this EPC
return m_uePgwbaseipv6prefix48;
}

} // namespace ns3
43 changes: 39 additions & 4 deletions src/lte/helper/emu-epc-helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#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>
Expand Down Expand Up @@ -70,26 +71,36 @@ class EmuEpcHelper : public EpcHelper
* \return The object TypeId.
*/
static TypeId GetTypeId (void);
TypeId GetInstanceTypeId () const;
virtual void DoInitialize ();
virtual void DoDispose ();

Ipv4Address GetEpcIpv4NetworkAddress ();
Ipv6Address GetEpcIpv6NetworkAddress ();

// 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 ();
virtual Ipv4InterfaceContainer AssignUeIpv4Address (NetDeviceContainer ueDevices);
Ipv6InterfaceContainer AssignUeIpv6Address (NetDeviceContainer ueDevices);
virtual Ipv4Address GetUeDefaultGatewayAddress ();

Ipv6Address GetUeDefaultGatewayAddress6 ();


private:

/**
* helper to assign addresses to UE devices as well as to the TUN device of the SGW/PGW
* 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
*/
Ipv4AddressHelper m_ueAddressHelper;
Ipv6AddressHelper m_uePgwAddressHelper6;

/**
* SGW-PGW network element
Expand All @@ -102,7 +113,7 @@ class EmuEpcHelper : public EpcHelper
Ptr<EpcSgwPgwApplication> m_sgwPgwApp;

/**
* TUN device implementing tunneling of user data over GTP-U/UDP/IP
* TUN device containg IPv4 address and implementing tunneling of user data over GTP-U/UDP/IP
*/
Ptr<VirtualNetDevice> m_tunDevice;

Expand Down Expand Up @@ -151,6 +162,30 @@ class EmuEpcHelper : public EpcHelper
* First 5 bytes of the Enb MAC address base
*/
std::string m_enbMacAddressBase;

/**
* The common 8 bit prefix used for the IPv4 address assignment of
* the EPC network
*/
Ipv4Address m_uePgwbaseipv4prefix8;

/**
* The 16 bit prefix used for the IPv4 address assignment of
* the UE and PGW
*/
Ipv4Address m_uePgwbaseipv4prefix16;

/**
* The common 32 bit prefix used for the IPv6 address assignment of
* this EPC network
*/
Ipv6Address m_uePgwbaseipv6prefix32;

/**
* The common 48 bit prefix used for the IPv6 address assignment of
* the UE and PGW
*/
Ipv6Address m_uePgwbaseipv6prefix48;
};


Expand Down
1 change: 1 addition & 0 deletions src/lte/helper/epc-helper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <ns3/log.h>
#include <ns3/node.h>
#include <ns3/ipv4-address.h>
#include <ns3/ipv6-address.h>

namespace ns3 {

Expand Down
3 changes: 2 additions & 1 deletion src/lte/helper/epc-helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#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>
Expand Down Expand Up @@ -132,7 +133,7 @@ class EpcHelper : public Object

/**
*
* \return the address of the Default Gateway to be used by UEs to reach the internet
* \return the IPv4 address of the Default Gateway to be used by UEs to reach the internet
*/
virtual Ipv4Address GetUeDefaultGatewayAddress () = 0;

Expand Down
154 changes: 136 additions & 18 deletions src/lte/helper/point-to-point-epc-helper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,23 @@
#include <ns3/mac48-address.h>
#include <ns3/eps-bearer.h>
#include <ns3/ipv4-address.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/epc-sgw-pgw-application.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/ipv4-address-generator.h>
#include <ns3/ipv6-address-generator.h>

namespace ns3 {

Expand All @@ -51,6 +55,8 @@ PointToPointEpcHelper::PointToPointEpcHelper ()
: m_gtpuUdpPort (2152) // fixed by the standard
{
NS_LOG_FUNCTION (this);
// To access the attribute value within the constructor
ObjectBase::ConstructSelf (AttributeConstructionList ());

// since we use point-to-point links for all S1-U links,
// we use a /30 subnet which can hold exactly two addresses
Expand All @@ -59,13 +65,35 @@ PointToPointEpcHelper::PointToPointEpcHelper ()

m_x2Ipv4AddressHelper.SetBase ("12.0.0.0", "255.255.255.252");

// we use a /8 net for all UEs
m_ueAddressHelper.SetBase ("7.0.0.0", "255.0.0.0");

// we use a /16 bit IPv4 net for an EPC network
m_uePgwbaseipv4prefix16 = m_uePgwbaseipv4prefix8.CombineMask (Ipv4Mask ("255.0.0.0")); //Initialize
Ipv4AddressGenerator::Init (m_uePgwbaseipv4prefix16, Ipv4Mask ("255.255.0.0"));

Ipv4AddressGenerator::TestMode ();
while (!(Ipv4AddressGenerator::AddAllocated (Ipv4AddressGenerator::GetNetwork (Ipv4Mask ("255.255.0.0")))))
m_uePgwbaseipv4prefix16 = Ipv4AddressGenerator::NextNetwork (Ipv4Mask ("255.255.0.0"));
m_uePgwAddressHelper.SetBase (m_uePgwbaseipv4prefix16, "255.255.0.0"); //The helper will assign IPv4 addresses using this 16 bit prefix
//Now we get an unique 16 bit IPv4 prefix for this EPC, which not used by any other EPC


// we use a /48 IPv6 net for an EPC network
m_uePgwbaseipv6prefix48 = m_uePgwbaseipv6prefix32.CombinePrefix (Ipv6Prefix (32));//Initialize
Ipv6AddressGenerator::Init (m_uePgwbaseipv6prefix48, Ipv6Prefix (48));

Ipv6AddressGenerator::TestMode ();
while (!(Ipv6AddressGenerator::AddAllocated (Ipv6AddressGenerator::GetNetwork (Ipv6Prefix (48)))))
m_uePgwbaseipv6prefix48 = Ipv6AddressGenerator::NextNetwork (Ipv6Prefix (48));
//Now we get an unique 48 bit IPv6 prefix for this EPC, which not used by any other EPC

// create SgwPgwNode
m_sgwPgw = CreateObject<Node> ();
InternetStackHelper internet;
internet.Install (m_sgwPgw);

//The Tun device resides in different 64 bit subnet and so, 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 (m_uePgwbaseipv6prefix48, Ipv6Prefix (48), Ipv6Address ("::"), 1, 0);

// create S1-U socket
Ptr<Socket> sgwPgwS1uSocket = Socket::CreateSocket (m_sgwPgw, TypeId::LookupByName ("ns3::UdpSocketFactory"));
Expand All @@ -74,11 +102,14 @@ PointToPointEpcHelper::PointToPointEpcHelper ()

// create TUN device 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_tunDevice->SetAddress (Mac48Address::Allocate ());



m_sgwPgw->AddDevice (m_tunDevice);
NetDeviceContainer tunDeviceContainer;
Expand All @@ -87,7 +118,18 @@ PointToPointEpcHelper::PointToPointEpcHelper ()
// 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 = m_ueAddressHelper.Assign (tunDeviceContainer);
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 EpcSgwPgwApplication
m_sgwPgwApp = CreateObject<EpcSgwPgwApplication> (m_tunDevice, sgwPgwS1uSocket);
Expand All @@ -96,6 +138,7 @@ PointToPointEpcHelper::PointToPointEpcHelper ()
// 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 ());
Expand Down Expand Up @@ -144,10 +187,26 @@ PointToPointEpcHelper::GetTypeId (void)
UintegerValue (3000),
MakeUintegerAccessor (&PointToPointEpcHelper::m_x2LinkMtu),
MakeUintegerChecker<uint16_t> ())
.AddAttribute ("BaseIpv4Prefix",
"The 8 bit IPv4 prefix to be used for the assignment of IPv4 addresses to pgw and ue.",
Ipv4AddressValue (Ipv4Address ("7.0.0.0")),
MakeIpv4AddressAccessor (&PointToPointEpcHelper::m_uePgwbaseipv4prefix8),
MakeIpv4AddressChecker ())
.AddAttribute ("BaseIpv6Prefix",
"The 32 bit IPv6 prefix to be used for the assignment of IPv6 addresses to pgw and ue.",
Ipv6AddressValue (Ipv6Address ("7777:f00d::")),
MakeIpv6AddressAccessor (&PointToPointEpcHelper::m_uePgwbaseipv6prefix32),
MakeIpv6AddressChecker ())
;
return tid;
}

TypeId
PointToPointEpcHelper::GetInstanceTypeId () const
{
return GetTypeId ();
}

void
PointToPointEpcHelper::DoDispose ()
{
Expand Down Expand Up @@ -214,10 +273,24 @@ PointToPointEpcHelper::AddEnb (Ptr<Node> enb, Ptr<NetDevice> lteEnbNetDevice, ui
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, enbS1uSocket, enbAddress, sgwAddress, cellId);
enbApp->SetLTESocket6(enbLteSocket6);
enb->AddApplication (enbApp);
NS_ASSERT (enb->GetNApplications () == 1);
NS_ASSERT_MSG (enb->GetApplication (0)->GetObject<EpcEnbApplication> () != 0, "cannot retrieve EpcEnbApplication");
Expand Down Expand Up @@ -298,42 +371,70 @@ PointToPointEpcHelper::ActivateEpsBearer (Ptr<NetDevice> ueDevice, uint64_t imsi
{
NS_LOG_FUNCTION (this << ueDevice << imsi);

// we now retrieve the IPv4 address of the UE and notify it to the SGW;
// 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> ();
NS_ASSERT_MSG (ueIpv4 != 0, "UEs need to have IPv4 installed before EPS bearers can be activated");
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");
int32_t interface = ueIpv4->GetInterfaceForDevice (ueDevice);
NS_ASSERT (interface >= 0);
NS_ASSERT (ueIpv4->GetNAddresses (interface) == 1);
Ipv4Address ueAddr = ueIpv4->GetAddress (interface, 0).GetLocal ();
NS_LOG_LOGIC (" UE IP address: " << ueAddr); m_sgwPgwApp->SetUeAddress (imsi, ueAddr);

int32_t interface6 = ueIpv6->GetInterfaceForDevice (ueDevice);
//NS_ASSERT (interface >= 0 || interface6 >= 0);
//NS_ASSERT (ueIpv4->GetNAddresses (interface) == 1 || ueIpv6->GetNAddresses (interface6) == 1);
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);
}
else
{
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)
{
ueLteDevice->GetNas ()->ActivateEpsBearer (bearer, tft);
Simulator::ScheduleNow (&EpcUeNas::ActivateEpsBearer, ueLteDevice->GetNas (), bearer, tft);
}
return bearerId;
}


Ptr<Node>
PointToPointEpcHelper::GetPgwNode ()
{
return m_sgwPgw;
}


Ipv4InterfaceContainer
PointToPointEpcHelper::AssignUeIpv4Address (NetDeviceContainer ueDevices)
{
return m_ueAddressHelper.Assign (ueDevices);
return m_uePgwAddressHelper.Assign (ueDevices);
}

Ipv6InterfaceContainer
PointToPointEpcHelper::AssignUeIpv6Address (NetDeviceContainer ueDevices)
{
Ipv6InterfaceContainer iifc;
Ptr<NetDevice> device;

// Assign unique 64 bit prefixes to each UE

Ipv6AddressGenerator::Init (m_uePgwbaseipv6prefix48, Ipv6Prefix (64));

for (uint32_t i = 0; i < ueDevices.GetN (); ++i)
{
NetDeviceContainer dc;
device = ueDevices.Get (i);
dc.Add (device);
while (!(Ipv6AddressGenerator::AddAllocated (Ipv6AddressGenerator::GetNetwork (Ipv6Prefix (64)))))
Ipv6AddressGenerator::NextNetwork (Ipv6Prefix (64));
iifc.Add (m_uePgwAddressHelper6.Assign (dc));
}

return iifc;
}

Ipv4Address
PointToPointEpcHelper::GetUeDefaultGatewayAddress ()
Expand All @@ -342,5 +443,22 @@ PointToPointEpcHelper::GetUeDefaultGatewayAddress ()
return m_sgwPgw->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal ();
}

Ipv6Address
PointToPointEpcHelper::GetUeDefaultGatewayAddress6 ()
{
// return the address of the tun device
return m_sgwPgw->GetObject<Ipv6> ()->GetAddress (1, 1).GetAddress ();
}

Ipv4Address PointToPointEpcHelper::GetEpcIpv4NetworkAddress ()
{
// return thr network address of this epc
return m_uePgwbaseipv4prefix16;
}

Ipv6Address PointToPointEpcHelper::GetEpcIpv6NetworkAddress ()
{
//return the network address of this epc
return m_uePgwbaseipv6prefix48;
}
} // namespace ns3
39 changes: 36 additions & 3 deletions src/lte/helper/point-to-point-epc-helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#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>
Expand Down Expand Up @@ -68,25 +69,34 @@ class PointToPointEpcHelper : public EpcHelper
* \return The object TypeId.
*/
static TypeId GetTypeId (void);
TypeId GetInstanceTypeId () const;
virtual void DoDispose ();

Ipv4Address GetEpcIpv4NetworkAddress ();
Ipv6Address GetEpcIpv6NetworkAddress ();

// 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 ();
virtual Ipv4InterfaceContainer AssignUeIpv4Address (NetDeviceContainer ueDevices);
Ipv6InterfaceContainer AssignUeIpv6Address (NetDeviceContainer ueDevices);
virtual Ipv4Address GetUeDefaultGatewayAddress ();

Ipv6Address GetUeDefaultGatewayAddress6 ();


private:

/**
* helper to assign addresses to UE devices as well as to the TUN device of the SGW/PGW
* 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
*/
Ipv4AddressHelper m_ueAddressHelper;
Ipv6AddressHelper m_uePgwAddressHelper6;

/**
* SGW-PGW network element
Expand Down Expand Up @@ -166,6 +176,29 @@ class PointToPointEpcHelper : public EpcHelper
*/
uint16_t m_x2LinkMtu;

/**
* The common 8 bit prefix used for the IPv4 address assignment of
* the EPC network
*/
Ipv4Address m_uePgwbaseipv4prefix8;

/**
* The 16 bit prefix used for the IPv4 address assignment of
* the UE and PGW
*/
Ipv4Address m_uePgwbaseipv4prefix16;

/**
* The common 32 bit prefix used for the IPv6 address assignment of
* this EPC network
*/
Ipv6Address m_uePgwbaseipv6prefix32;

/**
* The common 48 bit prefix used for the IPv6 address assignment of
* the UE and PGW
*/
Ipv6Address m_uePgwbaseipv6prefix48;
};


Expand Down
53 changes: 48 additions & 5 deletions src/lte/model/epc-enb-application.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,16 @@ EpcEnbApplication::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::EpcEnbApplication")
.SetParent<Object> ()
.SetGroupName("Lte");
.SetGroupName("Lte")
.AddTraceSource ("RxfromEnb",
"Receive data packets from LTE Enb Net Device",
MakeTraceSourceAccessor (&EpcEnbApplication::m_rxLteenbPktTrace),
"ns3::EpcEnbApplication::RxTracedCallback")
.AddTraceSource ("RxfromS1u",
"Receive data packets from S1-U Net Device",
MakeTraceSourceAccessor (&EpcEnbApplication::m_rxS1uPktTrace),
"ns3::EpcEnbApplication::RxTracedCallback")
;
return tid;
}

Expand All @@ -72,14 +81,15 @@ EpcEnbApplication::DoDispose (void)
{
NS_LOG_FUNCTION (this);
m_lteSocket = 0;
m_lteSocket6 = 0;
m_s1uSocket = 0;
delete m_s1SapProvider;
delete m_s1apSapEnb;
}


EpcEnbApplication::EpcEnbApplication (Ptr<Socket> lteSocket, Ptr<Socket> s1uSocket, Ipv4Address enbS1uAddress, Ipv4Address sgwS1uAddress, uint16_t cellId)
: m_lteSocket (lteSocket),
m_lteSocket6 (0),
m_s1uSocket (s1uSocket),
m_enbS1uAddress (enbS1uAddress),
m_sgwS1uAddress (sgwS1uAddress),
Expand Down Expand Up @@ -240,7 +250,14 @@ void
EpcEnbApplication::RecvFromLteSocket (Ptr<Socket> socket)
{
NS_LOG_FUNCTION (this);
NS_ASSERT (socket == m_lteSocket);
if(m_lteSocket6)
{
NS_ASSERT (socket == m_lteSocket || socket == m_lteSocket6);
}
else
{
NS_ASSERT (socket == m_lteSocket);
}
Ptr<Packet> packet = socket->Recv ();

/// \internal
Expand All @@ -264,6 +281,7 @@ EpcEnbApplication::RecvFromLteSocket (Ptr<Socket> socket)
std::map<uint8_t, uint32_t>::iterator bidIt = rntiIt->second.find (bid);
NS_ASSERT (bidIt != rntiIt->second.end ());
uint32_t teid = bidIt->second;
m_rxLteenbPktTrace (packet->Copy ());
SendToS1uSocket (packet, teid);
}
}
Expand All @@ -284,7 +302,7 @@ EpcEnbApplication::RecvFromS1uSocket (Ptr<Socket> socket)
/// Workaround for \bugid{231}
SocketAddressTag tag;
packet->RemovePacketTag (tag);

m_rxS1uPktTrace (packet->Copy ());
SendToLteSocket (packet, it->second.m_rnti, it->second.m_bid);
}

Expand All @@ -294,7 +312,20 @@ EpcEnbApplication::SendToLteSocket (Ptr<Packet> packet, uint16_t rnti, uint8_t b
NS_LOG_FUNCTION (this << packet << rnti << (uint16_t) bid << packet->GetSize ());
EpsBearerTag tag (rnti, bid);
packet->AddPacketTag (tag);
int sentBytes = m_lteSocket->Send (packet);
uint8_t ipType;
Ptr<Packet> pCopy = packet->Copy ();
pCopy->CopyData (&ipType, 1);
ipType=(ipType>>4) & 0x0f;
int sentBytes;
if (ipType == 0x04)
{
sentBytes = m_lteSocket->Send (packet);
}
else
{
sentBytes = m_lteSocket6->Send (packet);
}

NS_ASSERT (sentBytes > 0);
}

Expand Down Expand Up @@ -324,4 +355,16 @@ EpcEnbApplication::DoReleaseIndication (uint64_t imsi, uint16_t rnti, uint8_t be
//From 3GPP TS 23401-950 Section 5.4.4.2, enB sends EPS bearer Identity in Bearer Release Indication message to MME
m_s1apSapMme->ErabReleaseIndication (imsi, rnti, erabToBeReleaseIndication);
}

void EpcEnbApplication::SetLTESocket6(Ptr<Socket> lteSocket6)
{
m_lteSocket6 = lteSocket6;
m_lteSocket6->SetRecvCallback (MakeCallback (&EpcEnbApplication::RecvFromLteSocket, this));
}

Ptr<Socket> EpcEnbApplication::GetLTESocket6()
{
return m_lteSocket6;
}

} // namespace ns3
24 changes: 24 additions & 0 deletions src/lte/model/epc-enb-application.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ class EpcEnbApplication : public Application
*/
EpcEnbApplication (Ptr<Socket> lteSocket, Ptr<Socket> s1uSocket, Ipv4Address enbS1uAddress, Ipv4Address sgwS1uAddress, uint16_t cellId);

void SetLTESocket6(Ptr<Socket> lteSocket6);
Ptr<Socket> GetLTESocket6();
/**
* Destructor
*
Expand Down Expand Up @@ -123,6 +125,14 @@ class EpcEnbApplication : public Application
*/
void RecvFromS1uSocket (Ptr<Socket> socket);

/**
* TracedCallback signature for data Packet reception event.
*
* \param [in] packet The data packet sent from the internet.
*/
typedef void (* RxTracedCallback)
(Ptr<Packet> packet);


struct EpsFlowId_t
{
Expand Down Expand Up @@ -191,6 +201,11 @@ class EpcEnbApplication : public Application
*/
Ptr<Socket> m_lteSocket;

/**
* raw packet socket to send and receive the packets to and from the LTE radio interface
*/
Ptr<Socket> m_lteSocket6;

/**
* UDP socket to send and receive GTP-U the packets to and from the S1-U interface
*/
Expand Down Expand Up @@ -253,6 +268,15 @@ class EpcEnbApplication : public Application

uint16_t m_cellId;

/**
* \brief Callback to trace RX (reception) data packets from LTE Enb Net Device.
*/
TracedCallback<Ptr<Packet> > m_rxLteenbPktTrace;

/**
* \brief Callback to trace RX (reception) data packets from S1-U Net Device.
*/
TracedCallback<Ptr<Packet> > m_rxS1uPktTrace;
};

} //namespace ns3
Expand Down
118 changes: 98 additions & 20 deletions src/lte/model/epc-sgw-pgw-application.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#include "ns3/log.h"
#include "ns3/mac48-address.h"
#include "ns3/ipv4.h"
#include "ns3/ipv6.h"
#include "ns3/ipv6-header.h"
#include "ns3/inet-socket-address.h"
#include "ns3/epc-gtpu-header.h"
#include "ns3/abort.h"
Expand Down Expand Up @@ -91,6 +93,18 @@ 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
/////////////////////////
Expand All @@ -101,7 +115,16 @@ EpcSgwPgwApplication::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::EpcSgwPgwApplication")
.SetParent<Object> ()
.SetGroupName("Lte");
.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;
}

Expand All @@ -115,7 +138,6 @@ EpcSgwPgwApplication::DoDispose ()
}



EpcSgwPgwApplication::EpcSgwPgwApplication (const Ptr<VirtualNetDevice> tunDevice, const Ptr<Socket> s1uSocket)
: m_s1uSocket (s1uSocket),
m_tunDevice (tunDevice),
Expand All @@ -139,33 +161,65 @@ bool
EpcSgwPgwApplication::RecvFromTunDevice (Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber)
{
NS_LOG_FUNCTION (this << source << dest << packet << packet->GetSize ());

m_rxTunPktTrace (packet->Copy ());
uint8_t ipType;
// get IP address of UE
Ptr<Packet> pCopy = packet->Copy ();
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);
pCopy->CopyData (&ipType, 1);
ipType=(ipType>>4) & 0x0f;
if (ipType == 0x04)
{
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);
if (teid == 0)
{
NS_LOG_WARN ("no matching bearer for this packet");
}
else
{
SendToS1uSocket (packet, enbAddr, teid);
}
}
}
else
{
Ipv4Address enbAddr = it->second->GetEnbAddr ();
uint32_t teid = it->second->Classify (packet);
if (teid == 0)
{
NS_LOG_WARN ("no matching bearer for this packet");
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
{
SendToS1uSocket (packet, enbAddr, teid);
Ipv4Address enbAddr = it->second->GetEnbAddr ();
uint32_t teid = it->second->Classify (packet);
if (teid == 0)
{
NS_LOG_WARN ("no matching bearer for this packet");
}
else
{
SendToS1uSocket (packet, enbAddr, teid);
}
}
}

// 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.
Expand All @@ -189,14 +243,28 @@ EpcSgwPgwApplication::RecvFromS1uSocket (Ptr<Socket> socket)
packet->RemovePacketTag (tag);

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");
m_tunDevice->Receive (packet, 0x0800, m_tunDevice->GetAddress (), m_tunDevice->GetAddress (), NetDevice::PACKET_HOST);
uint8_t ipType;
// get IP address of UE
Ptr<Packet> pCopy = packet->Copy ();
pCopy->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
{
m_tunDevice->Receive (packet, 0x86DD, m_tunDevice->GetAddress (), m_tunDevice->GetAddress (), NetDevice::PACKET_HOST);
}
}

void
Expand Down Expand Up @@ -255,6 +323,16 @@ EpcSgwPgwApplication::SetUeAddress (uint64_t imsi, Ipv4Address ueAddr)
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)
{
Expand Down
46 changes: 45 additions & 1 deletion src/lte/model/epc-sgw-pgw-application.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class EpcSgwPgwApplication : public Application
* 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);

/**
Expand Down Expand Up @@ -150,6 +151,22 @@ class EpcSgwPgwApplication : public Application
*/
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
Expand Down Expand Up @@ -217,11 +234,23 @@ class EpcSgwPgwApplication : public Application
*/
void SetUeAddr (Ipv4Address addr);

/**
* \return the address of the UE
*/
Ipv6Address GetUeAddr6 ();

/**
* set the address of the UE
*
* \param addr the address of the UE
*/
void SetUeAddr6 (Ipv6Address addr);

private:
EpcTftClassifier m_tftClassifier;
Ipv4Address m_enbAddr;
Ipv4Address m_ueAddr;
Ipv6Address m_ueAddr6;
std::map<uint8_t, uint32_t> m_teidByBearerIdMap;
};

Expand All @@ -238,10 +267,15 @@ class EpcSgwPgwApplication : public Application
Ptr<VirtualNetDevice> m_tunDevice;

/**
* Map telling for each UE address the corresponding UE info
* 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
*/
Expand Down Expand Up @@ -273,6 +307,16 @@ class EpcSgwPgwApplication : public Application
};

std::map<uint16_t, EnbInfo> m_enbInfoByCellId;

/**
* \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
Expand Down
188 changes: 129 additions & 59 deletions src/lte/model/epc-tft-classifier.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,18 @@
*
*/




#include "epc-tft-classifier.h"
#include "epc-tft.h"
#include "ns3/log.h"
#include "ns3/packet.h"
#include "ns3/ipv4-header.h"
#include "ns3/ipv6-header.h"
#include "ns3/udp-header.h"
#include "ns3/tcp-header.h"
#include "ns3/udp-l4-protocol.h"
#include "ns3/tcp-l4-protocol.h"
#include "ns3/icmpv6-l4-protocol.h"
#include "ns3/icmpv4-l4-protocol.h"

namespace ns3 {

Expand Down Expand Up @@ -71,95 +71,165 @@ EpcTftClassifier::Classify (Ptr<Packet> p, EpcTft::Direction direction)

Ptr<Packet> pCopy = p->Copy ();

Ipv4Header ipv4Header;
pCopy->RemoveHeader (ipv4Header);
uint8_t ipType;
pCopy->CopyData (&ipType, 1);
ipType = (ipType>>4) & 0x0f;

Ipv4Address localAddress;
Ipv4Address remoteAddress;
Ipv4Address localAddressIpv4;
Ipv4Address remoteAddressIpv4;


if (direction == EpcTft::UPLINK)
Ipv6Address localAddressIpv6;
Ipv6Address remoteAddressIpv6;

uint8_t protocol;
uint8_t tos;

uint16_t localPort = 0;
uint16_t remotePort = 0;

if (ipType == 0x04)
{
localAddress = ipv4Header.GetSource ();
remoteAddress = ipv4Header.GetDestination ();
Ipv4Header ipv4Header;
pCopy->RemoveHeader (ipv4Header);

if (direction == EpcTft::UPLINK)
{
localAddressIpv4 = ipv4Header.GetSource ();
remoteAddressIpv4 = ipv4Header.GetDestination ();
}
else
{
NS_ASSERT (direction == EpcTft::DOWNLINK);
remoteAddressIpv4 = ipv4Header.GetSource ();
localAddressIpv4 = ipv4Header.GetDestination ();
}
NS_LOG_INFO ("local address: " << localAddressIpv4 << " remote address: " << remoteAddressIpv4);

protocol = ipv4Header.GetProtocol ();
tos = ipv4Header.GetTos ();
}
else
{
NS_ASSERT (direction == EpcTft::DOWNLINK);
remoteAddress = ipv4Header.GetSource ();
localAddress = ipv4Header.GetDestination ();
}

uint8_t protocol = ipv4Header.GetProtocol ();
{
Ipv6Header ipv6Header;
pCopy->RemoveHeader (ipv6Header);

uint8_t tos = ipv4Header.GetTos ();
if (direction == EpcTft::UPLINK)
{
localAddressIpv6 = ipv6Header.GetSourceAddress ();
remoteAddressIpv6 = ipv6Header.GetDestinationAddress ();
}
else
{
NS_ASSERT (direction == EpcTft::DOWNLINK);
remoteAddressIpv6 = ipv6Header.GetSourceAddress ();
localAddressIpv6 = ipv6Header.GetDestinationAddress ();
}
NS_LOG_INFO ("local address: " << localAddressIpv6 << " remote address: " << remoteAddressIpv6);

uint16_t localPort = 0;
uint16_t remotePort = 0;
protocol = ipv6Header.GetNextHeader ();
tos = ipv6Header.GetTrafficClass ();
}

if (protocol == UdpL4Protocol::PROT_NUMBER)
{
UdpHeader udpHeader;
pCopy->RemoveHeader (udpHeader);

if (direction == EpcTft::UPLINK)
{
localPort = udpHeader.GetSourcePort ();
remotePort = udpHeader.GetDestinationPort ();
}
{
localPort = udpHeader.GetSourcePort ();
remotePort = udpHeader.GetDestinationPort ();
}
else
{
remotePort = udpHeader.GetSourcePort ();
localPort = udpHeader.GetDestinationPort ();
}
{
remotePort = udpHeader.GetSourcePort ();
localPort = udpHeader.GetDestinationPort ();
}
}
else if (protocol == TcpL4Protocol::PROT_NUMBER)
{
TcpHeader tcpHeader;
pCopy->RemoveHeader (tcpHeader);
if (direction == EpcTft::UPLINK)
{
localPort = tcpHeader.GetSourcePort ();
remotePort = tcpHeader.GetDestinationPort ();
}
{
localPort = tcpHeader.GetSourcePort ();
remotePort = tcpHeader.GetDestinationPort ();
}
else
{
remotePort = tcpHeader.GetSourcePort ();
localPort = tcpHeader.GetDestinationPort ();
}
{
remotePort = tcpHeader.GetSourcePort ();
localPort = tcpHeader.GetDestinationPort ();
}
}
else if (protocol == Icmpv6L4Protocol::PROT_NUMBER || protocol == Icmpv4L4Protocol::PROT_NUMBER)
{
remotePort = 0;
localPort = 0;
}
else
{
NS_LOG_INFO ("Unknown protocol: " << protocol);
return 0; // no match
}

NS_LOG_INFO ("Classifing packet:"
<< " localAddr=" << localAddress
<< " remoteAddr=" << remoteAddress
<< " localPort=" << localPort
<< " remotePort=" << remotePort
<< " tos=0x" << (uint16_t) tos );

// now it is possible to classify the packet!
// we use a reverse iterator since filter priority is not implemented properly.
// This way, since the default bearer is expected to be added first, it will be evaluated last.
std::map <uint32_t, Ptr<EpcTft> >::const_reverse_iterator it;
NS_LOG_LOGIC ("TFT MAP size: " << m_tftMap.size ());

for (it = m_tftMap.rbegin (); it != m_tftMap.rend (); ++it)
if (ipType == 0x04)
{
NS_LOG_INFO ("Classifying packet:"
<< " localAddr=" << localAddressIpv4
<< " remoteAddr=" << remoteAddressIpv4
<< " localPort=" << localPort
<< " remotePort=" << remotePort
<< " tos=0x" << (uint16_t) tos );

// now it is possible to classify the packet!
// we use a reverse iterator since filter priority is not implemented properly.
// This way, since the default bearer is expected to be added first, it will be evaluated last.
std::map <uint32_t, Ptr<EpcTft> >::const_reverse_iterator it;
NS_LOG_LOGIC ("TFT MAP size: " << m_tftMap.size ());

for (it = m_tftMap.rbegin (); it != m_tftMap.rend (); ++it)
{
NS_LOG_LOGIC ("TFT id: " << it->first );
NS_LOG_LOGIC (" Ptr<EpcTft>: " << it->second);
Ptr<EpcTft> tft = it->second;
if (tft->Matches (direction, remoteAddressIpv4, localAddressIpv4, remotePort, localPort, tos))
{
NS_LOG_LOGIC ("matches with TFT ID = " << it->first);
return it->first; // the id of the matching TFT
}
}
NS_LOG_LOGIC ("no match");
return 0; // no match
}
else
{
NS_LOG_LOGIC ("TFT id: " << it->first );
NS_LOG_LOGIC (" Ptr<EpcTft>: " << it->second);
Ptr<EpcTft> tft = it->second;
if (tft->Matches (direction, remoteAddress, localAddress, remotePort, localPort, tos))
NS_LOG_INFO ("Classifying packet:"
<< " localAddr=" << localAddressIpv6
<< " remoteAddr=" << remoteAddressIpv6
<< " localPort=" << localPort
<< " remotePort=" << remotePort
<< " tos=0x" << (uint16_t) tos );

// now it is possible to classify the packet!
// we use a reverse iterator since filter priority is not implemented properly.
// This way, since the default bearer is expected to be added first, it will be evaluated last.
std::map <uint32_t, Ptr<EpcTft> >::const_reverse_iterator it;
NS_LOG_LOGIC ("TFT MAP size: " << m_tftMap.size ());

for (it = m_tftMap.rbegin (); it != m_tftMap.rend (); ++it)
{
NS_LOG_LOGIC ("matches with TFT ID = " << it->first);
return it->first; // the id of the matching TFT
NS_LOG_LOGIC ("TFT id: " << it->first );
NS_LOG_LOGIC (" Ptr<EpcTft>: " << it->second);
Ptr<EpcTft> tft = it->second;
if (tft->Matches (direction, remoteAddressIpv6, localAddressIpv6, remotePort, localPort, tos))
{
NS_LOG_LOGIC ("matches with TFT ID = " << it->first);
return it->first; // the id of the matching TFT
}
}
NS_LOG_LOGIC ("no match");
return 0; // no match
}
NS_LOG_LOGIC ("no match");
return 0; // no match
}


Expand Down
78 changes: 76 additions & 2 deletions src/lte/model/epc-tft.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,11 @@ std::ostream& operator<< (std::ostream& os, EpcTft::Direction& d)
std::ostream& operator<< (std::ostream& os, EpcTft::PacketFilter& f)
{
os << " direction: " << f.direction
<< " remoteAddress: " << f.remoteAddress
<< " remoteAddress: " << f.remoteAddress
<< " remoteAddress6: " << f.remoteAddress6
<< " remoteMask: " << f.remoteMask
<< " localAddress: " << f.localAddress
<< " localAddress: " << f.localAddress
<< " localAddress6: " << f.localAddress6
<< " localMask: " << f.localMask
<< " remotePortStart: " << f.remotePortStart
<< " remotePortEnd: " << f.remotePortEnd
Expand Down Expand Up @@ -136,6 +138,57 @@ EpcTft::PacketFilter::Matches (Direction d,
return false;
}

bool
EpcTft::PacketFilter::Matches (Direction d,
Ipv6Address ra,
Ipv6Address la,
uint16_t rp,
uint16_t lp,
uint8_t tos)
{
NS_LOG_FUNCTION (this << d << ra << la << rp << lp << (uint16_t) tos);
if (d & direction)
{
NS_LOG_LOGIC ("d matches");
if (rp >= remotePortStart)
{
NS_LOG_LOGIC ("rps matches");
if (rp <= remotePortEnd)
{
NS_LOG_LOGIC ("rpe matches");
if (lp >= localPortStart)
{
NS_LOG_LOGIC ("lps matches");
if (lp <= localPortEnd)
{
NS_LOG_LOGIC ("lpe matches");
if ((tos & typeOfServiceMask) == (typeOfService & typeOfServiceMask))
{
NS_LOG_LOGIC ("tos matches --> have match!");
return true;
}
}
}
}


else
{
NS_LOG_LOGIC ("la doesn't match: la=" << la << " f.la=" << localAddress << " f.lmask=" << localMask);
}
}
else
{
NS_LOG_LOGIC ("ra doesn't match: ra=" << ra << " f.ra=" << remoteAddress << " f.rmask=" << remoteMask);
}
}
else
{
NS_LOG_LOGIC ("d doesn't match: d=0x" << std::hex << d << " f.d=0x" << std::hex << direction << std::dec);
}
return false;
}


Ptr<EpcTft>
EpcTft::Default ()
Expand Down Expand Up @@ -191,5 +244,26 @@ EpcTft::Matches (Direction direction,
return false;
}

bool
EpcTft::Matches (Direction direction,
Ipv6Address remoteAddress,
Ipv6Address localAddress,
uint16_t remotePort,
uint16_t localPort,
uint8_t typeOfService)
{
NS_LOG_FUNCTION (this << direction << remoteAddress << localAddress << std::dec << remotePort << localPort << (uint16_t) typeOfService);
for (std::list<PacketFilter>::iterator it = m_filters.begin ();
it != m_filters.end ();
++it)
{
if (it->Matches (direction, remoteAddress, localAddress, remotePort, localPort, typeOfService))
{
return true;
}
}
return false;
}


} // namespace ns3
51 changes: 46 additions & 5 deletions src/lte/model/epc-tft.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#include <ns3/simple-ref-count.h>
#include <ns3/ipv4-address.h>
#include <ns3/ipv6-address.h>

#include <list>

Expand Down Expand Up @@ -88,7 +89,26 @@ class EpcTft : public SimpleRefCount<EpcTft>
*/
bool Matches (Direction d,
Ipv4Address ra,
Ipv4Address la,
Ipv4Address la,
uint16_t rp,
uint16_t lp,
uint8_t tos);

/**
*
* \param d the direction
* \param ra the remote address
* \param la the local address
* \param rp the remote port
* \param lp the local port
* \param tos the type of service
*
* \return true if the parameters match with the PacketFilter,
* false otherwise.
*/
bool Matches (Direction d,
Ipv6Address ra,
Ipv6Address la,
uint16_t rp,
uint16_t lp,
uint8_t tos);
Expand All @@ -105,8 +125,10 @@ class EpcTft : public SimpleRefCount<EpcTft>
to uplink / downlink only, or in both cases*/

Ipv4Address remoteAddress; /**< IPv4 address of the remote host */
Ipv4Mask remoteMask; /**< IPv4 address mask of the remote host */
Ipv4Address localAddress; /**< IPv4 address of the UE */
Ipv6Address remoteAddress6; /**< IPv6 address of the remote host */
Ipv4Mask remoteMask; /**< IPv4 address mask of the remote host */
Ipv4Address localAddress; /**< IPv4 address of the UE */
Ipv6Address localAddress6; /**< IPv6 address of the UE */
Ipv4Mask localMask; /**< IPv4 address mask of the UE */

uint16_t remotePortStart; /**< start of the port number range of the remote host */
Expand Down Expand Up @@ -144,8 +166,27 @@ class EpcTft : public SimpleRefCount<EpcTft>
* parameters, false otherwise.
*/
bool Matches (Direction direction,
Ipv4Address remoteAddress,
Ipv4Address localAddress,
Ipv4Address remoteAddress,
Ipv4Address localAddress,
uint16_t remotePort,
uint16_t localPort,
uint8_t typeOfService);

/**
*
* \param direction
* \param remoteAddress
* \param localAddress
* \param remotePort
* \param localPort
* \param typeOfService
*
* \return true if any PacketFilter in the TFT matches with the
* parameters, false otherwise.
*/
bool Matches (Direction direction,
Ipv6Address remoteAddress,
Ipv6Address localAddress,
uint16_t remotePort,
uint16_t localPort,
uint8_t typeOfService);
Expand Down
3 changes: 2 additions & 1 deletion src/lte/model/lte-enb-net-device.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include <ns3/lte-anr.h>
#include <ns3/lte-ffr-algorithm.h>
#include <ns3/ipv4-l3-protocol.h>
#include <ns3/ipv6-l3-protocol.h>
#include <ns3/abort.h>
#include <ns3/log.h>

Expand Down Expand Up @@ -344,7 +345,7 @@ bool
LteEnbNetDevice::Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
{
NS_LOG_FUNCTION (this << packet << dest << protocolNumber);
NS_ASSERT_MSG (protocolNumber == Ipv4L3Protocol::PROT_NUMBER, "unsupported protocol " << protocolNumber << ", only IPv4 is supported");
NS_ASSERT_MSG (protocolNumber == Ipv4L3Protocol::PROT_NUMBER || protocolNumber == Ipv6L3Protocol::PROT_NUMBER, "unsupported protocol " << protocolNumber << ", only IPv4/IPv6 is supported");
return m_rrc->SendData (packet);
}

Expand Down
11 changes: 10 additions & 1 deletion src/lte/model/lte-net-device.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@
#include "ns3/enum.h"
#include "lte-amc.h"
#include "ns3/ipv4-header.h"
#include "ns3/ipv6-header.h"
#include <ns3/lte-radio-bearer-tag.h>
#include <ns3/ipv4-l3-protocol.h>
#include <ns3/ipv6-l3-protocol.h>
#include <ns3/log.h>

namespace ns3 {
Expand Down Expand Up @@ -283,7 +285,14 @@ void
LteNetDevice::Receive (Ptr<Packet> p)
{
NS_LOG_FUNCTION (this << p);
m_rxCallback (this, p, Ipv4L3Protocol::PROT_NUMBER, Address ());
uint8_t ipType;
Ptr<Packet> pCopy = p->Copy ();
pCopy->CopyData (&ipType, 1);
ipType=(ipType>>4) & 0x0f;
if (ipType == 0x04)
m_rxCallback (this, p, Ipv4L3Protocol::PROT_NUMBER, Address ());
else
m_rxCallback (this, p, Ipv6L3Protocol::PROT_NUMBER, Address ());
}


Expand Down
7 changes: 5 additions & 2 deletions src/lte/model/lte-ue-net-device.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,14 @@
#include "lte-ue-mac.h"
#include "lte-ue-rrc.h"
#include "ns3/ipv4-header.h"
#include "ns3/ipv6-header.h"
#include "ns3/ipv4.h"
#include "ns3/ipv6.h"
#include "lte-amc.h"
#include "lte-ue-phy.h"
#include "epc-ue-nas.h"
#include <ns3/ipv4-l3-protocol.h>
#include <ns3/ipv6-l3-protocol.h>
#include <ns3/log.h>
#include "epc-tft.h"

Expand Down Expand Up @@ -252,9 +255,9 @@ bool
LteUeNetDevice::Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
{
NS_LOG_FUNCTION (this << dest << protocolNumber);
if (protocolNumber != Ipv4L3Protocol::PROT_NUMBER)
if (protocolNumber != Ipv4L3Protocol::PROT_NUMBER && protocolNumber != Ipv6L3Protocol::PROT_NUMBER)
{
NS_LOG_INFO("unsupported protocol " << protocolNumber << ", only IPv4 is supported");
NS_LOG_INFO("unsupported protocol " << protocolNumber << ", only IPv4 and IPv6 are supported");
return true;
}
return m_nas->Send (packet);
Expand Down
412 changes: 412 additions & 0 deletions src/lte/test/lena-test-ipv6-routing.cc

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/lte/wscript
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ def build(bld):
'test/lte-test-interference-fr.cc',
'test/lte-test-cqi-generation.cc',
'test/lte-simple-spectrum-phy.cc',
'test/lena-test-ipv6-routing.cc',
]

headers = bld(features='ns3header')
Expand Down