S1-U now working also in uplink

This commit is contained in:
Nicola Baldo
2011-10-21 17:31:08 +02:00
parent 460af60a0f
commit 05cc12b496
9 changed files with 601 additions and 71 deletions

View File

@@ -64,26 +64,26 @@ EpcHelper::EpcHelper ()
NS_ASSERT (retval == 0);
// create TUN device implementing tunneling of user data over GTP-U/UDP/IP
Ptr<VirtualNetDevice> giTunDevice = CreateObject<VirtualNetDevice> ();
Ptr<VirtualNetDevice> tunDevice = CreateObject<VirtualNetDevice> ();
// yes we need this
giTunDevice->SetAddress (Mac48Address::Allocate ());
tunDevice->SetAddress (Mac48Address::Allocate ());
m_sgwPgw->AddDevice (giTunDevice);
NetDeviceContainer giTunDeviceContainer;
giTunDeviceContainer.Add (giTunDevice);
m_sgwPgw->AddDevice (tunDevice);
NetDeviceContainer tunDeviceContainer;
tunDeviceContainer.Add (tunDevice);
// the TUN device is on the same subnet as the UEs, so when a packet
// addressed to an UE arrives at the intenet to the WAN interface of
// the PGW it will be forwarded to the TUN device.
Ipv4InterfaceContainer giTunDeviceIpv4IfContainer = m_ueAddressHelper.Assign (giTunDeviceContainer);
Ipv4InterfaceContainer tunDeviceIpv4IfContainer = m_ueAddressHelper.Assign (tunDeviceContainer);
// create EpcSgwPgwApplication
m_sgwPgwApp = CreateObject<EpcSgwPgwApplication> (giTunDevice, sgwPgwS1uSocket);
m_sgwPgwApp = CreateObject<EpcSgwPgwApplication> (tunDevice, sgwPgwS1uSocket);
m_sgwPgw->AddApplication (m_sgwPgwApp);
// connect SgwPgwApplication and virtual net device for tunneling
giTunDevice->SetSendCallback (MakeCallback (&EpcSgwPgwApplication::RecvFromGiTunDevice, m_sgwPgwApp));
tunDevice->SetSendCallback (MakeCallback (&EpcSgwPgwApplication::RecvFromTunDevice, m_sgwPgwApp));
}
@@ -164,6 +164,7 @@ EpcHelper::AddEnb (Ptr<Node> enb, Ptr<NetDevice> lteEnbNetDevice)
Ptr<Socket> enbLteSocket = Socket::CreateSocket (enb, TypeId::LookupByName ("ns3::PacketSocketFactory"));
PacketSocketAddress enbLteSocketBindAddress;
enbLteSocketBindAddress.SetSingleDevice (lteEnbNetDevice->GetIfIndex ());
enbLteSocketBindAddress.SetProtocol (Ipv4L3Protocol::PROT_NUMBER);
retval = enbLteSocket->Bind (enbLteSocketBindAddress);
NS_ASSERT (retval == 0);
PacketSocketAddress enbLteSocketConnectAddress;
@@ -241,4 +242,12 @@ EpcHelper::AssignUeIpv4Address (NetDeviceContainer ueDevices)
Ipv4Address
EpcHelper::GetUeDefaultGatewayAddress ()
{
// return the address of the tun device
return m_sgwPgw->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal ();
}
} // namespace ns3

View File

@@ -104,6 +104,13 @@ public:
Ipv4InterfaceContainer AssignUeIpv4Address (NetDeviceContainer ueDevices);
/**
*
* \return the address of the Default Gateway to be used by UEs to reach the internet
*/
Ipv4Address GetUeDefaultGatewayAddress ();
private:
@@ -118,7 +125,6 @@ private:
*/
Ipv4AddressHelper m_ueAddressHelper;
Ptr<Node> m_sgwPgw;
Ptr<EpcSgwPgwApplication> m_sgwPgwApp;

View File

@@ -45,9 +45,10 @@ EpcEnbApplication::GetTypeId (void)
EpcEnbApplication::EpcEnbApplication (Ptr<Socket> lteSocket, Ptr<Socket> s1uSocket, Ipv4Address sgwAddress)
: m_lteSocket (lteSocket),
m_s1uSocket (s1uSocket),
m_sgwAddress (sgwAddress)
m_sgwAddress (sgwAddress),
m_gtpuUdpPort (2152) // fixed by the standard
{
NS_LOG_FUNCTION (this);
NS_LOG_FUNCTION (this << lteSocket << s1uSocket << sgwAddress);
m_s1uSocket->SetRecvCallback (MakeCallback (&EpcEnbApplication::RecvFromS1uSocket, this));
m_lteSocket->SetRecvCallback (MakeCallback (&EpcEnbApplication::RecvFromLteSocket, this));
}
@@ -74,12 +75,18 @@ EpcEnbApplication::RecvFromLteSocket (Ptr<Socket> socket)
NS_LOG_FUNCTION (this);
NS_ASSERT (socket == m_lteSocket);
Ptr<Packet> packet = socket->Recv ();
// workaround for bug 231 https://www.nsnam.org/bugzilla/show_bug.cgi?id=231
SocketAddressTag satag;
packet->RemovePacketTag (satag);
LteMacTag tag;
bool found = packet->RemovePacketTag (tag);
NS_ASSERT (found);
LteFlowId_t flowId;
flowId.m_rnti = tag.GetRnti ();
flowId.m_lcId = tag.GetLcid ();
NS_LOG_LOGIC ("received packet with RNTI=" << flowId.m_rnti << ", LCID=" << (uint16_t) flowId.m_lcId);
std::map<LteFlowId_t, uint32_t>::iterator it = m_rbidTeidMap.find (flowId);
NS_ASSERT (it != m_rbidTeidMap.end ());
uint32_t teid = it->second;
@@ -127,7 +134,7 @@ EpcEnbApplication::SendToS1uSocket (Ptr<Packet> packet, uint32_t teid)
gtpu.SetLength (packet->GetSize () + gtpu.GetSerializedSize () - 8);
packet->AddHeader (gtpu);
uint32_t flags = 0;
m_s1uSocket->SendTo (packet, flags, m_sgwAddress);
m_s1uSocket->SendTo (packet, flags, InetSocketAddress(m_sgwAddress, m_gtpuUdpPort));
}

View File

@@ -141,6 +141,11 @@ private:
*
*/
std::map<uint32_t, LteFlowId_t> m_teidRbidMap;
/**
* UDP port to be used for GTP
*/
uint16_t m_gtpuUdpPort;
};

View File

@@ -76,12 +76,12 @@ EpcSgwPgwApplication::GetTypeId (void)
EpcSgwPgwApplication::EpcSgwPgwApplication (const Ptr<VirtualNetDevice> giTunDevice, const Ptr<Socket> s1uSocket)
EpcSgwPgwApplication::EpcSgwPgwApplication (const Ptr<VirtualNetDevice> tunDevice, const Ptr<Socket> s1uSocket)
: m_s1uSocket (s1uSocket),
m_giTunDevice (giTunDevice),
m_tunDevice (tunDevice),
m_gtpuUdpPort (2152) // fixed by the standard
{
NS_LOG_FUNCTION (this << giTunDevice << s1uSocket);
NS_LOG_FUNCTION (this << tunDevice << s1uSocket);
m_s1uSocket->SetRecvCallback (MakeCallback (&EpcSgwPgwApplication::RecvFromS1uSocket, this));
}
@@ -105,7 +105,7 @@ EpcSgwPgwApplication::ActivateS1Bearer (Ipv4Address ueAddr, Ipv4Address enbAddr,
}
bool
EpcSgwPgwApplication::RecvFromGiTunDevice (Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber)
EpcSgwPgwApplication::RecvFromTunDevice (Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber)
{
NS_LOG_FUNCTION (this << source << dest << packet << packet->GetSize ());
@@ -158,14 +158,14 @@ EpcSgwPgwApplication::RecvFromS1uSocket (Ptr<Socket> socket)
SocketAddressTag tag;
packet->RemovePacketTag (tag);
SendToGiTunDevice (packet, teid);
SendToTunDevice (packet, teid);
}
void
EpcSgwPgwApplication::SendToGiTunDevice (Ptr<Packet> packet, uint32_t teid)
EpcSgwPgwApplication::SendToTunDevice (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);
m_tunDevice->Receive (packet, 0x0800, m_tunDevice->GetAddress (), m_tunDevice->GetAddress (), NetDevice::PACKET_HOST);
}
void

View File

@@ -55,12 +55,12 @@ public:
/**
* Constructor that binds the tap device to the callback methods.
*
* \param giTunDevice TUN VirtualNetDevice used to tunnel IP packets from
* \param tunDevice TUN VirtualNetDevice used to tunnel IP packets from
* the Gi interface of the PGW/SGW over the
* internet over GTP-U/UDP/IP on the S1-U interface
* \param s1uSocket socket used to send GTP-U packets to the eNBs
*/
EpcSgwPgwApplication (const Ptr<VirtualNetDevice> giTunDevice, const Ptr<Socket> s1uSocket);
EpcSgwPgwApplication (const Ptr<VirtualNetDevice> tunDevice, const Ptr<Socket> s1uSocket);
/**
* Destructor
@@ -95,7 +95,7 @@ public:
* \param protocolNumber
* \return true always
*/
bool RecvFromGiTunDevice (Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
bool RecvFromTunDevice (Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
/**
@@ -112,7 +112,7 @@ public:
*
* \param packet
*/
void SendToGiTunDevice (Ptr<Packet> packet, uint32_t teid);
void SendToTunDevice (Ptr<Packet> packet, uint32_t teid);
/**
@@ -172,7 +172,7 @@ private:
* 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;
Ptr<VirtualNetDevice> m_tunDevice;
/**
* Map telling for each UE address what is the corresponding eNB address
@@ -185,6 +185,9 @@ private:
*/
std::map<Ipv4Address, EnbInfo> m_enbInfoMap;
/**
* UDP port to be used for GTP
*/
uint16_t m_gtpuUdpPort;
};

View File

@@ -38,13 +38,17 @@
#include "ns3/uinteger.h"
using namespace ns3;
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("EpcTestS1uDownlink");
struct UeTestData
struct UeDlTestData
{
UeTestData (uint32_t n, uint32_t s);
UeDlTestData (uint32_t n, uint32_t s);
uint32_t numPkts;
uint32_t pktSize;
@@ -53,42 +57,42 @@ struct UeTestData
Ptr<Application> clientApp;
};
UeTestData::UeTestData (uint32_t n, uint32_t s)
UeDlTestData::UeDlTestData (uint32_t n, uint32_t s)
: numPkts (n),
pktSize (s)
{
}
struct EnbTestData
struct EnbDlTestData
{
std::vector<UeTestData> ues;
std::vector<UeDlTestData> ues;
};
class EpcS1uTestCase : public TestCase
class EpcS1uDlTestCase : public TestCase
{
public:
EpcS1uTestCase (std::string name, std::vector<EnbTestData> v);
virtual ~EpcS1uTestCase ();
EpcS1uDlTestCase (std::string name, std::vector<EnbDlTestData> v);
virtual ~EpcS1uDlTestCase ();
private:
virtual void DoRun (void);
std::vector<EnbTestData> m_enbTestData;
std::vector<EnbDlTestData> m_enbDlTestData;
};
EpcS1uTestCase::EpcS1uTestCase (std::string name, std::vector<EnbTestData> v)
EpcS1uDlTestCase::EpcS1uDlTestCase (std::string name, std::vector<EnbDlTestData> v)
: TestCase (name),
m_enbTestData (v)
m_enbDlTestData (v)
{
}
EpcS1uTestCase::~EpcS1uTestCase ()
EpcS1uDlTestCase::~EpcS1uDlTestCase ()
{
}
void
EpcS1uTestCase::DoRun ()
EpcS1uDlTestCase::DoRun ()
{
Ptr<EpcHelper> epcHelper = CreateObject<EpcHelper> ();
Ptr<Node> pgw = epcHelper->GetPgwNode ();
@@ -119,8 +123,8 @@ EpcS1uTestCase::DoRun ()
NodeContainer enbs;
for (std::vector<EnbTestData>::iterator enbit = m_enbTestData.begin ();
enbit < m_enbTestData.end ();
for (std::vector<EnbDlTestData>::iterator enbit = m_enbDlTestData.begin ();
enbit < m_enbDlTestData.end ();
++enbit)
{
Ptr<Node> enb = CreateObject<Node> ();
@@ -190,11 +194,11 @@ EpcS1uTestCase::DoRun ()
Simulator::Run ();
for (std::vector<EnbTestData>::iterator enbit = m_enbTestData.begin ();
enbit < m_enbTestData.end ();
for (std::vector<EnbDlTestData>::iterator enbit = m_enbDlTestData.begin ();
enbit < m_enbDlTestData.end ();
++enbit)
{
for (std::vector<UeTestData>::iterator ueit = enbit->ues.begin ();
for (std::vector<UeDlTestData>::iterator ueit = enbit->ues.begin ();
ueit < enbit->ues.end ();
++ueit)
{
@@ -212,60 +216,57 @@ EpcS1uTestCase::DoRun ()
/**
* Test that the S1-U interface implementation works correctly
*/
class EpcS1uTestSuite : public TestSuite
class EpcS1uDlTestSuite : public TestSuite
{
public:
EpcS1uTestSuite ();
EpcS1uDlTestSuite ();
} g_epcS1uTestSuiteInstance;
} g_epcS1uDlTestSuiteInstance;
EpcS1uTestSuite::EpcS1uTestSuite ()
EpcS1uDlTestSuite::EpcS1uDlTestSuite ()
: TestSuite ("epc-s1u-downlink", SYSTEM)
{
std::vector<EnbTestData> v1;
EnbTestData e1;
UeTestData f1 (1, 100);
std::vector<EnbDlTestData> v1;
EnbDlTestData e1;
UeDlTestData f1 (1, 100);
e1.ues.push_back (f1);
v1.push_back (e1);
AddTestCase (new EpcS1uTestCase ("1 eNB, 1UE", v1));
AddTestCase (new EpcS1uDlTestCase ("1 eNB, 1UE", v1));
std::vector<EnbTestData> v2;
EnbTestData e2;
UeTestData f2_1 (1, 100);
std::vector<EnbDlTestData> v2;
EnbDlTestData e2;
UeDlTestData f2_1 (1, 100);
e2.ues.push_back (f2_1);
UeTestData f2_2 (2, 200);
UeDlTestData f2_2 (2, 200);
e2.ues.push_back (f2_2);
v2.push_back (e2);
AddTestCase (new EpcS1uTestCase ("1 eNB, 2UEs", v2));
AddTestCase (new EpcS1uDlTestCase ("1 eNB, 2UEs", v2));
std::vector<EnbTestData> v3;
std::vector<EnbDlTestData> v3;
v3.push_back (e1);
v3.push_back (e2);
AddTestCase (new EpcS1uTestCase ("2 eNBs", v3));
AddTestCase (new EpcS1uDlTestCase ("2 eNBs", v3));
EnbTestData e3;
UeTestData f3_1 (3, 50);
EnbDlTestData e3;
UeDlTestData f3_1 (3, 50);
e3.ues.push_back (f3_1);
UeTestData f3_2 (5, 1472);
UeDlTestData f3_2 (5, 1472);
e3.ues.push_back (f3_2);
UeTestData f3_3 (1, 1);
UeDlTestData f3_3 (1, 1);
e3.ues.push_back (f3_2);
std::vector<EnbTestData> v4;
std::vector<EnbDlTestData> v4;
v4.push_back (e3);
v4.push_back (e1);
v4.push_back (e2);
AddTestCase (new EpcS1uTestCase ("3 eNBs", v4));
AddTestCase (new EpcS1uDlTestCase ("3 eNBs", v4));
}
} // namespace ns3

View File

@@ -0,0 +1,498 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007,2008,2009 INRIA, UDCAST
* 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
*
* The original version of UdpClient is by Amine Ismail
* <amine.ismail@sophia.inria.fr> <amine.ismail@udcast.com>
* The rest of the code (including modifying UdpClient into
* LteMacTagUdpClient) is by 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/packet-sink.h"
#include <ns3/ipv4-static-routing-helper.h>
#include <ns3/ipv4-static-routing.h>
#include <ns3/ipv4-interface.h>
#include <ns3/mac48-address.h>
#include "ns3/seq-ts-header.h"
#include "ns3/lte-mac-tag.h"
#include "ns3/arp-cache.h"
#include "ns3/boolean.h"
#include "ns3/uinteger.h"
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("EpcTestS1uUplink");
/*
* A Udp client. Sends UDP packet carrying sequence number and time
* stamp but also including the LteMacTag. This tag is normally
* generated by the LteEnbNetDevice when forwarding packet in the
* uplink. But in this test we don't have the LteEnbNetDevice, because
* we test the S1-U interface with simpler devices to make sure it
* just works.
*
*/
class LteMacTagUdpClient : public Application
{
public:
static TypeId
GetTypeId (void);
LteMacTagUdpClient ();
LteMacTagUdpClient (uint16_t rnti, uint8_t lcid);
virtual ~LteMacTagUdpClient ();
/**
* \brief set the remote address and port
* \param ip remote IP address
* \param port remote port
*/
void SetRemote (Ipv4Address ip, uint16_t port);
protected:
virtual void DoDispose (void);
private:
virtual void StartApplication (void);
virtual void StopApplication (void);
void ScheduleTransmit (Time dt);
void Send (void);
uint32_t m_count;
Time m_interval;
uint32_t m_size;
uint32_t m_sent;
Ptr<Socket> m_socket;
Ipv4Address m_peerAddress;
uint16_t m_peerPort;
EventId m_sendEvent;
uint16_t m_rnti;
uint8_t m_lcid;
};
TypeId
LteMacTagUdpClient::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::LteMacTagUdpClient")
.SetParent<Application> ()
.AddConstructor<LteMacTagUdpClient> ()
.AddAttribute ("MaxPackets",
"The maximum number of packets the application will send",
UintegerValue (100),
MakeUintegerAccessor (&LteMacTagUdpClient::m_count),
MakeUintegerChecker<uint32_t> ())
.AddAttribute ("Interval",
"The time to wait between packets", TimeValue (Seconds (1.0)),
MakeTimeAccessor (&LteMacTagUdpClient::m_interval),
MakeTimeChecker ())
.AddAttribute (
"RemoteAddress",
"The destination Ipv4Address of the outbound packets",
Ipv4AddressValue (),
MakeIpv4AddressAccessor (&LteMacTagUdpClient::m_peerAddress),
MakeIpv4AddressChecker ())
.AddAttribute ("RemotePort", "The destination port of the outbound packets",
UintegerValue (100),
MakeUintegerAccessor (&LteMacTagUdpClient::m_peerPort),
MakeUintegerChecker<uint16_t> ())
.AddAttribute ("PacketSize",
"Size of packets generated. The minimum packet size is 12 bytes which is the size of the header carrying the sequence number and the time stamp.",
UintegerValue (1024),
MakeUintegerAccessor (&LteMacTagUdpClient::m_size),
MakeUintegerChecker<uint32_t> (12,1500))
;
return tid;
}
LteMacTagUdpClient::LteMacTagUdpClient ()
: m_rnti (0),
m_lcid (0)
{
NS_LOG_FUNCTION_NOARGS ();
m_sent = 0;
m_socket = 0;
m_sendEvent = EventId ();
}
LteMacTagUdpClient::LteMacTagUdpClient (uint16_t rnti, uint8_t lcid)
: m_rnti (rnti),
m_lcid (lcid)
{
NS_LOG_FUNCTION_NOARGS ();
m_sent = 0;
m_socket = 0;
m_sendEvent = EventId ();
}
LteMacTagUdpClient::~LteMacTagUdpClient ()
{
NS_LOG_FUNCTION_NOARGS ();
}
void
LteMacTagUdpClient::SetRemote (Ipv4Address ip, uint16_t port)
{
m_peerAddress = ip;
m_peerPort = port;
}
void
LteMacTagUdpClient::DoDispose (void)
{
NS_LOG_FUNCTION_NOARGS ();
Application::DoDispose ();
}
void
LteMacTagUdpClient::StartApplication (void)
{
NS_LOG_FUNCTION_NOARGS ();
if (m_socket == 0)
{
TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
m_socket = Socket::CreateSocket (GetNode (), tid);
m_socket->Bind ();
m_socket->Connect (InetSocketAddress (m_peerAddress, m_peerPort));
}
m_socket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
m_sendEvent = Simulator::Schedule (Seconds (0.0), &LteMacTagUdpClient::Send, this);
}
void
LteMacTagUdpClient::StopApplication ()
{
NS_LOG_FUNCTION_NOARGS ();
Simulator::Cancel (m_sendEvent);
}
void
LteMacTagUdpClient::Send (void)
{
NS_LOG_FUNCTION_NOARGS ();
NS_ASSERT (m_sendEvent.IsExpired ());
SeqTsHeader seqTs;
seqTs.SetSeq (m_sent);
Ptr<Packet> p = Create<Packet> (m_size-(8+4)); // 8+4 : the size of the seqTs header
p->AddHeader (seqTs);
LteMacTag tag (m_rnti, m_lcid);
p->AddPacketTag (tag);
if ((m_socket->Send (p)) >= 0)
{
++m_sent;
NS_LOG_INFO ("TraceDelay TX " << m_size << " bytes to "
<< m_peerAddress << " Uid: " << p->GetUid ()
<< " Time: " << (Simulator::Now ()).GetSeconds ());
}
else
{
NS_LOG_INFO ("Error while sending " << m_size << " bytes to "
<< m_peerAddress);
}
if (m_sent < m_count)
{
m_sendEvent = Simulator::Schedule (m_interval, &LteMacTagUdpClient::Send, this);
}
}
struct UeUlTestData
{
UeUlTestData (uint32_t n, uint32_t s, uint16_t r, uint8_t l);
uint32_t numPkts;
uint32_t pktSize;
uint16_t rnti;
uint8_t lcid;
Ptr<PacketSink> serverApp;
Ptr<Application> clientApp;
};
UeUlTestData::UeUlTestData (uint32_t n, uint32_t s, uint16_t r, uint8_t l)
: numPkts (n),
pktSize (s),
rnti (r),
lcid (l)
{
}
struct EnbUlTestData
{
std::vector<UeUlTestData> ues;
};
class EpcS1uUlTestCase : public TestCase
{
public:
EpcS1uUlTestCase (std::string name, std::vector<EnbUlTestData> v);
virtual ~EpcS1uUlTestCase ();
private:
virtual void DoRun (void);
std::vector<EnbUlTestData> m_enbUlTestData;
};
EpcS1uUlTestCase::EpcS1uUlTestCase (std::string name, std::vector<EnbUlTestData> v)
: TestCase (name),
m_enbUlTestData (v)
{
}
EpcS1uUlTestCase::~EpcS1uUlTestCase ()
{
}
void
EpcS1uUlTestCase::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");
Ipv4InterfaceContainer internetNodesIpIfaceContainer = 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);
uint16_t udpSinkPort = 1234;
NodeContainer enbs;
for (std::vector<EnbUlTestData>::iterator enbit = m_enbUlTestData.begin ();
enbit < m_enbUlTestData.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);
// disable IP Forwarding on the UE. This is because we use
// CSMA broadcast MAC addresses for this test. The problem
// won't happen with a LteUeNetDevice.
Ptr<Ipv4> ueIpv4 = ue->GetObject<Ipv4> ();
ueIpv4->SetAttribute ("IpForward", BooleanValue (false));
// tell the UE to route all packets to the GW
Ptr<Ipv4StaticRouting> ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ueIpv4);
Ipv4Address gwAddr = epcHelper->GetUeDefaultGatewayAddress ();
NS_LOG_INFO ("GW address: " << gwAddr);
ueStaticRouting->SetDefaultRoute (gwAddr, 1);
// since the UEs in this test use CSMA with IP enabled, and
// the eNB uses CSMA but without IP, we fool the UE's ARP
// cache into thinking that the IP address of the GW can be
// reached by sending a CSMA packet to the broadcast
// address, so the eNB will get it.
int32_t ueLteIpv4IfIndex = ueIpv4->GetInterfaceForDevice (ueLteDevice);
Ptr<Ipv4L3Protocol> ueIpv4L3Protocol = ue->GetObject<Ipv4L3Protocol> ();
Ptr<Ipv4Interface> ueLteIpv4Iface = ueIpv4L3Protocol->GetInterface (ueLteIpv4IfIndex);
Ptr<ArpCache> ueArpCache = ueLteIpv4Iface->GetArpCache ();
ueArpCache->SetAliveTimeout (Seconds (1000));
ArpCache::Entry* arpCacheEntry = ueArpCache->Add (gwAddr);
arpCacheEntry->MarkWaitReply(0);
arpCacheEntry->MarkAlive (Mac48Address::GetBroadcast ());
PacketSinkHelper packetSinkHelper ("ns3::UdpSocketFactory",
InetSocketAddress (Ipv4Address::GetAny (), udpSinkPort));
ApplicationContainer sinkApp = packetSinkHelper.Install (remoteHost);
sinkApp.Start (Seconds (1.0));
sinkApp.Stop (Seconds (10.0));
enbit->ues[u].serverApp = sinkApp.Get (0)->GetObject<PacketSink> ();
Time interPacketInterval = Seconds (0.01);
Ptr<LteMacTagUdpClient> client = CreateObject<LteMacTagUdpClient> (enbit->ues[u].rnti, enbit->ues[u].lcid);
client->SetAttribute ("RemoteAddress", Ipv4AddressValue (internetNodesIpIfaceContainer.GetAddress (1)));
client->SetAttribute ("RemotePort", UintegerValue (udpSinkPort));
client->SetAttribute ("MaxPackets", UintegerValue (enbit->ues[u].numPkts));
client->SetAttribute ("Interval", TimeValue (interPacketInterval));
client->SetAttribute ("PacketSize", UintegerValue (enbit->ues[u].pktSize));
ue->AddApplication (client);
ApplicationContainer clientApp;
clientApp.Add (client);
clientApp.Start (Seconds (2.0));
clientApp.Stop (Seconds (10.0));
enbit->ues[u].clientApp = client;
uint16_t rnti = u+1;
uint16_t lcid = 1;
epcHelper->ActivateEpsBearer (ueLteDevice, lteEnbNetDevice, LteTft::Default (), rnti, lcid);
// need this since all sinks are installed in the same node
++udpSinkPort;
}
}
Simulator::Run ();
for (std::vector<EnbUlTestData>::iterator enbit = m_enbUlTestData.begin ();
enbit < m_enbUlTestData.end ();
++enbit)
{
for (std::vector<UeUlTestData>::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");
}
}
Simulator::Destroy ();
}
/**
* Test that the S1-U interface implementation works correctly
*/
class EpcS1uUlTestSuite : public TestSuite
{
public:
EpcS1uUlTestSuite ();
} g_epcS1uUlTestSuiteInstance;
EpcS1uUlTestSuite::EpcS1uUlTestSuite ()
: TestSuite ("epc-s1u-uplink", SYSTEM)
{
std::vector<EnbUlTestData> v1;
EnbUlTestData e1;
UeUlTestData f1 (1, 100, 1, 1);
e1.ues.push_back (f1);
v1.push_back (e1);
AddTestCase (new EpcS1uUlTestCase ("1 eNB, 1UE", v1));
std::vector<EnbUlTestData> v2;
EnbUlTestData e2;
UeUlTestData f2_1 (1, 100, 1, 1);
e2.ues.push_back (f2_1);
UeUlTestData f2_2 (2, 200, 2, 1);
e2.ues.push_back (f2_2);
v2.push_back (e2);
AddTestCase (new EpcS1uUlTestCase ("1 eNB, 2UEs", v2));
std::vector<EnbUlTestData> v3;
v3.push_back (e1);
v3.push_back (e2);
AddTestCase (new EpcS1uUlTestCase ("2 eNBs", v3));
EnbUlTestData e3;
UeUlTestData f3_1 (3, 50, 1, 1);
e3.ues.push_back (f3_1);
UeUlTestData f3_2 (5, 1472, 2, 1);
e3.ues.push_back (f3_2);
UeUlTestData f3_3 (1, 1, 3, 1);
e3.ues.push_back (f3_2);
std::vector<EnbUlTestData> v4;
v4.push_back (e3);
v4.push_back (e1);
v4.push_back (e2);
AddTestCase (new EpcS1uUlTestCase ("3 eNBs", v4));
}
} // namespace ns3

View File

@@ -81,6 +81,7 @@ def build(bld):
'test/epc-test-gtpu.cc',
'test/test-eps-tft-classifier.cc',
'test/epc-test-s1u-downlink.cc',
'test/epc-test-s1u-uplink.cc',
]
headers = bld.new_task_gen('ns3header')