S1-U working in downlink
This commit is contained in:
@@ -116,8 +116,8 @@ int main (int argc, char *argv[])
|
||||
// Activate an EPS bearer on all UEs
|
||||
enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
|
||||
EpsBearer bearer (q);
|
||||
lena->ActivateEpsBearer (ueDevs1, bearer);
|
||||
lena->ActivateEpsBearer (ueDevs2, bearer);
|
||||
lena->ActivateEpsBearer (ueDevs1, bearer, LteTft::Default ());
|
||||
lena->ActivateEpsBearer (ueDevs2, bearer, LteTft::Default ());
|
||||
|
||||
Simulator::Stop (Seconds (10));
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ int main (int argc, char *argv[])
|
||||
// Activate an EPS bearer
|
||||
enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
|
||||
EpsBearer bearer (q);
|
||||
lena->ActivateEpsBearer (ueDevs, bearer);
|
||||
lena->ActivateEpsBearer (ueDevs, bearer, LteTft::Default ());
|
||||
|
||||
|
||||
Simulator::Stop (Seconds (0.010));
|
||||
|
||||
@@ -71,7 +71,7 @@ int main (int argc, char *argv[])
|
||||
// Activate an EPS bearer
|
||||
enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
|
||||
EpsBearer bearer (q);
|
||||
lena->ActivateEpsBearer (ueDevs, bearer);
|
||||
lena->ActivateEpsBearer (ueDevs, bearer, LteTft::Default ());
|
||||
|
||||
Simulator::Stop (Seconds (5));
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ int main (int argc, char *argv[])
|
||||
lena->Attach (ueDev, enbDevs.Get (i));
|
||||
enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
|
||||
EpsBearer bearer (q);
|
||||
lena->ActivateEpsBearer (ueDev, bearer);
|
||||
lena->ActivateEpsBearer (ueDev, bearer, LteTft::Default ());
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -21,9 +21,17 @@
|
||||
|
||||
#include <ns3/epc-helper.h>
|
||||
#include <ns3/log.h>
|
||||
#include "ns3/inet-socket-address.h"
|
||||
#include "ns3/mac48-address.h"
|
||||
#include "ns3/epc-gtpu-tunnel-endpoint.h"
|
||||
#include <ns3/inet-socket-address.h>
|
||||
#include <ns3/mac48-address.h>
|
||||
#include <ns3/epc-gtpu-tunnel-endpoint.h>
|
||||
#include <ns3/eps-bearer.h>
|
||||
#include <ns3/ipv4-address.h>
|
||||
#include <ns3/internet-stack-helper.h>
|
||||
#include <ns3/point-to-point-helper.h>
|
||||
#include <ns3/packet-socket-helper.h>
|
||||
#include <ns3/packet-socket-address.h>
|
||||
#include <ns3/epc-enb-application.h>
|
||||
#include <ns3/epc-sgw-pgw-application.h>
|
||||
|
||||
|
||||
namespace ns3 {
|
||||
@@ -33,30 +41,49 @@ NS_LOG_COMPONENT_DEFINE ("EpcHelper");
|
||||
NS_OBJECT_ENSURE_REGISTERED (EpcHelper);
|
||||
|
||||
EpcHelper::EpcHelper ()
|
||||
: m_gtpuUdpPort (2152) // fixed by the standard
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
// since we use point-to-point links for all S1-U links,
|
||||
// we use a /30 subnet which can hold exactly two addresses
|
||||
// (remember that net broadcast and null address are not valid)
|
||||
m_s1uIpv4AddressHelper.SetBase ("10.7.0.0", "255.255.255.252");
|
||||
m_s1uIpv4AddressHelper.SetBase ("10.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");
|
||||
|
||||
// create SgwPgwNode
|
||||
m_sgwPgw = CreateObject<Node> ();
|
||||
InternetStackHelper internet;
|
||||
internet.Install (m_sgwPgw);
|
||||
|
||||
// create S1-U socket
|
||||
Ptr<Socket> sgwPgwS1uSocket = Socket::CreateSocket (m_sgwPgw, TypeId::LookupByName ("ns3::UdpSocketFactory"));
|
||||
sgwPgwS1uSocket->Bind (InetSocketAddress (Ipv4Address::GetAny (), m_gtpuUdpPort));
|
||||
int retval = sgwPgwS1uSocket->Bind (InetSocketAddress (Ipv4Address::GetAny (), m_gtpuUdpPort));
|
||||
NS_ASSERT (retval == 0);
|
||||
|
||||
// create SgwPgwApplication
|
||||
// create TUN device implementing tunneling of user data over GTP-U/UDP/IP
|
||||
Ptr<VirtualNetDevice> giTunDevice = CreateObject<VirtualNetDevice> ();
|
||||
|
||||
// create WAN NetDevice?
|
||||
// yes we need this
|
||||
giTunDevice->SetAddress (Mac48Address::Allocate ());
|
||||
|
||||
// create virtual net device
|
||||
m_sgwPgw->AddDevice (giTunDevice);
|
||||
NetDeviceContainer giTunDeviceContainer;
|
||||
giTunDeviceContainer.Add (giTunDevice);
|
||||
|
||||
// interface SgwPgwApplication and virtual net device for tunneling
|
||||
// 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 giTunDeviceIpv4IfContainer = m_ueAddressHelper.Assign (giTunDeviceContainer);
|
||||
|
||||
// set up static routes appropriately
|
||||
// create EpcSgwPgwApplication
|
||||
m_sgwPgwApp = CreateObject<EpcSgwPgwApplication> (giTunDevice, sgwPgwS1uSocket);
|
||||
m_sgwPgw->AddApplication (m_sgwPgwApp);
|
||||
|
||||
// connect SgwPgwApplication and virtual net device for tunneling
|
||||
giTunDevice->SetSendCallback (MakeCallback (&EpcSgwPgwApplication::RecvFromGiTunDevice, m_sgwPgwApp));
|
||||
|
||||
}
|
||||
|
||||
@@ -71,10 +98,6 @@ EpcHelper::GetTypeId (void)
|
||||
static TypeId tid = TypeId ("ns3::EpcHelper")
|
||||
.SetParent<Object> ()
|
||||
.AddConstructor<EpcHelper> ()
|
||||
.AddAttribute ("", "The IP address to assign to the tap device, when in ConfigureLocal mode. "
|
||||
Ipv4AddressValue ("255.255.255.255"),
|
||||
MakeIpv4AddressAccessor (&TapBridge::m_tapIp),
|
||||
MakeIpv4AddressChecker ())
|
||||
.AddAttribute ("S1uLinkDataRate",
|
||||
"The data rate to be used for the next S1-U link to be created",
|
||||
DataRateValue (DataRate ("10Gb/s")),
|
||||
@@ -83,31 +106,24 @@ EpcHelper::GetTypeId (void)
|
||||
.AddAttribute ("S1uLinkDelay",
|
||||
"The delay to be used for the next S1-U link to be created",
|
||||
TimeValue (Seconds (0)),
|
||||
MakeTimeAccessor (&EpcHelper::m_m_s1uLinkDelay),
|
||||
MakeTimeAccessor (&EpcHelper::m_s1uLinkDelay),
|
||||
MakeTimeChecker ())
|
||||
.AddAttribute("GtpuPort",
|
||||
"UDP Port to be used for GTP-U",
|
||||
UintegerValue (2152),
|
||||
MakeUintegerAccessor (&EpcHelper::m_gtpuUdpPort),
|
||||
MakeUintegerChecker<uint16_t> ())
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
void
|
||||
EpcHelper::CreateSgwPgw ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EpcHelper::AddEnb (Ptr<Node> enb, Ptr<NetDevice> lteEnbNetDevice)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << enb << lteEnbNetDevice);
|
||||
|
||||
NS_ASSERT (enb == lteEnbNetDevice->GetNode ());
|
||||
|
||||
// add an IPv4 stack to the previously created eNB
|
||||
InternetStackHelper internet;
|
||||
internet.Install (enb);
|
||||
NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB after node creation: " << enb->GetObject<Ipv4> ()->GetNInterfaces ());
|
||||
|
||||
// create a point to point link between the new eNB and the SGW with
|
||||
// the corresponding new NetDevices on each side
|
||||
@@ -118,82 +134,104 @@ EpcHelper::AddEnb (Ptr<Node> enb, Ptr<NetDevice> lteEnbNetDevice)
|
||||
p2ph.SetDeviceAttribute ("DataRate", DataRateValue (m_s1uLinkDataRate));
|
||||
p2ph.SetChannelAttribute ("Delay", TimeValue (m_s1uLinkDelay));
|
||||
NetDeviceContainer enbSgwDevices = p2ph.Install (enb, m_sgwPgw);
|
||||
NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB after installing p2p dev: " << enb->GetObject<Ipv4> ()->GetNInterfaces ());
|
||||
Ptr<NetDevice> enbDev = enbSgwDevices.Get (0);
|
||||
Ptr<NetDevice> sgwDev = enbSgwDevices.Get (1);
|
||||
m_s1uIpv4AddressHelper.NewNetwork ();
|
||||
Ipv4InterfaceContainer enbSgwIpIfaces m_s1uIpv4AddressHelper.Assign (enbSgwDevices);
|
||||
Ipv4InterfaceContainer enbSgwIpIfaces = m_s1uIpv4AddressHelper.Assign (enbSgwDevices);
|
||||
NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB after assigning Ipv4 addr to S1 dev: " << enb->GetObject<Ipv4> ()->GetNInterfaces ());
|
||||
|
||||
Ipv4Address enbAddress = enbSgwIpIfaces.GetAddress (0);
|
||||
Ipv4Address sgwAddress = enbSgwIpIfaces.GetAddress (1);
|
||||
|
||||
// create S1-U socket for the ENB
|
||||
Ptr<Socket> enbS1uSocket = Socket::CreateSocket (enb, TypeId::LookupByName ("ns3::UdpSocketFactory"));
|
||||
enbS1uSocket->Bind (InetSocketAddress (enbAddress, m_gtpuUdpPort));
|
||||
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
|
||||
PacketSocketAddress enbLteSocketAddr;
|
||||
enbLteSocketAddr.SetSingleDevice (lteEnbNetDevice->GetIfIndex ());
|
||||
// do we need the following?
|
||||
//enbLteSocketAddr.SetPhysicalAddress (devices.Get (1)->GetAddress ());
|
||||
//enbLteSocketAddr.SetProtocol (1);
|
||||
|
||||
Ptr<Socket> enbLteSocket = Socket::CreateSocket (enb, TypeId::LookupByName ("ns3::PacketSocketFactory"));
|
||||
enbLteSocket->Bind (enbLteSocketAddr);
|
||||
|
||||
// create EpcEnbApplication
|
||||
Ptr<EpcEnbApplication> = CreateObject<EpcEnbApplication> (enbLteSocket, enbS1uSocket, sgwAddress);
|
||||
PacketSocketAddress enbLteSocketBindAddress;
|
||||
enbLteSocketBindAddress.SetSingleDevice (lteEnbNetDevice->GetIfIndex ());
|
||||
retval = enbLteSocket->Bind (enbLteSocketBindAddress);
|
||||
NS_ASSERT (retval == 0);
|
||||
PacketSocketAddress enbLteSocketConnectAddress;
|
||||
enbLteSocketConnectAddress.SetPhysicalAddress (Mac48Address::GetBroadcast ());
|
||||
enbLteSocketConnectAddress.SetProtocol (Ipv4L3Protocol::PROT_NUMBER);
|
||||
retval = enbLteSocket->Connect (enbLteSocketConnectAddress);
|
||||
NS_ASSERT (retval == 0);
|
||||
|
||||
|
||||
NS_LOG_INFO ("create EpcEnbApplication");
|
||||
Ptr<EpcEnbApplication> enbApp = CreateObject<EpcEnbApplication> (enbLteSocket, enbS1uSocket, sgwAddress);
|
||||
enb->AddApplication (enbApp);
|
||||
NS_ASSERT (enb->GetNApplications () == 1);
|
||||
NS_ASSERT_MSG (enb->GetApplication (0)->GetObject<EpcEnbApplication> () != 0, "cannot retrieve EpcEnbApplication");
|
||||
NS_LOG_LOGIC ("enb: " << enb << ", enb->GetApplication (0): " << enb->GetApplication (0));
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EpcHelper::ActivateEpsBearer ()
|
||||
EpcHelper::ActivateEpsBearer (Ptr<NetDevice> ueLteDevice, Ptr<NetDevice> enbLteDevice, Ptr<LteTft> tft, uint16_t rnti, uint8_t lcid)
|
||||
{
|
||||
// add tunnel at EpcSgwPgwApplication
|
||||
// add tunnel at EpcEnbApplication
|
||||
Ptr<Node> ueNode = ueLteDevice->GetNode ();
|
||||
Ptr<Ipv4> ueIpv4 = ueNode->GetObject<Ipv4> ();
|
||||
int32_t interface = ueIpv4->GetInterfaceForDevice (ueLteDevice);
|
||||
NS_ASSERT (interface >= 0);
|
||||
NS_ASSERT (ueIpv4->GetNAddresses (interface) == 1);
|
||||
Ipv4Address ueAddr = ueIpv4->GetAddress (interface, 0).GetLocal ();
|
||||
NS_LOG_LOGIC (" UE IP address: " << ueAddr);
|
||||
|
||||
// NOTE: unlike ueLteDevice, enbLteDevice is NOT an Ipv4 enabled
|
||||
// device. In fact we are interested in the S1 device of the eNB.
|
||||
// We find it by relying on the assumption that the S1 device is the
|
||||
// only Ipv4 enabled device of the eNB besides the localhost interface.
|
||||
Ptr<Node> enbNode = enbLteDevice->GetNode ();
|
||||
NS_ASSERT (enbNode != 0);
|
||||
Ptr<Ipv4> enbIpv4 = enbNode->GetObject<Ipv4> ();
|
||||
NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB: " << enbIpv4->GetNInterfaces ());
|
||||
// two ifaces total: loopback + the S1-U interface
|
||||
NS_ASSERT (enbIpv4->GetNInterfaces () == 2);
|
||||
NS_ASSERT (ueIpv4->GetNAddresses (1) == 1);
|
||||
// iface index 0 is loopback, index 1 is the S1-U interface
|
||||
Ipv4Address enbAddr = enbIpv4->GetAddress (1, 0).GetLocal ();
|
||||
NS_LOG_LOGIC (" ENB IP address: " << enbAddr);
|
||||
|
||||
// setup S1 bearer at EpcSgwPgwApplication
|
||||
uint32_t teid = m_sgwPgwApp->ActivateS1Bearer (ueAddr, enbAddr, tft);
|
||||
|
||||
// setup S1 bearer at EpcEnbApplication
|
||||
NS_LOG_LOGIC ("enb: " << enbNode << ", enb->GetApplication (0): " << enbNode->GetApplication (0));
|
||||
NS_ASSERT (enbNode->GetNApplications () == 1);
|
||||
Ptr<Application> app = enbNode->GetApplication (0);
|
||||
NS_ASSERT (app != 0);
|
||||
Ptr<EpcEnbApplication> epcEnbApp = app->GetObject<EpcEnbApplication> ();
|
||||
NS_ASSERT (epcEnbApp != 0);
|
||||
epcEnbApp->ErabSetupRequest (teid, rnti, lcid);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
Ptr<Node>
|
||||
EpcHelper::GetSgwPgwNode ()
|
||||
EpcHelper::GetPgwNode ()
|
||||
{
|
||||
return m_sgwPgw;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EpcHelper::InstallGtpu (Ptr<Node> n)
|
||||
Ipv4InterfaceContainer
|
||||
EpcHelper::AssignUeIpv4Address (NetDeviceContainer ueDevices)
|
||||
{
|
||||
InstallGtpu (n, m_ipv4.NewAddress ());
|
||||
return m_ueAddressHelper.Assign (ueDevices);
|
||||
}
|
||||
|
||||
void
|
||||
EpcHelper::InstallGtpu (Ptr<Node> n, Ipv4Address addr)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
// UDP socket creation and configuration
|
||||
Ptr<Socket> m_socket = Socket::CreateSocket (n, TypeId::LookupByName ("ns3::UdpSocketFactory"));
|
||||
m_socket->Bind (InetSocketAddress (Ipv4Address::GetAny (), m_udpPort));
|
||||
|
||||
// tap device creation and configuration
|
||||
Ptr<VirtualNetDevice> m_tap = CreateObject<VirtualNetDevice> ();
|
||||
m_tap->SetAddress (Mac48Address::Allocate ());
|
||||
|
||||
n->AddDevice (m_tap);
|
||||
Ptr<Ipv4> ipv4 = n->GetObject<Ipv4> ();
|
||||
uint32_t i = ipv4->AddInterface (m_tap);
|
||||
ipv4->AddAddress (i, Ipv4InterfaceAddress (addr, m_mask));
|
||||
ipv4->SetUp (i);
|
||||
Ptr<GtpuTunnelEndpoint> tunnel = CreateObject<GtpuTunnelEndpoint> (m_tap, m_socket);
|
||||
m_gtpuEndpoint[n] = tunnel;
|
||||
}
|
||||
|
||||
void
|
||||
EpcHelper::CreateGtpuTunnel (Ptr<Node> n, Ipv4Address nAddr, Ptr<Node> m, Ipv4Address mAddr)
|
||||
{
|
||||
uint32_t teid = m_gtpuEndpoint[n]->CreateGtpuTunnel (mAddr);
|
||||
m_gtpuEndpoint[m]->CreateGtpuTunnel (nAddr, teid);
|
||||
}
|
||||
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -16,20 +16,23 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Jaume Nin <jnin@cttc.es>
|
||||
* Nicola Baldo <nbaldo@cttc.es>
|
||||
*/
|
||||
|
||||
#ifndef EPC_HELPER_H
|
||||
#define EPC_HELPER_H
|
||||
|
||||
#include <ns3/object.h>
|
||||
|
||||
|
||||
#include <ns3/ipv4-address-helper.h>
|
||||
#include <ns3/data-rate.h>
|
||||
#include <ns3/lte-tft.h>
|
||||
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class Node;
|
||||
class NetDevice;
|
||||
class EpcSgwPgwApplication;
|
||||
|
||||
/**
|
||||
* \brief Helper class to handle the creation of the EPC entities and protocols.
|
||||
@@ -54,7 +57,7 @@ public:
|
||||
virtual ~EpcHelper ();
|
||||
|
||||
// inherited from Object
|
||||
TypeId GetTypeId (void);
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
|
||||
/**
|
||||
@@ -70,8 +73,15 @@ public:
|
||||
/**
|
||||
* Activate an EPS bearer, setting up the corresponding S1-U tunnel.
|
||||
*
|
||||
*
|
||||
*
|
||||
* \param ueLteDevice the Ipv4-enabled device of the UE, normally connected via the LTE radio interface
|
||||
* \param enbLteDevice the non-Ipv4-enabled device of the eNB
|
||||
* \param tft the Traffic Flow Template of the new bearer
|
||||
* \param rnti the Radio Network Temporary Identifier that identifies the UE
|
||||
* \param lcid the Logical Channel IDentifier of the corresponding RadioBearer
|
||||
*/
|
||||
void ActivateEpsBearer ();
|
||||
void ActivateEpsBearer (Ptr<NetDevice> ueLteDevice, Ptr<NetDevice> enbLteDevice, Ptr<LteTft> tft, uint16_t rnti, uint8_t lcid);
|
||||
|
||||
|
||||
/**
|
||||
@@ -84,14 +94,34 @@ public:
|
||||
*/
|
||||
Ptr<Node> GetPgwNode ();
|
||||
|
||||
/**
|
||||
* Assign IPv4 addresses to UE devices
|
||||
*
|
||||
* \param ueDevices the set of UE devices
|
||||
*
|
||||
* \return the interface container, \see Ipv4AddressHelper::Assign() which has similar semantics
|
||||
*/
|
||||
Ipv4InterfaceContainer AssignUeIpv4Address (NetDeviceContainer ueDevices);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* helper to assign addresses to S1-U
|
||||
* NetDevices
|
||||
*/
|
||||
Ipv4AddressHelper m_s1uIpv4AddressHelper;
|
||||
|
||||
Ipv4AddressHelper m_s1uIpv4AddressHelper; /**< helper to assign
|
||||
addresses to S1-U
|
||||
NetDevices */
|
||||
/**
|
||||
* helper to assign addresses to UE devices as well as to the TUN device of the SGW/PGW
|
||||
*/
|
||||
Ipv4AddressHelper m_ueAddressHelper;
|
||||
|
||||
Ptr<Node> m_sgwPgw; /**< the SGW/PGW node */
|
||||
|
||||
Ptr<Node> m_sgwPgw;
|
||||
|
||||
Ptr<EpcSgwPgwApplication> m_sgwPgwApp;
|
||||
|
||||
DataRate m_s1uLinkDataRate;
|
||||
Time m_s1uLinkDelay;
|
||||
|
||||
@@ -318,28 +318,33 @@ LenaHelper::Attach (Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice)
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
LenaHelper::ActivateEpsBearer (NetDeviceContainer ueDevices, EpsBearer bearer)
|
||||
LenaHelper::ActivateEpsBearer (NetDeviceContainer ueDevices, EpsBearer bearer, Ptr<LteTft> tft)
|
||||
{
|
||||
for (NetDeviceContainer::Iterator i = ueDevices.Begin (); i != ueDevices.End (); ++i)
|
||||
{
|
||||
ActivateEpsBearer (*i, bearer);
|
||||
ActivateEpsBearer (*i, bearer, tft);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LenaHelper::ActivateEpsBearer (Ptr<NetDevice> ueDevice, EpsBearer bearer)
|
||||
LenaHelper::ActivateEpsBearer (Ptr<NetDevice> ueDevice, EpsBearer bearer, Ptr<LteTft> tft)
|
||||
{
|
||||
// setup RadioBearer first
|
||||
Ptr<LteEnbNetDevice> enbDevice = ueDevice->GetObject<LteUeNetDevice> ()->GetTargetEnb ();
|
||||
Ptr<LteEnbRrc> enbRrc = enbDevice->GetObject<LteEnbNetDevice> ()->GetRrc ();
|
||||
Ptr<LteUeRrc> ueRrc = ueDevice->GetObject<LteUeNetDevice> ()->GetRrc ();
|
||||
uint16_t rnti = ueRrc->GetRnti ();
|
||||
uint8_t lcid = enbRrc->SetupRadioBearer (rnti, bearer);
|
||||
ueRrc->SetupRadioBearer (rnti, bearer, lcid);
|
||||
|
||||
// then setup S1 Bearer
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
LenaHelper::EnableLogComponents (void)
|
||||
{
|
||||
@@ -380,7 +385,6 @@ LenaHelper::EnableRlcTraces (void)
|
||||
{
|
||||
EnableDlRlcTraces ();
|
||||
EnableUlRlcTraces ();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <ns3/eps-bearer.h>
|
||||
#include <ns3/mac-stats-calculator.h>
|
||||
#include <ns3/rlc-stats-calculator.h>
|
||||
#include <ns3/lte-tft.h>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
@@ -106,20 +107,22 @@ public:
|
||||
void Attach (Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice);
|
||||
|
||||
/**
|
||||
* Activate an EPS bearer on a given set of UE devices
|
||||
* Activate a dedicated EPS bearer on a given set of UE devices
|
||||
*
|
||||
* \param ueDevices the set of UE devices
|
||||
* \param bearer the characteristics of the bearer to be activated
|
||||
* \param tft the Traffic Flow Template that identifies the traffic to go on this bearer
|
||||
*/
|
||||
void ActivateEpsBearer (NetDeviceContainer ueDevices, EpsBearer bearer);
|
||||
void ActivateEpsBearer (NetDeviceContainer ueDevices, EpsBearer bearer, Ptr<LteTft> tft);
|
||||
|
||||
/**
|
||||
* Activate an EPS bearer on a given UE device
|
||||
* Activate a dedicated EPS bearer on a given UE device
|
||||
*
|
||||
* \param ueDevices the set of UE devices
|
||||
* \param bearer the characteristics of the bearer to be activated
|
||||
* \param tft the Traffic Flow Template that identifies the traffic to go on this bearer
|
||||
*/
|
||||
void ActivateEpsBearer (Ptr<NetDevice> ueDevice, EpsBearer bearer);
|
||||
void ActivateEpsBearer (Ptr<NetDevice> ueDevice, EpsBearer bearer, Ptr<LteTft> tft);
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -25,38 +25,48 @@
|
||||
#include "ns3/mac48-address.h"
|
||||
#include "ns3/ipv4.h"
|
||||
#include "ns3/inet-socket-address.h"
|
||||
#include "ns3/uinteger.h"
|
||||
#include "ns3/epc-gtpu-header.h"
|
||||
#include "ns3/lte-mac-tag.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("EpcEnbApplication");
|
||||
|
||||
uint16_t EpcEnbApplication::m_teidCounter = 0;
|
||||
uint32_t EpcEnbApplication::m_indexCounter = 0;
|
||||
|
||||
|
||||
TypeId
|
||||
EpcEnbApplication::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::EpcEnbApplication")
|
||||
.SetParent<Object> ()
|
||||
.AddAttribute("GtpuPort",
|
||||
"UDP Port to be used for GTP-U",
|
||||
UintegerValue (2152),
|
||||
MakeUintegerAccessor (&EpcEnbApplication::m_updPort),
|
||||
MakeUintegerChecker<uint16_t> ());
|
||||
.SetParent<Object> ();
|
||||
return tid;
|
||||
}
|
||||
|
||||
EpcEnbApplication::EpcEnbApplication (Address sgwAddress)
|
||||
EpcEnbApplication::EpcEnbApplication (Ptr<Socket> lteSocket, Ptr<Socket> s1uSocket, Ipv4Address sgwAddress)
|
||||
: m_lteSocket (lteSocket),
|
||||
m_s1uSocket (s1uSocket),
|
||||
m_sgwAddress (sgwAddress)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_s1uSocket->SetRecvCallback (MakeCallback (&EpcEnbApplication::RecvFromS1uSocket, this));
|
||||
m_lteSocket->SetRecvCallback (MakeCallback (&EpcEnbApplication::RecvFromLteSocket, this));
|
||||
}
|
||||
|
||||
|
||||
EpcEnbApplication::~EpcEnbApplication (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
void
|
||||
EpcEnbApplication::ErabSetupRequest (uint32_t teid, uint16_t rnti, uint8_t lcid)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << teid << rnti << (uint16_t) lcid);
|
||||
LteFlowId_t rbid (rnti, lcid);
|
||||
// side effect: create entries if not exist
|
||||
m_rbidTeidMap[rbid] = teid;
|
||||
m_teidRbidMap[teid] = rbid;
|
||||
}
|
||||
|
||||
void
|
||||
EpcEnbApplication::RecvFromLteSocket (Ptr<Socket> socket)
|
||||
@@ -64,99 +74,61 @@ EpcEnbApplication::RecvFromLteSocket (Ptr<Socket> socket)
|
||||
NS_LOG_FUNCTION (this);
|
||||
NS_ASSERT (socket == m_lteSocket);
|
||||
Ptr<Packet> packet = socket->Recv ();
|
||||
GtpuHeader gtpu;
|
||||
// TODO: should determine the TEID based on the Radio Bearer ID
|
||||
// which should be conveyed by means of a Packet Tag
|
||||
uint32_t teid = 0;
|
||||
LteMacTag tag;
|
||||
bool found = packet->RemovePacketTag (tag);
|
||||
NS_ASSERT (found);
|
||||
LteFlowId_t flowId;
|
||||
flowId.m_rnti = tag.GetRnti ();
|
||||
flowId.m_lcId = tag.GetLcid ();
|
||||
std::map<LteFlowId_t, uint32_t>::iterator it = m_rbidTeidMap.find (flowId);
|
||||
NS_ASSERT (it != m_rbidTeidMap.end ());
|
||||
uint32_t teid = it->second;
|
||||
SendToS1uSocket (packet, teid);
|
||||
}
|
||||
|
||||
void
|
||||
EpcEnbApplication::RecvFromS1uSocket (Ptr<Socket> socket)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
NS_LOG_FUNCTION (this << socket);
|
||||
NS_ASSERT (socket == m_s1uSocket);
|
||||
Ptr<Packet> packet = socket->Recv ();
|
||||
GtpuHeader gtpu;
|
||||
packet->RemoveHeader (gtpu);
|
||||
uint32_t teid = gtpu.GetTeid ();
|
||||
uint32_t rbid = GetRbid (teid);
|
||||
SendToLteSocket (packet, rbid);
|
||||
std::map<uint32_t, LteFlowId_t>::iterator it = m_teidRbidMap.find (teid);
|
||||
NS_ASSERT (it != m_teidRbidMap.end ());
|
||||
|
||||
// workaround for bug 231 https://www.nsnam.org/bugzilla/show_bug.cgi?id=231
|
||||
SocketAddressTag tag;
|
||||
packet->RemovePacketTag (tag);
|
||||
|
||||
SendToLteSocket (packet, it->second.m_rnti, it->second.m_lcId);
|
||||
}
|
||||
|
||||
void
|
||||
EpcEnbApplication::SendToLteSocket (Ptr<Packet> packet, uint16_t rnti, uint8_t lcid)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << packet << rnti << (uint16_t) lcid);
|
||||
LteMacTag tag (rnti, lcid);
|
||||
packet->AddPacketTag (tag);
|
||||
int sentBytes = m_lteSocket->Send (packet);
|
||||
NS_ASSERT (sentBytes > 0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EpcEnbApplication::SendToS1uSocket (Ptr<Packet> packet, uint32_t teid)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << packet << teid);
|
||||
GtpuHeader gtpu;
|
||||
gtpu.SetTeid (teid);
|
||||
// From 3GPP TS 29.281 v10.0.0 Section 5.1
|
||||
// Length of the payload + the non obligatory GTP-U header
|
||||
gtpu.SetLength (p->GetSize () + h.GetSerializedSize () - 8);
|
||||
gtpu.SetLength (packet->GetSize () + gtpu.GetSerializedSize () - 8);
|
||||
packet->AddHeader (gtpu);
|
||||
uint32_t flags = 0;
|
||||
m_s1uSocket->SendTo (packet, flags, m_sgwAddress);
|
||||
}
|
||||
|
||||
|
||||
uint32_t
|
||||
EpcEnbApplication::CreateGtpuTunnel (Ipv4Address destination)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
if (m_teidCounter == 0xffffffff)
|
||||
{
|
||||
NS_FATAL_ERROR ("TEID space exhausted, please implement some TEID reuse mechanism");
|
||||
}
|
||||
CreateGtpuTunnel (destination, ++m_teidCounter);
|
||||
return m_teidCounter;
|
||||
}
|
||||
|
||||
void
|
||||
EpcEnbApplication::CreateGtpuTunnel (Ipv4Address destination, uint32_t teid)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_gtpuMap[m_indexCounter] = CreateObject<GtpuL5Protocol> (teid);
|
||||
m_dstAddrMap[m_indexCounter] = destination;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
EpcEnbApplication::GetRbid (uint32_t teid)
|
||||
{
|
||||
// since we don't have SRBs for now, we can just use the same identifiers
|
||||
return teid;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
EpcEnbApplication::GetTeid (uint32_t rbid)
|
||||
{
|
||||
// since we don't have SRBs for now, we can just use the same identifiers
|
||||
return rbid;
|
||||
}
|
||||
|
||||
void
|
||||
EpcEnbApplication::GtpuRecv (Ptr<Socket> socket)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
Ptr<Packet> packet = socket->Recv ();
|
||||
uint32_t index = 0;
|
||||
m_gtpuMap[index]->RemoveHeader (packet);
|
||||
m_tap->Receive (packet, 0x0800, m_tap->GetAddress (), m_tap->GetAddress (), NetDevice::PACKET_HOST);
|
||||
}
|
||||
|
||||
bool
|
||||
EpcEnbApplication::GtpuSend (Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << source << dest << packet << packet->GetSize ());
|
||||
// TODO: Instead of use always index 0 make use of the TFT classifier class, probably
|
||||
// a mapping between the tunnel index (assigned during the tunnel creation) and the classifier
|
||||
// index (assigned when the first packet is send through) should be maintained.
|
||||
uint32_t index = 0;
|
||||
packet = m_gtpuMap[index]->AddHeader (packet);
|
||||
m_socket->SendTo (packet, 0, InetSocketAddress (m_dstAddrMap[index], m_udpPort));
|
||||
return true;
|
||||
}
|
||||
|
||||
EpcEnbApplication::~EpcEnbApplication ()
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
}
|
||||
|
||||
}; // namespace ns3
|
||||
|
||||
@@ -22,14 +22,16 @@
|
||||
#ifndef EPC_ENB_APPLICATION_H
|
||||
#define EPC_ENB_APPLICATION_H
|
||||
|
||||
#include "ns3/address.h"
|
||||
#include "ns3/socket.h"
|
||||
#include "ns3/virtual-net-device.h"
|
||||
#include "ns3/epc-gtpu-l5-protocol.h"
|
||||
#include "ns3/traced-callback.h"
|
||||
#include "ns3/callback.h"
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/object.h"
|
||||
#include <ns3/address.h>
|
||||
#include <ns3/socket.h>
|
||||
#include <ns3/virtual-net-device.h>
|
||||
#include <ns3/epc-gtpu-l5-protocol.h>
|
||||
#include <ns3/traced-callback.h>
|
||||
#include <ns3/callback.h>
|
||||
#include <ns3/ptr.h>
|
||||
#include <ns3/object.h>
|
||||
#include <ns3/lte-common.h>
|
||||
#include <ns3/application.h>
|
||||
#include <map>
|
||||
|
||||
namespace ns3 {
|
||||
@@ -37,35 +39,45 @@ namespace ns3 {
|
||||
/**
|
||||
* \ingroup lte
|
||||
*
|
||||
* GTPv1-U endpoint for all the tunnels of a given node. It encapsulates all the tunnel logic for creating tunnels and encapsulating data through it
|
||||
* This application is installed inside eNBs and provides the bridge functionality for user data plane packets between the radio interface and the S1-U interface.
|
||||
*/
|
||||
class EpcEnbApplication : public Object
|
||||
class EpcEnbApplication : public Application
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
// inherited from Object
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
*
|
||||
* \param radioSocket the socket to be used to send/receive packets to/from the LTE radio interface
|
||||
* \param lteSocket the socket to be used to send/receive packets to/from the LTE radio interface
|
||||
* \param s1uSocket the socket to be used to send/receive packets
|
||||
* to/from the S1-U interface connected with the SGW
|
||||
* \param sgwAddress the IPv4 address at which this eNB will be able to reach its SGW
|
||||
*
|
||||
*/
|
||||
EpcEnbApplication (Ptr<Socket> radioSocket, Ptr<Socket> s1uSocket, Address sgwAddress);
|
||||
EpcEnbApplication (Ptr<Socket> lteSocket, Ptr<Socket> s1uSocket, Ipv4Address sgwAddress);
|
||||
|
||||
/**
|
||||
* destructor
|
||||
* Destructor
|
||||
*
|
||||
*/
|
||||
virtual ~EpcEnbApplication (void);
|
||||
|
||||
|
||||
|
||||
void SetupS1Bearer ()
|
||||
/**
|
||||
* This method is triggered after the eNB received
|
||||
* a S1-AP message of type E-RAB Setup Request by the MME and the RadioBearer has already been created
|
||||
*
|
||||
* \param teid the Tunnel Endpoint IDentifier of the S1-bearer to be setup.
|
||||
* \param rnti the unique ID of the UE on this eNB
|
||||
* \param lcid the Logical Channel ID identifying the Radio Bearer
|
||||
*/
|
||||
void ErabSetupRequest (uint32_t teid, uint16_t rnti, uint8_t lcid);
|
||||
|
||||
/**
|
||||
* Method to be assigned to the recv callback of the LTE socket. It is called when the eNB receives a data packet from the radio interface that is to be forwarded to the SGW.
|
||||
@@ -88,7 +100,7 @@ public:
|
||||
* \param packet t
|
||||
* \param rbid the Radio Bearer IDentifier
|
||||
*/
|
||||
void SendToLteSocket (Ptr<Packet> packet, uint32_t rbid);
|
||||
void SendToLteSocket (Ptr<Packet> packet, uint16_t rnti, uint8_t lcid);
|
||||
|
||||
|
||||
/**
|
||||
@@ -103,42 +115,6 @@ public:
|
||||
private:
|
||||
|
||||
|
||||
/**
|
||||
* Creates a GTPv1-U tunnel between the given destination and the enpoint
|
||||
* using the specified TEID.
|
||||
* \param destination IP address of the other end of the tunnel
|
||||
* \param teid Tunnel Endpoint IDentifier to be assigned to the tunnel
|
||||
*/
|
||||
void CreateGtpuTunnel (Ipv4Address destination, uint32_t teid);
|
||||
|
||||
/**
|
||||
* Creates a GTPv1-U tunnel between the given destination and the enpoint. The
|
||||
* TEID is automatically sellected.
|
||||
* \param destination IP address of the other end of the tunnel
|
||||
* \return the Tunnel Endpoint IDentifier (TEID) assigned to the tunnel
|
||||
*/
|
||||
uint32_t CreateGtpuTunnel (Ipv4Address destination);
|
||||
|
||||
|
||||
/**
|
||||
* this function implements the 1-to-1 mapping between S1 Bearers and Radio Bearers
|
||||
*
|
||||
* \param teid the Tunnel Endpoint IDentifier (TEID) that identifies an S1-bearer on this eNB
|
||||
*
|
||||
* \return the corresponding Radio Bearer Identifier
|
||||
*/
|
||||
uint32_t GetRbid (uint32_t teid);
|
||||
|
||||
|
||||
/**
|
||||
* this function implements the 1-to-1 mapping between Radio Bearers and S1 Bearers
|
||||
*
|
||||
* \param rbid the Radio Bearer Identifier
|
||||
*
|
||||
* \return the corresponding the Tunnel Endpoint IDentifier (TEID) that identifies an S1-bearer on this eNB
|
||||
*/
|
||||
uint32_t GetTeid (uint32_t rbid);
|
||||
|
||||
/**
|
||||
* raw packet socket to send and receive the packets to and from the LTE radio interface
|
||||
*/
|
||||
@@ -147,25 +123,25 @@ private:
|
||||
/**
|
||||
* UDP socket to send and receive GTP-U the packets to and from the S1-U interface
|
||||
*/
|
||||
Ptr<Socket> m_epcSocket;
|
||||
Ptr<Socket> m_s1uSocket;
|
||||
|
||||
/**
|
||||
* UDP port where the GTP-U Socket is bound, fixed by the standard as 2152
|
||||
*/
|
||||
uint16_t m_udpPort;
|
||||
|
||||
/**
|
||||
* Map holding the GTP instances of the active tunnels on this endpoint
|
||||
*/
|
||||
std::map<uint32_t, Ptr<GtpuL5Protocol> > m_gtpuMap;
|
||||
|
||||
/**
|
||||
* address of the SGW which terminates all tunnels
|
||||
* address of the SGW which terminates all S1-U tunnels
|
||||
*/
|
||||
Ipv4Address m_sgwAddress;
|
||||
|
||||
static uint16_t m_teidCounter;
|
||||
static uint32_t m_indexCounter;
|
||||
/**
|
||||
* map telling for each RadioBearer (RNTI,LCID) the corresponding S1-U TEID
|
||||
*
|
||||
*/
|
||||
std::map<LteFlowId_t, uint32_t> m_rbidTeidMap;
|
||||
|
||||
/**
|
||||
* map telling for each S1-U TEID the corresponding RadioBearer (RNTI,LCID)
|
||||
*
|
||||
*/
|
||||
std::map<uint32_t, LteFlowId_t> m_teidRbidMap;
|
||||
|
||||
};
|
||||
|
||||
} //namespace ns3
|
||||
|
||||
@@ -25,76 +25,162 @@
|
||||
#include "ns3/mac48-address.h"
|
||||
#include "ns3/ipv4.h"
|
||||
#include "ns3/inet-socket-address.h"
|
||||
#include "ns3/epc-gtpu-header.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("EpcSgwPgwApplication");
|
||||
|
||||
uint16_t EpcSgwPgwAplication::m_teidCounter = 0;
|
||||
uint32_t EpcSgwPgwAplication::m_indexCounter = 0;
|
||||
|
||||
/////////////////////////
|
||||
// EnbInfo
|
||||
/////////////////////////
|
||||
|
||||
|
||||
EpcSgwPgwApplication::EnbInfo::EnbInfo ()
|
||||
: m_teidCounter (0)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
EpcSgwPgwApplication::EnbInfo::AddBearer (Ptr<LteTft> tft)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tft);
|
||||
return m_tftClassifier.Add (tft);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
EpcSgwPgwApplication::EnbInfo::Classify (Ptr<Packet> p)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << p);
|
||||
// we hardcode DOWNLINK direction since the PGW is espected to
|
||||
// classify only downlink packets (uplink packets will go to the
|
||||
// internet without any classification).
|
||||
return m_tftClassifier.Classify (p, LteTft::DOWNLINK);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////
|
||||
// EpcSgwPgwApplication
|
||||
/////////////////////////
|
||||
|
||||
|
||||
TypeId
|
||||
EpcSgwPgwAplication::GetTypeId (void)
|
||||
EpcSgwPgwApplication::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::EpcSgwPgwApplication")
|
||||
.SetParent<Object> ();
|
||||
return tid;
|
||||
}
|
||||
|
||||
EpcSgwPgwAplication::EpcSgwPgwAplication (const Ptr<VirtualNetDevice> tap, const Ptr<Socket> s)
|
||||
: m_udpPort (2152)
|
||||
|
||||
|
||||
EpcSgwPgwApplication::EpcSgwPgwApplication (const Ptr<VirtualNetDevice> giTunDevice, const Ptr<Socket> s1uSocket)
|
||||
: m_s1uSocket (s1uSocket),
|
||||
m_giTunDevice (giTunDevice),
|
||||
m_gtpuUdpPort (2152) // fixed by the standard
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_tap = tap;
|
||||
m_tap->SetSendCallback (MakeCallback (&EpcSgwPgwAplication::GtpuSend, this));
|
||||
m_socket = s;
|
||||
m_socket->SetRecvCallback (MakeCallback (&EpcSgwPgwAplication::GtpuRecv, this));
|
||||
NS_LOG_FUNCTION (this << giTunDevice << s1uSocket);
|
||||
m_s1uSocket->SetRecvCallback (MakeCallback (&EpcSgwPgwApplication::RecvFromS1uSocket, this));
|
||||
}
|
||||
|
||||
uint32_t
|
||||
EpcSgwPgwAplication::CreateGtpuTunnel (Ipv4Address destination)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
CreateGtpuTunnel (destination, ++m_teidCounter);
|
||||
return m_teidCounter;
|
||||
}
|
||||
|
||||
void
|
||||
EpcSgwPgwAplication::CreateGtpuTunnel (Ipv4Address destination, uint32_t teid)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_gtpuMap[m_indexCounter] = CreateObject<GtpuL5Protocol> (teid);
|
||||
m_dstAddrMap[m_indexCounter] = destination;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EpcSgwPgwAplication::GtpuRecv (Ptr<Socket> socket)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
Ptr<Packet> packet = socket->Recv (65535, 0);
|
||||
uint32_t index = 0;
|
||||
m_gtpuMap[index]->RemoveHeader (packet);
|
||||
m_tap->Receive (packet, 0x0800, m_tap->GetAddress (), m_tap->GetAddress (), NetDevice::PACKET_HOST);
|
||||
}
|
||||
|
||||
bool
|
||||
EpcSgwPgwAplication::GtpuSend (Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << source << dest << packet << packet->GetSize ());
|
||||
// TODO: Instead of use always index 0 make use of the TFT classifier class, probably
|
||||
// a mapping between the tunnel index (assigned during the tunnel creation) and the classifier
|
||||
// index (assigned when the first packet is send through) should be maintained.
|
||||
uint32_t index = 0;
|
||||
packet = m_gtpuMap[index]->AddHeader (packet);
|
||||
m_socket->SendTo (packet, 0, InetSocketAddress (m_dstAddrMap[index], m_udpPort));
|
||||
return true;
|
||||
}
|
||||
|
||||
EpcSgwPgwAplication::~EpcSgwPgwAplication ()
|
||||
|
||||
EpcSgwPgwApplication::~EpcSgwPgwApplication ()
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
}
|
||||
|
||||
|
||||
uint32_t
|
||||
EpcSgwPgwApplication::ActivateS1Bearer (Ipv4Address ueAddr, Ipv4Address enbAddr, Ptr<LteTft> tft)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << ueAddr << enbAddr << tft);
|
||||
// side effect: add entry if not exists
|
||||
m_ueAddrEnbAddrMap[ueAddr] = enbAddr;
|
||||
|
||||
// side effect: create new EnbInfo if it does not exist
|
||||
uint32_t teid = m_enbInfoMap[enbAddr].AddBearer (tft);
|
||||
return teid;
|
||||
}
|
||||
|
||||
bool
|
||||
EpcSgwPgwApplication::RecvFromGiTunDevice (Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << source << dest << packet << packet->GetSize ());
|
||||
|
||||
// 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 eNB address
|
||||
std::map<Ipv4Address, Ipv4Address>::iterator it1 = m_ueAddrEnbAddrMap.find (ueAddr);
|
||||
if (it1 == m_ueAddrEnbAddrMap.end ())
|
||||
{
|
||||
NS_LOG_WARN ("could not find corresponding eNB for UE address " << ueAddr) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
Ipv4Address enbAddr = it1->second;
|
||||
// lookup into TFT classifier for that eNB
|
||||
std::map<Ipv4Address, EnbInfo>::iterator it2 = m_enbInfoMap.find (enbAddr);
|
||||
NS_ASSERT (it2 != m_enbInfoMap.end ());
|
||||
uint32_t teid = it2->second.Classify (packet);
|
||||
if (teid == 0)
|
||||
{
|
||||
NS_LOG_WARN ("no matching TEID for this packet");
|
||||
}
|
||||
else
|
||||
{
|
||||
SendToS1uSocket (packet, enbAddr, teid);
|
||||
}
|
||||
}
|
||||
// there is no reason why we should notify the Gi TUN
|
||||
// VirtualNetDevice that he failed to send the packet
|
||||
const bool succeeded = true;
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
void
|
||||
EpcSgwPgwApplication::RecvFromS1uSocket (Ptr<Socket> socket)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << socket);
|
||||
NS_ASSERT (socket == m_s1uSocket);
|
||||
Ptr<Packet> packet = socket->Recv ();
|
||||
GtpuHeader gtpu;
|
||||
packet->RemoveHeader (gtpu);
|
||||
uint32_t teid = gtpu.GetTeid ();
|
||||
|
||||
// workaround for bug 231 https://www.nsnam.org/bugzilla/show_bug.cgi?id=231
|
||||
SocketAddressTag tag;
|
||||
packet->RemovePacketTag (tag);
|
||||
|
||||
SendToGiTunDevice (packet, teid);
|
||||
}
|
||||
|
||||
void
|
||||
EpcSgwPgwApplication::SendToGiTunDevice (Ptr<Packet> packet, uint32_t teid)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << packet << teid);
|
||||
m_giTunDevice->Receive (packet, 0x0800, m_giTunDevice->GetAddress (), m_giTunDevice->GetAddress (), NetDevice::PACKET_HOST);
|
||||
}
|
||||
|
||||
void
|
||||
EpcSgwPgwApplication::SendToS1uSocket (Ptr<Packet> packet, Ipv4Address enbAddr, uint32_t teid)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << packet << enbAddr << teid);
|
||||
|
||||
GtpuHeader gtpu;
|
||||
gtpu.SetTeid (teid);
|
||||
// From 3GPP TS 29.281 v10.0.0 Section 5.1
|
||||
// Length of the payload + the non obligatory GTP-U header
|
||||
gtpu.SetLength (packet->GetSize () + gtpu.GetSerializedSize () - 8);
|
||||
packet->AddHeader (gtpu);
|
||||
uint32_t flags = 0;
|
||||
m_s1uSocket->SendTo (packet, flags, InetSocketAddress(enbAddr, m_gtpuUdpPort));
|
||||
}
|
||||
|
||||
}; // namespace ns3
|
||||
|
||||
@@ -22,14 +22,19 @@
|
||||
#ifndef EPC_SGW_PGW_APPLICATION_H
|
||||
#define EPC_SGW_PGW_APPLICATION_H
|
||||
|
||||
#include "ns3/address.h"
|
||||
#include "ns3/socket.h"
|
||||
#include "ns3/virtual-net-device.h"
|
||||
#include "ns3/epc-gtpu-l5-protocol.h"
|
||||
#include "ns3/traced-callback.h"
|
||||
#include "ns3/callback.h"
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/object.h"
|
||||
#include <ns3/address.h>
|
||||
#include <ns3/socket.h>
|
||||
#include <ns3/virtual-net-device.h>
|
||||
#include <ns3/epc-gtpu-l5-protocol.h>
|
||||
#include <ns3/traced-callback.h>
|
||||
#include <ns3/callback.h>
|
||||
#include <ns3/ptr.h>
|
||||
#include <ns3/object.h>
|
||||
#include <ns3/eps-bearer.h>
|
||||
#include <ns3/lte-tft.h>
|
||||
#include <ns3/eps-tft-classifier.h>
|
||||
#include <ns3/lte-common.h>
|
||||
#include <ns3/application.h>
|
||||
#include <map>
|
||||
|
||||
namespace ns3 {
|
||||
@@ -37,73 +42,151 @@ namespace ns3 {
|
||||
/**
|
||||
* \ingroup lte
|
||||
*
|
||||
* GTPv1-U endpoint for all the tunnels of a given node. It encapsulates all the tunnel logic for creating tunnels and encapsulating data through it
|
||||
* This application implements the SGW/PGW functionality.
|
||||
*/
|
||||
class EpcSgwPgwAplication : public Object
|
||||
class EpcSgwPgwApplication : public Application
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
// inherited from Object
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
/**
|
||||
* Method assigned to the send callback of the upper end of the tunnel. It adds
|
||||
* the GTP header and sends it through the tunnel
|
||||
*/
|
||||
bool GtpuSend (Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
|
||||
/**
|
||||
* Method assigned to the receive callback of the upper end of the tunnel. It strips
|
||||
* the GTP header and sends it up to the application
|
||||
*/
|
||||
void GtpuRecv (Ptr<Socket> socket);
|
||||
|
||||
/**
|
||||
* Constructor that binds the tap device to the callback methods.
|
||||
* \param tap VirtualNetDevice used to tunnel the packets
|
||||
* \param s Socket used to send the tunneled packets
|
||||
*
|
||||
* \param giTunDevice TUN VirtualNetDevice used to tunnel IP packets from
|
||||
* the Gi interface of the PGW/SGW over the
|
||||
* internet over GTP-U/UDP/IP on the S1-U interface
|
||||
* \param s1uSocket socket used to send GTP-U packets to the eNBs
|
||||
*/
|
||||
EpcSgwPgwAplication (const Ptr<VirtualNetDevice> tap, const Ptr<Socket> s);
|
||||
virtual ~EpcSgwPgwAplication (void);
|
||||
EpcSgwPgwApplication (const Ptr<VirtualNetDevice> giTunDevice, const Ptr<Socket> s1uSocket);
|
||||
|
||||
/**
|
||||
* Creates a GTPv1-U tunnel between the given destination and the enpoint
|
||||
* using the specified TEID.
|
||||
* \param destination IP address of the other end of the tunnel
|
||||
* \param teid Tunnel Endpoint IDentifier to be assigned to the tunnel
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
void CreateGtpuTunnel (Ipv4Address destination, uint32_t teid);
|
||||
virtual ~EpcSgwPgwApplication (void);
|
||||
|
||||
/**
|
||||
* Creates a GTPv1-U tunnel between the given destination and the enpoint. The
|
||||
* TEID is automatically sellected.
|
||||
* \param destination IP address of the other end of the tunnel
|
||||
* \return teid Tunnel Endpoint IDentifier assigned to the tunnel
|
||||
|
||||
/**
|
||||
* Simulates the reception by the PGW of a GTP-C message of type
|
||||
* CreateSessionRequest or BearerResourceCommand coming from the
|
||||
* MME. This triggers the creation of a new EPS Bearer.
|
||||
*
|
||||
* \param bearer the specification of the EPS Bearer to be created
|
||||
* \param enbS1uAddress the IPv4 address at which the SGW can reach
|
||||
* the eNB via the S1-U interface
|
||||
* \param tft the Traffic Flow Template related to this bearer
|
||||
*
|
||||
* \return the TunnelEndpointIdentifier of this EPS bearer
|
||||
*/
|
||||
uint32_t CreateGtpuTunnel (Ipv4Address destination);
|
||||
uint32_t ActivateS1Bearer (Ipv4Address ueAddr, Ipv4Address enbAddr, Ptr<LteTft> tft);
|
||||
|
||||
|
||||
/**
|
||||
* Method to be assigned to the callback of the Gi TUN VirtualNetDevice. It
|
||||
* is called when the SGW/PGW receives a data packet from the
|
||||
* internet (including IP headers) that is to be sent to the UE via
|
||||
* its associated eNB, tunneling IP over GTP-U/UDP/IP.
|
||||
*
|
||||
* \param packet
|
||||
* \param source
|
||||
* \param dest
|
||||
* \param protocolNumber
|
||||
* \return true always
|
||||
*/
|
||||
bool RecvFromGiTunDevice (Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
|
||||
|
||||
|
||||
/**
|
||||
* Method to be assigned to the recv callback of the S1-U socket. It
|
||||
* is called when the SGW/PGW receives a data packet from the eNB
|
||||
* that is to be forwarded to the internet.
|
||||
*
|
||||
* \param socket pointer to the S1-U socket
|
||||
*/
|
||||
void RecvFromS1uSocket (Ptr<Socket> socket);
|
||||
|
||||
/**
|
||||
* Send a packet to the internet via the Gi interface of the SGW/PGW
|
||||
*
|
||||
* \param packet
|
||||
*/
|
||||
void SendToGiTunDevice (Ptr<Packet> packet, uint32_t teid);
|
||||
|
||||
|
||||
/**
|
||||
* Send a packet to the SGW via the S1-U interface
|
||||
*
|
||||
* \param packet packet to be sent
|
||||
* \param enbS1uAddress the address of the eNB
|
||||
* \param teid the Tunnel Enpoint IDentifier
|
||||
*/
|
||||
void SendToS1uSocket (Ptr<Packet> packet, Ipv4Address enbS1uAddress, uint32_t teid);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
/**
|
||||
* UDP socket to send and receive the packets to and from the tunnel
|
||||
*/
|
||||
Ptr<Socket> m_socket;
|
||||
/**
|
||||
* UDP port where the socket is bind, fixed by the standard as 2152
|
||||
*/
|
||||
uint16_t m_udpPort;
|
||||
/**
|
||||
* VirtualNetDevice to create the tunnel
|
||||
*/
|
||||
Ptr<VirtualNetDevice> m_tap;
|
||||
/**
|
||||
* Map holding the GTP instances of the active tunnels on this endpoint
|
||||
*/
|
||||
std::map<uint32_t, Ptr<GtpuL5Protocol> > m_gtpuMap;
|
||||
/**
|
||||
* Map holding the destination address of the active tunnels on this endpoint
|
||||
*/
|
||||
std::map<uint32_t, Ipv4Address> m_dstAddrMap;
|
||||
|
||||
static uint16_t m_teidCounter;
|
||||
static uint32_t m_indexCounter;
|
||||
|
||||
/**
|
||||
* store info for each eNB connected to this SGW
|
||||
*
|
||||
*/
|
||||
class EnbInfo
|
||||
{
|
||||
public:
|
||||
EnbInfo ();
|
||||
|
||||
/**
|
||||
*
|
||||
* \param tft the Traffic Flow Template of the new bearer to be added
|
||||
*
|
||||
* \return the TEID of the newly added bearer
|
||||
*/
|
||||
uint32_t AddBearer (Ptr<LteTft> tft);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* \param p the IP packet from the internet to be classified
|
||||
*
|
||||
* \return the corresponding TEID > 0 if matched, or 0 if no match
|
||||
*/
|
||||
uint32_t Classify (Ptr<Packet> p);
|
||||
|
||||
|
||||
private:
|
||||
uint32_t m_teidCounter;
|
||||
EpsTftClassifier m_tftClassifier;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* UDP socket to send and receive GTP-U packets to and from the S1-U interface
|
||||
*/
|
||||
Ptr<Socket> m_s1uSocket;
|
||||
|
||||
/**
|
||||
* TUN VirtualNetDevice used for tunneling/detunneling IP packets
|
||||
* from/to the internet over GTP-U/UDP/IP on the S1 interface
|
||||
*/
|
||||
Ptr<VirtualNetDevice> m_giTunDevice;
|
||||
|
||||
/**
|
||||
* Map telling for each UE address what is the corresponding eNB address
|
||||
*/
|
||||
std::map<Ipv4Address, Ipv4Address> m_ueAddrEnbAddrMap;
|
||||
|
||||
/**
|
||||
* Map telling for each eNB address the corresponding eNB info (TFT
|
||||
* classifier, etc.)
|
||||
*/
|
||||
std::map<Ipv4Address, EnbInfo> m_enbInfoMap;
|
||||
|
||||
uint16_t m_gtpuUdpPort;
|
||||
|
||||
};
|
||||
|
||||
} //namespace ns3
|
||||
|
||||
@@ -144,9 +144,12 @@ EpsTftClassifier::Classify (Ptr<Packet> p, LteTft::Direction direction)
|
||||
<< " tos=0x" << std::hex << tos);
|
||||
|
||||
// now it is possible to classify the packet!
|
||||
std::map <uint32_t, Ptr<LteTft> >::const_iterator it;
|
||||
// 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<LteTft> >::const_reverse_iterator it;
|
||||
NS_LOG_LOGIC ("TFT MAP size: " << m_tftMap.size ());
|
||||
for (it = m_tftMap.begin (); it != m_tftMap.end (); ++it)
|
||||
|
||||
for (it = m_tftMap.rbegin (); it != m_tftMap.rend (); ++it)
|
||||
{
|
||||
NS_LOG_LOGIC ("TFT id: " << it->first );
|
||||
NS_LOG_LOGIC (" Ptr<LteTft>: " << it->second);
|
||||
|
||||
@@ -135,6 +135,17 @@ LteTft::PacketFilter::Matches (Direction d,
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Ptr<LteTft>
|
||||
LteTft::Default ()
|
||||
{
|
||||
Ptr<LteTft> tft = Create<LteTft> ();
|
||||
LteTft::PacketFilter defaultPacketFilter;
|
||||
tft->Add (defaultPacketFilter);
|
||||
return tft;
|
||||
}
|
||||
|
||||
|
||||
LteTft::LteTft ()
|
||||
: m_numFilters (0)
|
||||
{
|
||||
|
||||
@@ -41,6 +41,14 @@ class LteTft : public SimpleRefCount<LteTft>
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* creates a TFT matching any traffic
|
||||
*
|
||||
* \return a newly created TFT that will match any traffic
|
||||
*/
|
||||
static Ptr<LteTft> Default ();
|
||||
|
||||
/**
|
||||
* Indicates the direction of the traffic that is to be classified.
|
||||
|
||||
226
src/lte/test/epc-test-s1u-downlink.cc
Normal file
226
src/lte/test/epc-test-s1u-downlink.cc
Normal file
@@ -0,0 +1,226 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Nicola Baldo <nbaldo@cttc.es>
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/test.h"
|
||||
#include "ns3/epc-helper.h"
|
||||
#include "ns3/packet-sink-helper.h"
|
||||
#include "ns3/udp-client-server-helper.h"
|
||||
#include "ns3/point-to-point-helper.h"
|
||||
#include "ns3/csma-helper.h"
|
||||
#include "ns3/internet-stack-helper.h"
|
||||
#include "ns3/ipv4-address-helper.h"
|
||||
#include "ns3/inet-socket-address.h"
|
||||
#include "ns3/uinteger.h"
|
||||
#include "ns3/packet-sink.h"
|
||||
#include <ns3/ipv4-static-routing-helper.h>
|
||||
#include <ns3/ipv4-static-routing.h>
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
|
||||
|
||||
struct UeTestData
|
||||
{
|
||||
UeTestData (uint32_t n, uint32_t s);
|
||||
|
||||
uint32_t numPkts;
|
||||
uint32_t pktSize;
|
||||
|
||||
Ptr<PacketSink> serverApp;
|
||||
Ptr<Application> clientApp;
|
||||
};
|
||||
|
||||
UeTestData::UeTestData (uint32_t n, uint32_t s)
|
||||
: numPkts (n),
|
||||
pktSize (s)
|
||||
{
|
||||
}
|
||||
|
||||
struct EnbTestData
|
||||
{
|
||||
std::vector<UeTestData> ues;
|
||||
};
|
||||
|
||||
|
||||
class EpcS1uTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
EpcS1uTestCase (std::string name, std::vector<EnbTestData> v);
|
||||
virtual ~EpcS1uTestCase ();
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
std::vector<EnbTestData> m_enbTestData;
|
||||
};
|
||||
|
||||
|
||||
EpcS1uTestCase::EpcS1uTestCase (std::string name, std::vector<EnbTestData> v)
|
||||
: TestCase (name),
|
||||
m_enbTestData (v)
|
||||
{
|
||||
}
|
||||
|
||||
EpcS1uTestCase::~EpcS1uTestCase ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
EpcS1uTestCase::DoRun ()
|
||||
{
|
||||
Ptr<EpcHelper> epcHelper = CreateObject<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;
|
||||
NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost);
|
||||
Ipv4AddressHelper ipv4h;
|
||||
ipv4h.SetBase ("1.0.0.0", "255.0.0.0");
|
||||
ipv4h.Assign (internetDevices);
|
||||
|
||||
// setup default gateway for the remote hosts
|
||||
Ipv4StaticRoutingHelper ipv4RoutingHelper;
|
||||
Ptr<Ipv4StaticRouting> remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject<Ipv4> ());
|
||||
|
||||
// hardcoded UE addresses for now
|
||||
remoteHostStaticRouting->AddNetworkRouteTo (Ipv4Address ("7.0.0.0"), Ipv4Mask ("255.255.255.0"), 1);
|
||||
|
||||
|
||||
|
||||
|
||||
NodeContainer enbs;
|
||||
|
||||
for (std::vector<EnbTestData>::iterator enbit = m_enbTestData.begin ();
|
||||
enbit < m_enbTestData.end ();
|
||||
++enbit)
|
||||
{
|
||||
Ptr<Node> enb = CreateObject<Node> ();
|
||||
enbs.Add (enb);
|
||||
|
||||
// we test EPC without LTE, hence we use:
|
||||
// 1) a CSMA network to simulate the cell
|
||||
// 2) a raw socket opened on the CSMA device to simulate the LTE socket
|
||||
|
||||
NodeContainer ues;
|
||||
ues.Create (enbit->ues.size ());
|
||||
|
||||
NodeContainer cell;
|
||||
cell.Add (ues);
|
||||
cell.Add (enb);
|
||||
|
||||
CsmaHelper csmaCell;
|
||||
NetDeviceContainer cellDevices = csmaCell.Install (cell);
|
||||
|
||||
// the eNB's CSMA NetDevice acting as an LTE NetDevice.
|
||||
Ptr<NetDevice> lteEnbNetDevice = cellDevices.Get (cellDevices.GetN () - 1);
|
||||
|
||||
// Note that the EpcEnbApplication won't care of the actual NetDevice type
|
||||
epcHelper->AddEnb (enb, lteEnbNetDevice);
|
||||
|
||||
// we install the IP stack on UEs only
|
||||
InternetStackHelper internet;
|
||||
internet.Install (ues);
|
||||
|
||||
// assign IP address to UEs, and install applications
|
||||
for (uint32_t u = 0; u < ues.GetN (); ++u)
|
||||
{
|
||||
Ptr<NetDevice> ueLteDevice = cellDevices.Get (u);
|
||||
Ipv4InterfaceContainer ueIpIface = epcHelper->AssignUeIpv4Address (NetDeviceContainer (ueLteDevice));
|
||||
|
||||
Ptr<Node> ue = ues.Get (u);
|
||||
|
||||
uint16_t port = 1234;
|
||||
PacketSinkHelper packetSinkHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), port));
|
||||
ApplicationContainer apps = packetSinkHelper.Install (ue);
|
||||
apps.Start (Seconds (1.0));
|
||||
apps.Stop (Seconds (10.0));
|
||||
enbit->ues[u].serverApp = apps.Get (0)->GetObject<PacketSink> ();
|
||||
|
||||
Time interPacketInterval = Seconds (0.01);
|
||||
UdpClientHelper client (ueIpIface.GetAddress (0), port);
|
||||
client.SetAttribute ("MaxPackets", UintegerValue (enbit->ues[u].numPkts));
|
||||
client.SetAttribute ("Interval", TimeValue (interPacketInterval));
|
||||
client.SetAttribute ("PacketSize", UintegerValue (enbit->ues[u].pktSize));
|
||||
apps = client.Install (remoteHost);
|
||||
apps.Start (Seconds (2.0));
|
||||
apps.Stop (Seconds (10.0));
|
||||
enbit->ues[u].clientApp = apps.Get (0);
|
||||
|
||||
uint16_t rnti = u+1;
|
||||
uint16_t lcid = 1;
|
||||
epcHelper->ActivateEpsBearer (ueLteDevice, lteEnbNetDevice, LteTft::Default (), rnti, lcid);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Simulator::Run ();
|
||||
|
||||
for (std::vector<EnbTestData>::iterator enbit = m_enbTestData.begin ();
|
||||
enbit < m_enbTestData.end ();
|
||||
++enbit)
|
||||
{
|
||||
for (std::vector<UeTestData>::iterator ueit = enbit->ues.begin ();
|
||||
ueit < enbit->ues.end ();
|
||||
++ueit)
|
||||
{
|
||||
NS_TEST_ASSERT_MSG_EQ (ueit->serverApp->GetTotalRx (), (ueit->numPkts) * (ueit->pktSize), "wrong total received bytes");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Test that the S1-U interface implementation works correctly
|
||||
*/
|
||||
class EpcS1uTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
EpcS1uTestSuite ();
|
||||
|
||||
} g_epcS1uTestSuiteInstance;
|
||||
|
||||
EpcS1uTestSuite::EpcS1uTestSuite ()
|
||||
: TestSuite ("epc-s1u-downlink", SYSTEM)
|
||||
{
|
||||
|
||||
std::vector<EnbTestData> v1;
|
||||
EnbTestData e1;
|
||||
UeTestData f1 (1, 100);
|
||||
e1.ues.push_back (f1);
|
||||
v1.push_back (e1);
|
||||
AddTestCase (new EpcS1uTestCase ("1 eNB, 1UE", v1));
|
||||
}
|
||||
|
||||
@@ -160,8 +160,8 @@ LteInterferenceTestCase::DoRun (void)
|
||||
// Activate an EPS bearer
|
||||
enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
|
||||
EpsBearer bearer (q);
|
||||
lena->ActivateEpsBearer (ueDevs1, bearer);
|
||||
lena->ActivateEpsBearer (ueDevs2, bearer);
|
||||
lena->ActivateEpsBearer (ueDevs1, bearer, LteTft::Default ());
|
||||
lena->ActivateEpsBearer (ueDevs2, bearer, LteTft::Default ());
|
||||
|
||||
|
||||
// Use testing chunk processor in the PHY layer
|
||||
|
||||
@@ -188,10 +188,10 @@ LteLinkAdaptationTestCase::DoRun (void)
|
||||
// Attach a UE to a eNB
|
||||
lena->Attach (ueDevs, enbDevs.Get (0));
|
||||
|
||||
// Activate an EPS bearer
|
||||
enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
|
||||
// Activate the default EPS bearer
|
||||
enum EpsBearer::Qci q = EpsBearer::NGBR_VIDEO_TCP_DEFAULT;
|
||||
EpsBearer bearer (q);
|
||||
lena->ActivateEpsBearer (ueDevs, bearer);
|
||||
lena->ActivateEpsBearer (ueDevs, bearer, LteTft::Default ());
|
||||
|
||||
// Use testing chunk processor in the PHY layer
|
||||
// It will be used to test that the SNR is as intended
|
||||
|
||||
@@ -262,7 +262,7 @@ LenaPfFfMacSchedulerTestCase1::DoRun (void)
|
||||
// Activate an EPS bearer
|
||||
enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
|
||||
EpsBearer bearer (q);
|
||||
lena->ActivateEpsBearer (ueDevs, bearer);
|
||||
lena->ActivateEpsBearer (ueDevs, bearer, LteTft::Default ());
|
||||
|
||||
lena->SetAttribute ("PropagationModel", StringValue ("ns3::FriisSpectrumPropagationLossModel"));
|
||||
|
||||
@@ -438,7 +438,7 @@ LenaPfFfMacSchedulerTestCase2::DoRun (void)
|
||||
// Activate an EPS bearer
|
||||
enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
|
||||
EpsBearer bearer (q);
|
||||
lena->ActivateEpsBearer (ueDevs, bearer);
|
||||
lena->ActivateEpsBearer (ueDevs, bearer, LteTft::Default ());
|
||||
|
||||
lena->SetAttribute ("PropagationModel", StringValue ("ns3::FriisSpectrumPropagationLossModel"));
|
||||
|
||||
|
||||
@@ -250,7 +250,7 @@ LenaRrFfMacSchedulerTestCase::DoRun (void)
|
||||
// Activate an EPS bearer
|
||||
enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
|
||||
EpsBearer bearer (q);
|
||||
lena->ActivateEpsBearer (ueDevs, bearer);
|
||||
lena->ActivateEpsBearer (ueDevs, bearer, LteTft::Default ());
|
||||
|
||||
lena->SetAttribute ("PropagationModel", StringValue ("ns3::FriisSpectrumPropagationLossModel"));
|
||||
|
||||
|
||||
@@ -133,6 +133,12 @@ EpsTftClassifierTestSuite::EpsTftClassifierTestSuite ()
|
||||
: TestSuite ("eps-tft-classifier", UNIT)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
|
||||
///////////////////////////
|
||||
// check some TFT matches
|
||||
///////////////////////////
|
||||
|
||||
|
||||
Ptr<EpsTftClassifier> c1 = Create<EpsTftClassifier> ();
|
||||
|
||||
@@ -171,8 +177,6 @@ EpsTftClassifierTestSuite::EpsTftClassifierTestSuite ()
|
||||
|
||||
c1->Add (tft1_2);
|
||||
|
||||
|
||||
|
||||
// ------------------------------------classifier---direction--------------src address---------------dst address---src port--dst port--ToS--TFT id
|
||||
|
||||
// test IP addresses
|
||||
@@ -199,6 +203,82 @@ EpsTftClassifierTestSuite::EpsTftClassifierTestSuite ()
|
||||
AddTestCase (new EpsTftClassifierTestCase (c1, LteTft::UPLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 3456, 6, 0, 2));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c1, LteTft::DOWNLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 3461, 3461, 0, 2));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c1, LteTft::DOWNLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 9, 3489, 0, 2));
|
||||
|
||||
|
||||
|
||||
///////////////////////////
|
||||
// check default TFT
|
||||
///////////////////////////
|
||||
|
||||
Ptr<EpsTftClassifier> c2 = Create<EpsTftClassifier> ();
|
||||
c2->Add (LteTft::Default ());
|
||||
|
||||
// ------------------------------------classifier---direction--------------src address---------------dst address---src port--dst port--ToS--TFT id
|
||||
|
||||
// test IP addresses
|
||||
AddTestCase (new EpsTftClassifierTestCase (c2, LteTft::UPLINK, Ipv4Address ("2.2.3.4"), Ipv4Address ("1.1.1.1"), 4, 1234, 0, 1));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c2, LteTft::UPLINK, Ipv4Address ("2.2.3.4"), Ipv4Address ("1.0.0.0"), 2, 123, 5, 1));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c2, LteTft::UPLINK, Ipv4Address ("6.2.3.4"), Ipv4Address ("1.1.1.1"), 4, 1234, 0, 1));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c2, LteTft::DOWNLINK, Ipv4Address ("3.3.3.4"), Ipv4Address ("4.4.4.1"), 4, 1234, 0, 1));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c2, LteTft::DOWNLINK, Ipv4Address ("3.3.4.4"), Ipv4Address ("4.4.4.1"), 4, 1234, 0, 1));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c2, LteTft::UPLINK, Ipv4Address ("3.3.3.4"), Ipv4Address ("4.4.2.1"), 4, 1234, 0, 1));
|
||||
|
||||
// test remote port
|
||||
AddTestCase (new EpsTftClassifierTestCase (c2, LteTft::UPLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 4, 1024, 0, 1));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c2, LteTft::UPLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 4, 1025, 0, 1));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c2, LteTft::UPLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 4, 1035, 0, 1));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c2, LteTft::UPLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 4, 1234, 0, 1));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c2, LteTft::DOWNLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 4, 1024, 0, 1));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c2, LteTft::DOWNLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 4, 1025, 0, 1));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c2, LteTft::DOWNLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 4, 1035, 0, 1));
|
||||
|
||||
// test local port
|
||||
AddTestCase (new EpsTftClassifierTestCase (c2, LteTft::UPLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 4, 3456, 0, 1));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c2, LteTft::UPLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 4, 3457, 0, 1));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c2, LteTft::UPLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 4, 3489, 0, 1));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c2, LteTft::UPLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 3456, 6, 0, 1));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c2, LteTft::DOWNLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 3461, 3461, 0, 1));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c2, LteTft::DOWNLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 9, 3489, 0, 1));
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////
|
||||
// check default TFT plus dedicated ones
|
||||
///////////////////////////////////////////
|
||||
|
||||
Ptr<EpsTftClassifier> c3 = Create<EpsTftClassifier> ();
|
||||
c3->Add (LteTft::Default ());
|
||||
c3->Add (tft1_1);
|
||||
c3->Add (tft1_2);
|
||||
|
||||
// ------------------------------------classifier---direction--------------src address---------------dst address---src port--dst port--ToS--TFT id
|
||||
|
||||
// test IP addresses
|
||||
AddTestCase (new EpsTftClassifierTestCase (c3, LteTft::UPLINK, Ipv4Address ("2.2.3.4"), Ipv4Address ("1.1.1.1"), 4, 1234, 0, 2));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c3, LteTft::UPLINK, Ipv4Address ("2.2.3.4"), Ipv4Address ("1.0.0.0"), 2, 123, 5, 2));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c3, LteTft::UPLINK, Ipv4Address ("6.2.3.4"), Ipv4Address ("1.1.1.1"), 4, 1234, 0, 1));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c3, LteTft::DOWNLINK, Ipv4Address ("3.3.3.4"), Ipv4Address ("4.4.4.1"), 4, 1234, 0, 2));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c3, LteTft::DOWNLINK, Ipv4Address ("3.3.4.4"), Ipv4Address ("4.4.4.1"), 4, 1234, 0, 1));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c3, LteTft::UPLINK, Ipv4Address ("3.3.3.4"), Ipv4Address ("4.4.2.1"), 4, 1234, 0, 1));
|
||||
|
||||
// test remote port
|
||||
AddTestCase (new EpsTftClassifierTestCase (c3, LteTft::UPLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 4, 1024, 0, 3));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c3, LteTft::UPLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 4, 1025, 0, 3));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c3, LteTft::UPLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 4, 1035, 0, 3));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c3, LteTft::UPLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 4, 1234, 0, 1));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c3, LteTft::DOWNLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 4, 1024, 0, 1));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c3, LteTft::DOWNLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 4, 1025, 0, 1));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c3, LteTft::DOWNLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 4, 1035, 0, 1));
|
||||
|
||||
// test local port
|
||||
AddTestCase (new EpsTftClassifierTestCase (c3, LteTft::UPLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 4, 3456, 0, 1));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c3, LteTft::UPLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 4, 3457, 0, 1));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c3, LteTft::UPLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 4, 3489, 0, 1));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c3, LteTft::UPLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 3456, 6, 0, 3));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c3, LteTft::DOWNLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 3461, 3461, 0, 3));
|
||||
AddTestCase (new EpsTftClassifierTestCase (c3, LteTft::DOWNLINK, Ipv4Address ("9.1.1.1"), Ipv4Address ("8.1.1.1"), 9, 3489, 0, 3));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
def build(bld):
|
||||
|
||||
module = bld.create_ns3_module('lte', ['core', 'network', 'spectrum', 'stats', 'virtual-net-device'])
|
||||
module = bld.create_ns3_module('lte', ['core', 'network', 'spectrum', 'stats', 'virtual-net-device','point-to-point','applications','internet','csma'])
|
||||
module.source = [
|
||||
'model/lte-common.cc',
|
||||
'model/lte-spectrum-phy.cc',
|
||||
@@ -80,6 +80,7 @@ def build(bld):
|
||||
'test/lte-test-rlc-um-transmitter.cc',
|
||||
'test/epc-test-gtpu.cc',
|
||||
'test/test-eps-tft-classifier.cc',
|
||||
'test/epc-test-s1u-downlink.cc',
|
||||
]
|
||||
|
||||
headers = bld.new_task_gen('ns3header')
|
||||
|
||||
@@ -356,7 +356,7 @@ PacketSocket::SendTo (Ptr<Packet> p, uint32_t flags, const Address &address)
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
return p->GetSize ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user