S1-U working in downlink

This commit is contained in:
Nicola Baldo
2011-10-19 19:01:50 +02:00
parent 814ad43df3
commit 7201c0cd2f
23 changed files with 884 additions and 363 deletions

View File

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

View File

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

View File

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

View File

@@ -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 ());
}

View File

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

View File

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

View File

@@ -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 ();
}

View File

@@ -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);
/**
*

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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));
}

View File

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

View File

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

View File

@@ -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"));

View File

@@ -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"));

View File

@@ -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));
}

View File

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

View File

@@ -356,7 +356,7 @@ PacketSocket::SendTo (Ptr<Packet> p, uint32_t flags, const Address &address)
}
else
{
return 0;
return p->GetSize ();
}
}