# HG changeset patch # User Tommaso Pecorella # Date 1516934058 21600 # Parent c2f702e4adffbd1bbe55472ac9f60260eb5d7d04 diff --git a/src/lte/doc/source/lte-design.rst b/src/lte/doc/source/lte-design.rst --- a/src/lte/doc/source/lte-design.rst +++ b/src/lte/doc/source/lte-design.rst @@ -120,7 +120,7 @@ The following design choices have been made for the EPC model: - #. The only Packet Data Network (PDN) type supported is IPv4. + #. The Packet Data Network (PDN) type supported is both IPv4 and IPv6. #. The SGW and PGW functional entities are implemented within a single node, which is hence referred to as the SGW/PGW node. #. The scenarios with inter-SGW mobility are not of interests. Hence, a @@ -3098,9 +3098,13 @@ IP networking. The first one is the end-to-end layer, which provides end-to-end connectivity to the users; this layers involves the UEs, the PGW and the remote host (including eventual internet routers and hosts in -between), but does not involve the eNB. By default, UEs are assigned a public IPv4 address in the 7.0.0.0/8 -network, and the PGW gets the address 7.0.0.1, which is used by all -UEs as the gateway to reach the internet. +between), but does not involve the eNB. In this version of LTE, the EPC +supports both IPv4 and IPv6 type users. The 3GPP unique 64 bit IPv6 prefix +allocation process for each UE and PGW is followed here. Each EPC is assigned +an unique 16 bit IPv4 and a 48 bit IPv6 network address from the pool of +7.0.0.0/8 and 7777:f00d::/32 respectively. In the end-to-end IP connection +between UE and PGW, all addresses are configured using these prefixes. +The PGW's address is used by all UEs as the gateway to reach the internet. The second layer of IP networking is the EPC local area network. This involves all eNB nodes and the SGW/PGW node. This network is @@ -3126,17 +3130,19 @@ To begin with, we consider the case of the downlink, which is depicted in Figure :ref:`fig-epc-data-flow-dl`. -Downlink Ipv4 packets are generated from a generic remote host, and +Downlink Ipv4/Ipv6 packets are generated from a generic remote host, and addressed to one of the UE device. Internet routing will take care of forwarding the packet to the generic NetDevice of the SGW/PGW node which is connected to the internet (this is the Gi interface according to 3GPP terminology). The SGW/PGW has a VirtualNetDevice which is -assigned the gateway IP address of the UE subnet; hence, static +assigned the base IPv4 address of the EPC network; hence, static routing rules will cause the incoming packet from the internet to be -routed through this VirtualNetDevice. Such device starts the -GTP/UDP/IP tunneling procedure, by forwarding the packet to a -dedicated application in the SGW/PGW node which is called -EpcSgwPgwApplication. This application does the following operations: +routed through this VirtualNetDevice. In case of IPv6 address as destination, +a manual route towards the VirtualNetDevice is inserted in the routing table, +containg the 48 bit IPv6 prefix from which all the IPv6 addresses of the UEs +and PGW are configured. Such device starts the GTP/UDP/IP tunneling procedure, +by forwarding the packet to a dedicated application in the SGW/PGW node which +is called EpcSgwPgwApplication. This application does the following operations: #. it determines the eNB node to which the UE is attached, by looking at the IP destination address (which is the address of the UE); diff --git a/src/lte/doc/source/lte-user.rst b/src/lte/doc/source/lte-user.rst --- a/src/lte/doc/source/lte-user.rst +++ b/src/lte/doc/source/lte-user.rst @@ -779,9 +779,9 @@ We now explain how to write a simulation program that allows to simulate the EPC in addition to the LTE radio access network. The use -of EPC allows to use IPv4 networking with LTE devices. In other words, +of EPC allows to use IPv4 and IPv6 networking with LTE devices. In other words, you will be able to use the regular ns-3 applications and sockets over -IPv4 over LTE, and also to connect an LTE network to any other IPv4 +IPv4 and IPv6 over LTE, and also to connect an LTE network to any other IPv4 and IPv6 network you might have in your simulation. First of all, in addition to ``LteHelper`` that we already introduced @@ -820,9 +820,9 @@ create the PGW node and configure it so that it can properly handle traffic from/to the LTE radio access network. Still, you need to add some explicit code to connect the PGW to other -IPv4 networks (e.g., the internet). Here is a very simple example about -how to connect a single remote host to the PGW via a point-to-point -link:: +IPv4/IPv6 networks (e.g., the internet, another EPC). Here is a very +simple example about how to connect a single remote host (IPv4 type) +to the PGW via a point-to-point link:: Ptr pgw = epcHelper->GetPgwNode (); @@ -844,16 +844,11 @@ Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign (internetDevices); // interface 0 is localhost, 1 is the p2p device Ipv4Address remoteHostAddr = internetIpIfaces.GetAddress (1); - - -It's important to specify routes so that the remote host can reach LTE -UEs. One way of doing this is by exploiting the fact that the -``PointToPointEpcHelper`` will by default assign to LTE UEs an IP address in the -7.0.0.0 network. With this in mind, it suffices to do:: + Ipv4StaticRoutingHelper ipv4RoutingHelper; Ptr remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject ()); - remoteHostStaticRouting->AddNetworkRouteTo (Ipv4Address ("7.0.0.0"), Ipv4Mask ("255.0.0.0"), 1); + 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 @@ -1046,7 +1041,7 @@ ``LteHelper::InstallEnbDevice`` and ``LteHelper::InstallUeDevice`` functions must have been called before attaching. In an EPC-enabled simulation, it is also -required to have IPv4 properly pre-installed in the UE. +required to have IPv4/IPv6 properly pre-installed in the UE. This method is very simple, but requires you to know exactly which UE belongs to to which eNodeB before the simulation begins. This can be difficult when the UE diff --git a/src/lte/examples/lena-ipv6-addr-conf.cc b/src/lte/examples/lena-ipv6-addr-conf.cc new file mode 100644 --- /dev/null +++ b/src/lte/examples/lena-ipv6-addr-conf.cc @@ -0,0 +1,198 @@ +/* -*- 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 + */ + +#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. + * It configures IPv6 addresses for UEs by setting the 48 bit prefix attribute in epc helper + */ + +NS_LOG_COMPONENT_DEFINE ("EpcFirstExampleForIpv6"); + +int +main (int argc, char *argv[]) +{ + CommandLine cmd; + cmd.Parse (argc, argv); + + //Set 32 bit prefix value + Config::SetDefault ("ns3::PointToPointEpcHelper::BaseIpv6Prefix", Ipv6AddressValue (Ipv6Address ("8888:f00d:432a::"))); + + Ptr lteHelper = CreateObject (); + Ptr epcHelper = CreateObject (); + lteHelper->SetEpcHelper (epcHelper); + + Ptr pgw = epcHelper->GetPgwNode (); + + // Create a single RemoteHost + NodeContainer remoteHostContainer; + remoteHostContainer.Create (1); + Ptr remoteHost = remoteHostContainer.Get (0); + InternetStackHelper internet; + internet.Install (remoteHostContainer); + + // Create the Internet + PointToPointHelper p2ph; + p2ph.SetDeviceAttribute ("DataRate", DataRateValue (DataRate ("100Gb/s"))); + p2ph.SetDeviceAttribute ("Mtu", UintegerValue (1500)); + p2ph.SetChannelAttribute ("Delay", TimeValue (Seconds (0.010))); + NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost); + + NodeContainer ueNodes; + NodeContainer enbNodes; + enbNodes.Create (2); + ueNodes.Create (2); + + // Install Mobility Model + Ptr positionAlloc = CreateObject (); + 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 ueLteDevs1 = lteHelper->InstallUeDevice (NodeContainer (ueNodes.Get (0))); + NetDeviceContainer ueLteDevs2 = lteHelper->InstallUeDevice (NodeContainer (ueNodes.Get (1))); + + Ipv6InterfaceContainer ueIpIface; + + for (NetDeviceContainer::Iterator it = ueLteDevs1.Begin (); it != ueLteDevs1.End (); ++it) + { + (*it)->SetAddress (Mac48Address::Allocate ()); + } + + for (NetDeviceContainer::Iterator it = ueLteDevs2.Begin (); it != ueLteDevs2.End (); ++it) + { + (*it)->SetAddress (Mac48Address::Allocate ()); + } + + + Ipv6AddressHelper ipv6h; + ipv6h.SetBase (Ipv6Address ("6001:db80::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer internetIpIfaces = ipv6h.Assign (internetDevices); + + internetIpIfaces.SetForwarding (0, true); + internetIpIfaces.SetDefaultRouteInAllNodes (0); + + + // Assign IP address to the first UE + ueIpIface = epcHelper->AssignUeIpv6Address (NetDeviceContainer (ueLteDevs1)); + + + Ipv6StaticRoutingHelper ipv6RoutingHelper; + Ptr remoteHostStaticRouting = ipv6RoutingHelper.GetStaticRouting (remoteHost->GetObject ()); + remoteHostStaticRouting->AddNetworkRouteTo ("7777:f00d::", Ipv6Prefix (64), internetIpIfaces.GetAddress (0, 1), 1, 0); + + + // Assign IP address to the second UE + ueIpIface.Add (epcHelper->AssignUeIpv6Address (NetDeviceContainer (ueLteDevs2))); + + + + for (uint32_t u = 0; u < ueNodes.GetN (); ++u) + { + Ptr ueNode = ueNodes.Get (u); + // Set the default gateway for the UEs + Ptr ueStaticRouting = ipv6RoutingHelper.GetStaticRouting (ueNode->GetObject ()); + ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress6 (), 1); + } + + // Attach one UE per eNodeB + lteHelper->Attach (ueLteDevs1.Get (0), enbLteDevs.Get (0)); + lteHelper->Attach (ueLteDevs2.Get (0), enbLteDevs.Get (1)); + + + // interface 0 is localhost, 1 is the p2p device + Ipv6Address remoteHostAddr = internetIpIfaces.GetAddress (1, 1); + + + // Install and start applications on UEs and remote host + + UdpEchoServerHelper echoServer (9); + + ApplicationContainer serverApps = echoServer.Install (remoteHost); + + serverApps.Start (Seconds (4.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 (4.0)); + clientApps1.Stop (Seconds (50.0)); + + clientApps2.Start (Seconds (4.5)); + clientApps2.Stop (Seconds (50.0)); + + + LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_ALL); + LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_ALL); + + internet.EnablePcapIpv6 ("lena9", ueNodes.Get (0)); + internet.EnablePcapIpv6 ("lena10", ueNodes.Get (1)); + internet.EnablePcapIpv6 ("lena11", remoteHostContainer.Get (0)); + internet.EnablePcapIpv6 ("lena12", pgw); + + + Simulator::Stop (Seconds (50)); + Simulator::Run (); + + Simulator::Destroy (); + return 0; + +} + diff --git a/src/lte/examples/lena-ipv6-ue-rh.cc b/src/lte/examples/lena-ipv6-ue-rh.cc new file mode 100644 --- /dev/null +++ b/src/lte/examples/lena-ipv6-ue-rh.cc @@ -0,0 +1,184 @@ +/* -*- 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 + */ + +#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 = CreateObject (); + Ptr epcHelper = CreateObject (); + lteHelper->SetEpcHelper (epcHelper); + + Ptr pgw = epcHelper->GetPgwNode (); + + // Create a single RemoteHost + NodeContainer remoteHostContainer; + remoteHostContainer.Create (1); + Ptr remoteHost = remoteHostContainer.Get (0); + InternetStackHelper internet; + internet.Install (remoteHostContainer); + + // Create the Internet + PointToPointHelper p2ph; + p2ph.SetDeviceAttribute ("DataRate", DataRateValue (DataRate ("100Gb/s"))); + p2ph.SetDeviceAttribute ("Mtu", UintegerValue (1500)); + p2ph.SetChannelAttribute ("Delay", TimeValue (Seconds (0.010))); + NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost); + + NodeContainer ueNodes; + NodeContainer enbNodes; + enbNodes.Create (2); + ueNodes.Create (2); + + // Install Mobility Model + Ptr positionAlloc = CreateObject (); + 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 ueNode = ueNodes.Get (u); + // Set the default gateway for the UEs + Ptr ueStaticRouting = ipv6RoutingHelper.GetStaticRouting (ueNode->GetObject ()); + 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 remoteHostStaticRouting = ipv6RoutingHelper.GetStaticRouting (remoteHost->GetObject ()); + remoteHostStaticRouting->AddNetworkRouteTo ("7777:f00d::", Ipv6Prefix (64), 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; + +} + diff --git a/src/lte/examples/lena-ipv6-ue-ue.cc b/src/lte/examples/lena-ipv6-ue-ue.cc new file mode 100644 --- /dev/null +++ b/src/lte/examples/lena-ipv6-ue-ue.cc @@ -0,0 +1,180 @@ +/* -*- 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 + */ + +#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 = CreateObject (); + Ptr epcHelper = CreateObject (); + lteHelper->SetEpcHelper (epcHelper); + + Ptr pgw = epcHelper->GetPgwNode (); + + // Create a single RemoteHost + NodeContainer remoteHostContainer; + remoteHostContainer.Create (1); + Ptr remoteHost = remoteHostContainer.Get (0); + InternetStackHelper internet; + internet.Install (remoteHostContainer); + + // Create the Internet + PointToPointHelper p2ph; + p2ph.SetDeviceAttribute ("DataRate", DataRateValue (DataRate ("100Gb/s"))); + p2ph.SetDeviceAttribute ("Mtu", UintegerValue (1500)); + p2ph.SetChannelAttribute ("Delay", TimeValue (Seconds (0.010))); + NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost); + + NodeContainer ueNodes; + NodeContainer enbNodes; + enbNodes.Create (2); + ueNodes.Create (2); + + // Install Mobility Model + Ptr positionAlloc = CreateObject (); + 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 ueNode = ueNodes.Get (u); + // Set the default gateway for the UE + Ptr ueStaticRouting = ipv6RoutingHelper.GetStaticRouting (ueNode->GetObject ()); + 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 remoteHostStaticRouting = ipv6RoutingHelper.GetStaticRouting (remoteHost->GetObject ()); + remoteHostStaticRouting->AddNetworkRouteTo ("7777:f00d::", Ipv6Prefix (64), 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; + +} + diff --git a/src/lte/examples/wscript b/src/lte/examples/wscript --- a/src/lte/examples/wscript +++ b/src/lte/examples/wscript @@ -13,6 +13,15 @@ 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' diff --git a/src/lte/helper/emu-epc-helper.cc b/src/lte/helper/emu-epc-helper.cc --- a/src/lte/helper/emu-epc-helper.cc +++ b/src/lte/helper/emu-epc-helper.cc @@ -26,13 +26,15 @@ #include #include #include +#include #include #include #include #include #include #include - +#include "ns3/ipv6-static-routing.h" +#include "ns3/ipv6-static-routing-helper.h" #include #include #include @@ -41,6 +43,8 @@ #include #include #include +#include +#include #include #include @@ -56,7 +60,8 @@ : m_gtpuUdpPort (2152) // fixed by the standard { NS_LOG_FUNCTION (this); - + // To access the attribute value within the constructor + ObjectBase::ConstructSelf (AttributeConstructionList ()); } EmuEpcHelper::~EmuEpcHelper () @@ -95,30 +100,44 @@ return tid; } +TypeId +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 /8 net for all UEs - m_ueAddressHelper.SetBase ("7.0.0.0", "255.0.0.0"); + // we use a /64 IPv6 net all UEs + m_uePgwAddressHelper6.SetBase ("7777:f00d::", Ipv6Prefix (64)); - - + // create SgwPgwNode m_sgwPgw = CreateObject (); InternetStackHelper internet; - internet.SetIpv4StackInstall (true); internet.Install (m_sgwPgw); + + // The Tun device resides in different 64 bit subnet. + // We must create an unique route to tun device for all the packets destined + // to all 64 bit IPv6 prefixes of UEs, based by the unique 48 bit network prefix of this EPC network + Ipv6StaticRoutingHelper ipv6RoutingHelper; + Ptr pgwStaticRouting = ipv6RoutingHelper.GetStaticRouting (m_sgwPgw->GetObject ()); + pgwStaticRouting->AddNetworkRouteTo ("7777:f00d::", Ipv6Prefix (64), Ipv6Address ("::"), 1, 0); // create S1-U socket Ptr sgwPgwS1uSocket = Socket::CreateSocket (m_sgwPgw, TypeId::LookupByName ("ns3::UdpSocketFactory")); int retval = sgwPgwS1uSocket->Bind (InetSocketAddress (Ipv4Address::GetAny (), m_gtpuUdpPort)); NS_ASSERT (retval == 0); - // create TUN device 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 (); + // allow jumbo packets m_tunDevice->SetAttribute ("Mtu", UintegerValue (30000)); @@ -130,9 +149,19 @@ 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 (m_tunDevice, sgwPgwS1uSocket); @@ -141,6 +170,7 @@ // connect SgwPgwApplication and virtual net device for tunneling m_tunDevice->SetSendCallback (MakeCallback (&EpcSgwPgwApplication::RecvFromTunDevice, m_sgwPgwApp)); + // Create MME and connect with SGW via S11 interface m_mme = CreateObject (); m_mme->SetS11SapSgw (m_sgwPgwApp->GetS11SapSgw ()); @@ -184,7 +214,7 @@ 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 ()->GetNInterfaces ()); @@ -231,10 +261,24 @@ enbLteSocketConnectAddress.SetProtocol (Ipv4L3Protocol::PROT_NUMBER); retval = enbLteSocket->Connect (enbLteSocketConnectAddress); NS_ASSERT (retval == 0); + + // create LTE socket for the ENB + Ptr enbLteSocket6 = Socket::CreateSocket (enb, TypeId::LookupByName ("ns3::PacketSocketFactory")); + PacketSocketAddress enbLteSocketBindAddress6; + enbLteSocketBindAddress6.SetSingleDevice (lteEnbNetDevice->GetIfIndex ()); + enbLteSocketBindAddress6.SetProtocol (Ipv6L3Protocol::PROT_NUMBER); + retval = enbLteSocket6->Bind (enbLteSocketBindAddress6); + NS_ASSERT (retval == 0); + PacketSocketAddress enbLteSocketConnectAddress6; + enbLteSocketConnectAddress6.SetPhysicalAddress (Mac48Address::GetBroadcast ()); + enbLteSocketConnectAddress6.SetSingleDevice (lteEnbNetDevice->GetIfIndex ()); + enbLteSocketConnectAddress6.SetProtocol (Ipv6L3Protocol::PROT_NUMBER); + retval = enbLteSocket6->Connect (enbLteSocketConnectAddress6); + NS_ASSERT (retval == 0); - NS_LOG_INFO ("create EpcEnbApplication"); Ptr enbApp = CreateObject (enbLteSocket, enbS1uSocket, enbAddress, sgwAddress, cellId); + enbApp->SetLTESocket6(enbLteSocket6); enb->AddApplication (enbApp); NS_ASSERT (enb->GetNApplications () == 1); NS_ASSERT_MSG (enb->GetApplication (0)->GetObject () != 0, "cannot retrieve EpcEnbApplication"); @@ -312,23 +356,35 @@ } + uint8_t EmuEpcHelper::ActivateEpsBearer (Ptr ueDevice, uint64_t imsi, Ptr 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 ueNode = ueDevice->GetNode (); Ptr ueIpv4 = ueNode->GetObject (); - NS_ASSERT_MSG (ueIpv4 != 0, "UEs need to have IPv4 installed before EPS bearers can be activated"); + Ptr ueIpv6 = ueNode->GetObject (); + //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 ueLteDevice = ueDevice->GetObject (); if (ueLteDevice) @@ -349,10 +405,14 @@ Ipv4InterfaceContainer EmuEpcHelper::AssignUeIpv4Address (NetDeviceContainer ueDevices) { - return m_ueAddressHelper.Assign (ueDevices); + return m_uePgwAddressHelper.Assign (ueDevices); } - +Ipv6InterfaceContainer +EmuEpcHelper::AssignUeIpv6Address (NetDeviceContainer ueDevices) +{ + return m_uePgwAddressHelper6.Assign (ueDevices); +} Ipv4Address EmuEpcHelper::GetUeDefaultGatewayAddress () @@ -361,5 +421,11 @@ return m_sgwPgw->GetObject ()->GetAddress (1, 0).GetLocal (); } +Ipv6Address +EmuEpcHelper::GetUeDefaultGatewayAddress6 () +{ + // return the address of the tun device 6 + return m_sgwPgw->GetObject ()->GetAddress (1, 1).GetAddress (); +} } // namespace ns3 diff --git a/src/lte/helper/emu-epc-helper.h b/src/lte/helper/emu-epc-helper.h --- a/src/lte/helper/emu-epc-helper.h +++ b/src/lte/helper/emu-epc-helper.h @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -70,6 +71,7 @@ * \return The object TypeId. */ static TypeId GetTypeId (void); + TypeId GetInstanceTypeId () const; virtual void DoInitialize (); virtual void DoDispose (); @@ -80,16 +82,22 @@ virtual uint8_t ActivateEpsBearer (Ptr ueLteDevice, uint64_t imsi, Ptr tft, EpsBearer bearer); virtual Ptr 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_ueAddressHelper; + 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-PGW network element @@ -102,7 +110,7 @@ Ptr m_sgwPgwApp; /** - * TUN device implementing tunneling of user data over GTP-U/UDP/IP + * TUN device containing IPv4 address and implementing tunneling of user data over GTP-U/UDP/IP */ Ptr m_tunDevice; @@ -151,6 +159,7 @@ * First 5 bytes of the Enb MAC address base */ std::string m_enbMacAddressBase; + }; diff --git a/src/lte/helper/epc-helper.cc b/src/lte/helper/epc-helper.cc --- a/src/lte/helper/epc-helper.cc +++ b/src/lte/helper/epc-helper.cc @@ -24,6 +24,7 @@ #include #include #include +#include namespace ns3 { diff --git a/src/lte/helper/epc-helper.h b/src/lte/helper/epc-helper.h --- a/src/lte/helper/epc-helper.h +++ b/src/lte/helper/epc-helper.h @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -133,7 +134,7 @@ /** * - * \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; diff --git a/src/lte/helper/point-to-point-epc-helper.cc b/src/lte/helper/point-to-point-epc-helper.cc --- a/src/lte/helper/point-to-point-epc-helper.cc +++ b/src/lte/helper/point-to-point-epc-helper.cc @@ -26,19 +26,23 @@ #include #include #include +#include #include #include #include #include #include #include - +#include "ns3/ipv6-static-routing.h" +#include "ns3/ipv6-static-routing-helper.h" #include #include #include #include #include #include +#include +#include namespace ns3 { @@ -51,6 +55,8 @@ : 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 @@ -60,12 +66,22 @@ 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"); - + m_uePgwAddressHelper.SetBase ("7.0.0.0", "255.0.0.0"); + + // we use a /64 IPv6 net all UEs + m_uePgwAddressHelper6.SetBase ("7777:f00d::", Ipv6Prefix (64)); + // create SgwPgwNode m_sgwPgw = CreateObject (); InternetStackHelper internet; internet.Install (m_sgwPgw); + + // The Tun device resides in different 64 bit subnet. + // We must create an unique route to tun device for all the packets destined + // to all 64 bit IPv6 prefixes of UEs, based by the unique 48 bit network prefix of this EPC network + Ipv6StaticRoutingHelper ipv6RoutingHelper; + Ptr pgwStaticRouting = ipv6RoutingHelper.GetStaticRouting (m_sgwPgw->GetObject ()); + pgwStaticRouting->AddNetworkRouteTo ("7777:f00d::", Ipv6Prefix (64), Ipv6Address ("::"), 1, 0); // create S1-U socket Ptr sgwPgwS1uSocket = Socket::CreateSocket (m_sgwPgw, TypeId::LookupByName ("ns3::UdpSocketFactory")); @@ -74,11 +90,14 @@ // create TUN device implementing tunneling of user data over GTP-U/UDP/IP m_tunDevice = CreateObject (); + // allow jumbo packets m_tunDevice->SetAttribute ("Mtu", UintegerValue (30000)); // yes we need this - m_tunDevice->SetAddress (Mac48Address::Allocate ()); + m_tunDevice->SetAddress (Mac48Address::Allocate ()); + + m_sgwPgw->AddDevice (m_tunDevice); NetDeviceContainer tunDeviceContainer; @@ -87,7 +106,18 @@ // 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 (m_tunDevice, sgwPgwS1uSocket); @@ -96,6 +126,7 @@ // connect SgwPgwApplication and virtual net device for tunneling m_tunDevice->SetSendCallback (MakeCallback (&EpcSgwPgwApplication::RecvFromTunDevice, m_sgwPgwApp)); + // Create MME and connect with SGW via S11 interface m_mme = CreateObject (); m_mme->SetS11SapSgw (m_sgwPgwApp->GetS11SapSgw ()); @@ -144,10 +175,26 @@ UintegerValue (3000), MakeUintegerAccessor (&PointToPointEpcHelper::m_x2LinkMtu), MakeUintegerChecker ()) +// .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 () { @@ -195,12 +242,7 @@ Ptr enbS1uSocket = Socket::CreateSocket (enb, TypeId::LookupByName ("ns3::UdpSocketFactory")); int retval = enbS1uSocket->Bind (InetSocketAddress (enbAddress, m_gtpuUdpPort)); NS_ASSERT (retval == 0); - - // give PacketSocket powers to the eNB - //PacketSocketHelper packetSocket; - //packetSocket.Install (enb); - // create LTE socket for the ENB Ptr enbLteSocket = Socket::CreateSocket (enb, TypeId::LookupByName ("ns3::PacketSocketFactory")); PacketSocketAddress enbLteSocketBindAddress; @@ -214,10 +256,24 @@ enbLteSocketConnectAddress.SetProtocol (Ipv4L3Protocol::PROT_NUMBER); retval = enbLteSocket->Connect (enbLteSocketConnectAddress); NS_ASSERT (retval == 0); - + + // create LTE socket for the ENB + Ptr enbLteSocket6 = Socket::CreateSocket (enb, TypeId::LookupByName ("ns3::PacketSocketFactory")); + PacketSocketAddress enbLteSocketBindAddress6; + enbLteSocketBindAddress6.SetSingleDevice (lteEnbNetDevice->GetIfIndex ()); + enbLteSocketBindAddress6.SetProtocol (Ipv6L3Protocol::PROT_NUMBER); + retval = enbLteSocket6->Bind (enbLteSocketBindAddress6); + NS_ASSERT (retval == 0); + PacketSocketAddress enbLteSocketConnectAddress6; + enbLteSocketConnectAddress6.SetPhysicalAddress (Mac48Address::GetBroadcast ()); + enbLteSocketConnectAddress6.SetSingleDevice (lteEnbNetDevice->GetIfIndex ()); + enbLteSocketConnectAddress6.SetProtocol (Ipv6L3Protocol::PROT_NUMBER); + retval = enbLteSocket6->Connect (enbLteSocketConnectAddress6); + NS_ASSERT (retval == 0); NS_LOG_INFO ("create EpcEnbApplication"); Ptr enbApp = CreateObject (enbLteSocket, enbS1uSocket, enbAddress, sgwAddress, cellId); + enbApp->SetLTESocket6(enbLteSocket6); enb->AddApplication (enbApp); NS_ASSERT (enb->GetNApplications () == 1); NS_ASSERT_MSG (enb->GetApplication (0)->GetObject () != 0, "cannot retrieve EpcEnbApplication"); @@ -298,42 +354,53 @@ { 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 ueNode = ueDevice->GetNode (); Ptr ueIpv4 = ueNode->GetObject (); - NS_ASSERT_MSG (ueIpv4 != 0, "UEs need to have IPv4 installed before EPS bearers can be activated"); + Ptr ueIpv6 = ueNode->GetObject (); + //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 ueLteDevice = ueDevice->GetObject (); if (ueLteDevice) { - ueLteDevice->GetNas ()->ActivateEpsBearer (bearer, tft); + Simulator::ScheduleNow (&EpcUeNas::ActivateEpsBearer, ueLteDevice->GetNas (), bearer, tft); } return bearerId; } - Ptr 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) +{ + return m_uePgwAddressHelper6.Assign (ueDevices); +} Ipv4Address PointToPointEpcHelper::GetUeDefaultGatewayAddress () @@ -342,5 +409,11 @@ return m_sgwPgw->GetObject ()->GetAddress (1, 0).GetLocal (); } +Ipv6Address +PointToPointEpcHelper::GetUeDefaultGatewayAddress6 () +{ + // return the address of the tun device + return m_sgwPgw->GetObject ()->GetAddress (1, 1).GetAddress (); +} } // namespace ns3 diff --git a/src/lte/helper/point-to-point-epc-helper.h b/src/lte/helper/point-to-point-epc-helper.h --- a/src/lte/helper/point-to-point-epc-helper.h +++ b/src/lte/helper/point-to-point-epc-helper.h @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -68,6 +69,7 @@ * \return The object TypeId. */ static TypeId GetTypeId (void); + TypeId GetInstanceTypeId () const; virtual void DoDispose (); // inherited from EpcHelper @@ -77,16 +79,21 @@ virtual uint8_t ActivateEpsBearer (Ptr ueLteDevice, uint64_t imsi, Ptr tft, EpsBearer bearer); virtual Ptr 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_ueAddressHelper; + 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-PGW network element @@ -165,7 +172,6 @@ * because of some big X2 messages, you need a big MTU. */ uint16_t m_x2LinkMtu; - }; diff --git a/src/lte/model/epc-enb-application.cc b/src/lte/model/epc-enb-application.cc --- a/src/lte/model/epc-enb-application.cc +++ b/src/lte/model/epc-enb-application.cc @@ -63,7 +63,16 @@ { static TypeId tid = TypeId ("ns3::EpcEnbApplication") .SetParent () - .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; } @@ -72,14 +81,15 @@ { NS_LOG_FUNCTION (this); m_lteSocket = 0; + m_lteSocket6 = 0; m_s1uSocket = 0; delete m_s1SapProvider; delete m_s1apSapEnb; } - EpcEnbApplication::EpcEnbApplication (Ptr lteSocket, Ptr s1uSocket, Ipv4Address enbS1uAddress, Ipv4Address sgwS1uAddress, uint16_t cellId) : m_lteSocket (lteSocket), + m_lteSocket6 (0), m_s1uSocket (s1uSocket), m_enbS1uAddress (enbS1uAddress), m_sgwS1uAddress (sgwS1uAddress), @@ -240,7 +250,14 @@ EpcEnbApplication::RecvFromLteSocket (Ptr 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 = socket->Recv (); EpsBearerTag tag; @@ -259,6 +276,7 @@ std::map::iterator bidIt = rntiIt->second.find (bid); NS_ASSERT (bidIt != rntiIt->second.end ()); uint32_t teid = bidIt->second; + m_rxLteenbPktTrace (packet->Copy ()); SendToS1uSocket (packet, teid); } } @@ -275,6 +293,7 @@ std::map::iterator it = m_teidRbidMap.find (teid); NS_ASSERT (it != m_teidRbidMap.end ()); + m_rxS1uPktTrace (packet->Copy ()); SendToLteSocket (packet, it->second.m_rnti, it->second.m_bid); } @@ -284,7 +303,20 @@ 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 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); } @@ -314,4 +346,16 @@ //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 lteSocket6) +{ + m_lteSocket6 = lteSocket6; + m_lteSocket6->SetRecvCallback (MakeCallback (&EpcEnbApplication::RecvFromLteSocket, this)); +} + +Ptr EpcEnbApplication::GetLTESocket6() +{ + return m_lteSocket6; +} + } // namespace ns3 diff --git a/src/lte/model/epc-enb-application.h b/src/lte/model/epc-enb-application.h --- a/src/lte/model/epc-enb-application.h +++ b/src/lte/model/epc-enb-application.h @@ -80,6 +80,8 @@ */ EpcEnbApplication (Ptr lteSocket, Ptr s1uSocket, Ipv4Address enbS1uAddress, Ipv4Address sgwS1uAddress, uint16_t cellId); + void SetLTESocket6(Ptr lteSocket6); + Ptr GetLTESocket6(); /** * Destructor * @@ -128,6 +130,14 @@ */ void RecvFromS1uSocket (Ptr socket); + /** + * TracedCallback signature for data Packet reception event. + * + * \param [in] packet The data packet sent from the internet. + */ + typedef void (* RxTracedCallback) + (Ptr packet); + /** * EPS flow ID structure @@ -246,6 +256,11 @@ Ptr m_lteSocket; /** + * raw packet socket to send and receive the packets to and from the LTE radio interface + */ + Ptr m_lteSocket6; + + /** * UDP socket to send and receive GTP-U the packets to and from the S1-U interface */ Ptr m_s1uSocket; @@ -307,6 +322,15 @@ uint16_t m_cellId; ///< cell ID + /** + * \brief Callback to trace RX (reception) data packets from LTE Enb Net Device. + */ + TracedCallback > m_rxLteenbPktTrace; + + /** + * \brief Callback to trace RX (reception) data packets from S1-U Net Device. + */ + TracedCallback > m_rxS1uPktTrace; }; } //namespace ns3 diff --git a/src/lte/model/epc-sgw-pgw-application.cc b/src/lte/model/epc-sgw-pgw-application.cc --- a/src/lte/model/epc-sgw-pgw-application.cc +++ b/src/lte/model/epc-sgw-pgw-application.cc @@ -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" @@ -91,6 +93,18 @@ m_ueAddr = ueAddr; } +Ipv6Address +EpcSgwPgwApplication::UeInfo::GetUeAddr6 () +{ + return m_ueAddr6; +} + +void +EpcSgwPgwApplication::UeInfo::SetUeAddr6 (Ipv6Address ueAddr) +{ + m_ueAddr6 = ueAddr; +} + ///////////////////////// // EpcSgwPgwApplication ///////////////////////// @@ -101,7 +115,16 @@ { static TypeId tid = TypeId ("ns3::EpcSgwPgwApplication") .SetParent () - .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; } @@ -115,7 +138,6 @@ } - EpcSgwPgwApplication::EpcSgwPgwApplication (const Ptr tunDevice, const Ptr s1uSocket) : m_s1uSocket (s1uSocket), m_tunDevice (tunDevice), @@ -139,33 +161,65 @@ EpcSgwPgwApplication::RecvFromTunDevice (Ptr 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 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 >::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 >::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 >::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. @@ -184,6 +238,8 @@ uint32_t teid = gtpu.GetTeid (); SendToTunDevice (packet, teid); + + m_rxS1uPktTrace (packet->Copy ()); } void @@ -191,7 +247,19 @@ { 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 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 @@ -251,6 +319,16 @@ } void +EpcSgwPgwApplication::SetUeAddress6 (uint64_t imsi, Ipv6Address ueAddr) +{ + NS_LOG_FUNCTION (this << imsi << ueAddr); + std::map >::iterator ueit = m_ueInfoByImsiMap.find (imsi); + NS_ASSERT_MSG (ueit != m_ueInfoByImsiMap.end (), "unknown IMSI " << imsi); + m_ueInfoByAddrMap6[ueAddr] = ueit->second; + ueit->second->SetUeAddr6 (ueAddr); +} + +void EpcSgwPgwApplication::DoCreateSessionRequest (EpcS11SapSgw::CreateSessionRequestMessage req) { NS_LOG_FUNCTION (this << req.imsi); diff --git a/src/lte/model/epc-sgw-pgw-application.h b/src/lte/model/epc-sgw-pgw-application.h --- a/src/lte/model/epc-sgw-pgw-application.h +++ b/src/lte/model/epc-sgw-pgw-application.h @@ -67,6 +67,7 @@ * internet over GTP-U/UDP/IP on the S1-U interface * \param s1uSocket socket used to send GTP-U packets to the eNBs */ + EpcSgwPgwApplication (const Ptr tunDevice, const Ptr s1uSocket); /** @@ -155,6 +156,22 @@ */ void SetUeAddress (uint64_t imsi, Ipv4Address ueAddr); + /** + * set the address of a previously added UE + * + * \param imsi the unique identifier of the UE + * \param ueAddr the IPv6 address of the UE + */ + void SetUeAddress6 (uint64_t imsi, Ipv6Address ueAddr); + + /** + * TracedCallback signature for data Packet reception event. + * + * \param [in] packet The data packet sent from the internet. + */ + typedef void (* RxTracedCallback) + (Ptr packet); + private: // S11 SAP SGW methods @@ -238,11 +255,23 @@ */ 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; ///< TFT classifier Ipv4Address m_enbAddr; ///< ENB address Ipv4Address m_ueAddr; ///< UE address + Ipv6Address m_ueAddr6; ///< UE address std::map m_teidByBearerIdMap; ///< TEID By bearer ID Map }; @@ -259,11 +288,16 @@ Ptr 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 > m_ueInfoByAddrMap; /** + * Map telling for each UE IPv6 address the corresponding UE info + */ + std::map > m_ueInfoByAddrMap6; + + /** * Map telling for each IMSI the corresponding UE info */ std::map > m_ueInfoByImsiMap; @@ -298,6 +332,16 @@ }; std::map m_enbInfoByCellId; ///< eNB info by cell ID + + /** + * \brief Callback to trace RX (reception) data packets at Tun Net Device from internet. + */ + TracedCallback > m_rxTunPktTrace; + + /** + * \brief Callback to trace RX (reception) data packets from S1-U socket. + */ + TracedCallback > m_rxS1uPktTrace; }; } //namespace ns3 diff --git a/src/lte/model/epc-tft-classifier.cc b/src/lte/model/epc-tft-classifier.cc --- a/src/lte/model/epc-tft-classifier.cc +++ b/src/lte/model/epc-tft-classifier.cc @@ -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 { @@ -71,62 +71,100 @@ Ptr pCopy = p->Copy (); - Ipv4Header ipv4Header; - pCopy->RemoveHeader (ipv4Header); - - Ipv4Address localAddress; - Ipv4Address remoteAddress; + uint8_t ipType; + pCopy->CopyData (&ipType, 1); + ipType = (ipType>>4) & 0x0f; - - if (direction == EpcTft::UPLINK) - { - localAddress = ipv4Header.GetSource (); - remoteAddress = ipv4Header.GetDestination (); - } - else - { - NS_ASSERT (direction == EpcTft::DOWNLINK); - remoteAddress = ipv4Header.GetSource (); - localAddress = ipv4Header.GetDestination (); - } - - uint8_t protocol = ipv4Header.GetProtocol (); + Ipv4Address localAddressIpv4; + Ipv4Address remoteAddressIpv4; - uint8_t tos = ipv4Header.GetTos (); + Ipv6Address localAddressIpv6; + Ipv6Address remoteAddressIpv6; + + uint8_t protocol; + uint8_t tos; uint16_t localPort = 0; uint16_t remotePort = 0; + if (ipType == 0x04) + { + 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 + { + Ipv6Header ipv6Header; + pCopy->RemoveHeader (ipv6Header); + + 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); + + 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 { @@ -134,32 +172,64 @@ return 0; // no match } - NS_LOG_INFO ("Classifing packet:" - << " localAddr=" << localAddress - << " remoteAddr=" << remoteAddress - << " localPort=" << localPort - << " remotePort=" << remotePort - << " tos=0x" << (uint16_t) tos ); + 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 >::const_reverse_iterator it; - NS_LOG_LOGIC ("TFT MAP size: " << m_tftMap.size ()); + // 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 >::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: " << it->second); - Ptr tft = it->second; - if (tft->Matches (direction, remoteAddress, localAddress, remotePort, localPort, tos)) + 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: " << it->second); + Ptr 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 } - NS_LOG_LOGIC ("no match"); - return 0; // no match + else + { + 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 >::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: " << it->second); + Ptr 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 + } } diff --git a/src/lte/model/epc-tft.cc b/src/lte/model/epc-tft.cc --- a/src/lte/model/epc-tft.cc +++ b/src/lte/model/epc-tft.cc @@ -65,9 +65,11 @@ 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 @@ -150,6 +152,57 @@ 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::Default () @@ -205,5 +258,26 @@ 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::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 diff --git a/src/lte/model/epc-tft.h b/src/lte/model/epc-tft.h --- a/src/lte/model/epc-tft.h +++ b/src/lte/model/epc-tft.h @@ -25,6 +25,7 @@ #include #include +#include #include @@ -88,7 +89,26 @@ */ 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); @@ -105,8 +125,10 @@ 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 */ @@ -144,8 +166,27 @@ * 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); diff --git a/src/lte/model/lte-enb-net-device.cc b/src/lte/model/lte-enb-net-device.cc --- a/src/lte/model/lte-enb-net-device.cc +++ b/src/lte/model/lte-enb-net-device.cc @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -387,7 +388,7 @@ LteEnbNetDevice::Send (Ptr 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); } diff --git a/src/lte/model/lte-net-device.cc b/src/lte/model/lte-net-device.cc --- a/src/lte/model/lte-net-device.cc +++ b/src/lte/model/lte-net-device.cc @@ -32,8 +32,10 @@ #include "ns3/enum.h" #include "lte-amc.h" #include "ns3/ipv4-header.h" +#include "ns3/ipv6-header.h" #include #include +#include #include namespace ns3 { @@ -283,7 +285,14 @@ LteNetDevice::Receive (Ptr p) { NS_LOG_FUNCTION (this << p); - m_rxCallback (this, p, Ipv4L3Protocol::PROT_NUMBER, Address ()); + uint8_t ipType; + Ptr 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 ()); } diff --git a/src/lte/model/lte-ue-net-device.cc b/src/lte/model/lte-ue-net-device.cc --- a/src/lte/model/lte-ue-net-device.cc +++ b/src/lte/model/lte-ue-net-device.cc @@ -39,11 +39,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 +#include #include #include "epc-tft.h" #include @@ -284,9 +287,9 @@ LteUeNetDevice::Send (Ptr 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); diff --git a/src/lte/test/lte-test-ipv6-routing.cc b/src/lte/test/lte-test-ipv6-routing.cc new file mode 100644 --- /dev/null +++ b/src/lte/test/lte-test-ipv6-routing.cc @@ -0,0 +1,414 @@ +/* -*- 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 + */ + +#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" +#include + + +/* * + * Scenario: 3 UEs, 2 ENBs, 1 Remote Host, UE0<-->ENB0, UE1<-->ENB0, UE2<-->ENB1 + Servers: UE1, UE2, Remote Host + Client: UE0 (3 clients) + UDP Echo Packets transmitted between client and server + + * Pass criteria: 1) Every UDP Echo Request and Reply messages sent and received respectively + at UE0 must be matched by their UID, source address, destination address, + source port and destination port + 2) Every request reply must follow proper route (e.g. In case of UE0->UE1, + packet must travel this route: UE0->ENB0->PGW->ENB1->UE1->ENB1->PGW->ENB0->UE0) + 3) The above check also ensures no redundancy of the followed route for a packet +* */ + + + +using namespace ns3; + +class LteIpv6RoutingTestCase : public TestCase +{ +public: + LteIpv6RoutingTestCase (); + virtual ~LteIpv6RoutingTestCase (); + + /** + * \brief Initialize testing parameters. + */ + void Checker (); + + /** + * \brief sent Packets from client's IPv6 interface. + * \param: p packet + * \param: ipv6 Ipv6 object + * \param: interface Ipv6interface from which the packet is transmitted + */ + void SentAtClient (Ptr p, Ptr ipv6, uint32_t interface); + + /** + * \brief Received Packets at client's IPv6 interface. + * \param: p packet + * \param: ipv6 Ipv6 object + * \param: interface Ipv6interface at which the packet is received + */ + void ReceivedAtClient (Ptr p, Ptr ipv6, uint32_t interface); + + /** + * \brief Received Packet at pgw from enb. + * \param: p packet + */ + void EnbToPgw (Ptr p); + + /** + * \brief Received Packet at pgw from enb. + * \param: p packet + */ + void TunToPgw (Ptr p); + + /** + * \brief search uid in a list and delete if found. + * \param: l list + * \param: item a uid + */ + bool SearchAndDelete (std::list *l, uint64_t item); + + +private: + virtual void DoRun (void); + Ipv6InterfaceContainer ueIpIface; //IPv6 interface container for ue + Ipv6Address remoteHostAddr; //remote host address + std::list * EnbPgw; //list of uids of packets received at pgw from enb + std::list * TunPgw; //list of uids of packets received at pgw from tunnel net device + + std::list > ClientSent; //list of sent packets from client + std::list > ClientReceived; //list of received packets at client +}; + + +LteIpv6RoutingTestCase::LteIpv6RoutingTestCase () + : TestCase ("Test IPv6 Routing at LTE") +{ + EnbPgw = new std::list; + TunPgw = new std::list; +} + +LteIpv6RoutingTestCase::~LteIpv6RoutingTestCase () +{ +} + +void LteIpv6RoutingTestCase::SentAtClient (Ptr p, Ptr ipv6, uint32_t interface) +{ + Ipv6Header ipv6Header; + p->PeekHeader (ipv6Header); + if (ipv6Header.GetNextHeader () == UdpL4Protocol::PROT_NUMBER) + { + ClientSent.push_back (p->Copy ()); + } +} + +void LteIpv6RoutingTestCase::ReceivedAtClient (Ptr p, Ptr ipv6, uint32_t interface) +{ + Ipv6Header ipv6Header; + p->PeekHeader (ipv6Header); + if (ipv6Header.GetNextHeader () == UdpL4Protocol::PROT_NUMBER) + { + ClientReceived.push_back (p->Copy ()); + } +} + +void LteIpv6RoutingTestCase::EnbToPgw (Ptr p) +{ + Ipv6Header ipv6Header; + p->PeekHeader (ipv6Header); + if (ipv6Header.GetNextHeader () == UdpL4Protocol::PROT_NUMBER) + { + EnbPgw->push_back (p->GetUid ()); + } +} + +void LteIpv6RoutingTestCase::TunToPgw (Ptr p) +{ + Ipv6Header ipv6Header; + p->PeekHeader (ipv6Header); + if (ipv6Header.GetNextHeader () == UdpL4Protocol::PROT_NUMBER) + { + TunPgw->push_back (p->GetUid ()); + } +} + +bool LteIpv6RoutingTestCase::SearchAndDelete (std::list *l, uint64_t item) +{ + bool b = false; + std::list::iterator it; + it = std::find (l->begin (), l->end (), item); + if (it != l->end ()) + { + b = true; + l->erase (it); + } + return b; +} + +void LteIpv6RoutingTestCase::Checker () +{ + bool b = false; + bool check = true; + //Extract each received reply packet of the client + for (std::list >::iterator it1 = ClientReceived.begin (); it1 != ClientReceived.end (); it1++) + { + Ipv6Header ipv6header1; + UdpHeader udpHeader1; + Ptr p1 = (*it1)->Copy (); + p1->RemoveHeader (ipv6header1); + uint64_t uid = p1->GetUid (); + p1->RemoveHeader (udpHeader1); + //Search each packet in list of sent request packet of the client + for (std::list >::iterator it2 = ClientSent.begin (); it2 != ClientSent.end (); it2++) + { + Ptr p2 = (*it2)->Copy (); + Ipv6Header ipv6header2; + p2->RemoveHeader (ipv6header2); + Ipv6Address sorceAddress = ipv6header2.GetSourceAddress (); + Ipv6Address destinationAddress = ipv6header2.GetDestinationAddress (); + UdpHeader udpHeader2; + p2->RemoveHeader (udpHeader2); + uint16_t sourcePort; + uint16_t destinationPort; + sourcePort = udpHeader2.GetSourcePort (); + destinationPort = udpHeader2.GetDestinationPort (); + //Check whether the uids, addresses and ports match + if ((p2->GetUid () == p1->GetUid ()) && sorceAddress.IsEqual (ipv6header1.GetDestinationAddress ()) && destinationAddress.IsEqual (ipv6header1.GetSourceAddress ()) && sourcePort == udpHeader1.GetDestinationPort () && destinationPort == udpHeader1.GetSourcePort ()) + { + b = true; + break; + } + } + check &= b; + if (ipv6header1.GetSourceAddress ().IsEqual (remoteHostAddr)) + { + check &= (SearchAndDelete (EnbPgw, uid) && SearchAndDelete (TunPgw, uid)); + } + else + { + check &= (SearchAndDelete (EnbPgw, uid) && SearchAndDelete (TunPgw, uid) && SearchAndDelete (EnbPgw, uid) && SearchAndDelete (TunPgw, uid)); + } + + b = false; + } + + NS_TEST_ASSERT_MSG_EQ (check, true, "Failure Happens IPv6 routing of LENA"); + NS_TEST_ASSERT_MSG_EQ (ClientSent.size (), ClientReceived.size (), "No. of Request and Reply messages mismatch"); + NS_TEST_ASSERT_MSG_EQ (EnbPgw->size (), 0, "Route is not Redundant in Lte IPv6 test"); + NS_TEST_ASSERT_MSG_EQ (TunPgw->size (), 0, "Route is not Redundant in Lte IPv6 test"); + +} + +void +LteIpv6RoutingTestCase::DoRun (void) +{ + double distance = 60.0; + + Ptr lteHelper = CreateObject (); + Ptr epcHelper = CreateObject (); + lteHelper->SetEpcHelper (epcHelper); + + ConfigStore inputConfig; + inputConfig.ConfigureDefaults (); + + Ptr pgw = epcHelper->GetPgwNode (); + + // Create a single RemoteHost + NodeContainer remoteHostContainer; + remoteHostContainer.Create (1); + Ptr remoteHost = remoteHostContainer.Get (0); + InternetStackHelper internet; + internet.Install (remoteHostContainer); + + // Create the Internet + PointToPointHelper p2ph; + p2ph.SetDeviceAttribute ("DataRate", DataRateValue (DataRate ("100Gb/s"))); + p2ph.SetDeviceAttribute ("Mtu", UintegerValue (1500)); + p2ph.SetChannelAttribute ("Delay", TimeValue (Seconds (0.010))); + NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost); + + NodeContainer ueNodes; + NodeContainer enbNodes; + enbNodes.Create (2); + ueNodes.Create (3); + + // Install Mobility Model + Ptr positionAlloc1 = CreateObject (); + Ptr positionAlloc2 = CreateObject (); + + positionAlloc1->Add (Vector (distance * 0, 0, 0)); + positionAlloc1->Add (Vector (distance * 0 + 5, 0, 0)); + positionAlloc1->Add (Vector (distance * 1, 0, 0)); + + positionAlloc2->Add (Vector (distance * 0, 0, 0)); + positionAlloc2->Add (Vector (distance * 1, 0, 0)); + + MobilityHelper mobility; + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + mobility.SetPositionAllocator (positionAlloc1); + mobility.Install (ueNodes); + + mobility.SetPositionAllocator (positionAlloc2); + mobility.Install (enbNodes); + + // 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); + + + + for (NetDeviceContainer::Iterator it = ueLteDevs.Begin (); it != ueLteDevs.End (); ++it) + { + (*it)->SetAddress (Mac48Address::Allocate ()); + } + + // Assign IP address to UEs, and install applications + ueIpIface = epcHelper->AssignUeIpv6Address (NetDeviceContainer (ueLteDevs)); + + + Ipv6StaticRoutingHelper ipv6RoutingHelper; + + for (uint32_t u = 0; u < ueNodes.GetN (); ++u) + { + Ptr ueNode = ueNodes.Get (u); + // Set the default gateway for the UE + Ptr ueStaticRouting = ipv6RoutingHelper.GetStaticRouting (ueNode->GetObject ()); + ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress6 (), 1); + } + + + // Attach two UEs at first eNodeB and one UE at second eNodeB + lteHelper->Attach (ueLteDevs.Get (0), enbLteDevs.Get (0)); + lteHelper->Attach (ueLteDevs.Get (1), enbLteDevs.Get (0)); + lteHelper->Attach (ueLteDevs.Get (2), enbLteDevs.Get (1)); + + + Ipv6AddressHelper ipv6h; + ipv6h.SetBase (Ipv6Address ("6001:db80::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer internetIpIfaces = ipv6h.Assign (internetDevices); + + internetIpIfaces.SetForwarding (0, true); + internetIpIfaces.SetDefaultRouteInAllNodes (0); + + + Ptr remoteHostStaticRouting = ipv6RoutingHelper.GetStaticRouting (remoteHost->GetObject ()); + remoteHostStaticRouting->AddNetworkRouteTo ("7777:f00d::", Ipv6Prefix (64), internetIpIfaces.GetAddress (0, 1), 1, 0); + + + // interface 0 is localhost, 1 is the p2p device + remoteHostAddr = internetIpIfaces.GetAddress (1, 1); + + + // Install and start applications on UEs and remote host + UdpEchoServerHelper echoServer1 (10); + UdpEchoServerHelper echoServer2 (11); + UdpEchoServerHelper echoServer3 (12); + + ApplicationContainer serverApps = echoServer1.Install (remoteHost); + serverApps.Add (echoServer2.Install (ueNodes.Get (1))); + serverApps.Add (echoServer3.Install (ueNodes.Get (2))); + + + serverApps.Start (Seconds (4.0)); + serverApps.Stop (Seconds (12.0)); + + + UdpEchoClientHelper echoClient1 (remoteHostAddr, 10); + UdpEchoClientHelper echoClient2 (ueIpIface.GetAddress (1,1), 11); + UdpEchoClientHelper echoClient3 (ueIpIface.GetAddress (2,1), 12); + + echoClient1.SetAttribute ("MaxPackets", UintegerValue (1000)); + echoClient1.SetAttribute ("Interval", TimeValue (Seconds (0.2))); + echoClient1.SetAttribute ("PacketSize", UintegerValue (1024)); + + echoClient2.SetAttribute ("MaxPackets", UintegerValue (1000)); + echoClient2.SetAttribute ("Interval", TimeValue (Seconds (0.2))); + echoClient2.SetAttribute ("PacketSize", UintegerValue (1024)); + + echoClient3.SetAttribute ("MaxPackets", UintegerValue (1000)); + echoClient3.SetAttribute ("Interval", TimeValue (Seconds (0.2))); + echoClient3.SetAttribute ("PacketSize", UintegerValue (1024)); + + ApplicationContainer clientApps1 = echoClient1.Install (ueNodes.Get (0)); + ApplicationContainer clientApps2 = echoClient2.Install (ueNodes.Get (0)); + ApplicationContainer clientApps3 = echoClient3.Install (ueNodes.Get (0)); + + clientApps1.Start (Seconds (4.0)); + clientApps1.Stop (Seconds (6.0)); + + clientApps2.Start (Seconds (6.1)); + clientApps2.Stop (Seconds (8.0)); + + clientApps3.Start (Seconds (8.1)); + clientApps3.Stop (Seconds (10.0)); + + EnbPgw = new std::list; + TunPgw = new std::list; + + //Set Cllback for Client Sent and Received packets + Ptr ipl3 = (ueNodes.Get (0))->GetObject (); + ipl3->TraceConnectWithoutContext ("Tx", MakeCallback (&LteIpv6RoutingTestCase::SentAtClient, this)); + ipl3->TraceConnectWithoutContext ("Rx", MakeCallback (&LteIpv6RoutingTestCase::ReceivedAtClient, this)); + + //Set Callback at SgwPgWApplication of epc to get the packets from enb and from tunnel net device + Ptr apppgw = pgw->GetApplication (0); + apppgw->TraceConnectWithoutContext ("RxfromS1u", MakeCallback (&LteIpv6RoutingTestCase::EnbToPgw, this)); + apppgw->TraceConnectWithoutContext ("RxfromTun", MakeCallback (&LteIpv6RoutingTestCase::TunToPgw, this)); + + Simulator::Schedule (Time (Seconds (12.0)), &LteIpv6RoutingTestCase::Checker, this); + + Simulator::Stop (Seconds (14)); + Simulator::Run (); + + Simulator::Destroy (); +} + + +/** + * \brief test suite 1 + */ +class LteIpv6RoutingTestSuite : public TestSuite +{ +public: + LteIpv6RoutingTestSuite (); +}; + +LteIpv6RoutingTestSuite::LteIpv6RoutingTestSuite () + : TestSuite ("lte-ipv6-routing-test", UNIT) +{ + AddTestCase (new LteIpv6RoutingTestCase, TestCase::QUICK); +} + +static LteIpv6RoutingTestSuite lteipv6testsuite; diff --git a/src/lte/wscript b/src/lte/wscript --- a/src/lte/wscript +++ b/src/lte/wscript @@ -191,6 +191,7 @@ 'test/lte-simple-spectrum-phy.cc', 'test/lte-test-carrier-aggregation.cc', 'test/lte-test-aggregation-throughput-scale.cc', + 'test/lte-test-ipv6-routing.cc' ] headers = bld(features='ns3header')