S1-U now working also in uplink
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -141,6 +141,11 @@ private:
|
||||
*
|
||||
*/
|
||||
std::map<uint32_t, LteFlowId_t> m_teidRbidMap;
|
||||
|
||||
/**
|
||||
* UDP port to be used for GTP
|
||||
*/
|
||||
uint16_t m_gtpuUdpPort;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
498
src/lte/test/epc-test-s1u-uplink.cc
Normal file
498
src/lte/test/epc-test-s1u-uplink.cc
Normal 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
|
||||
|
||||
@@ -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')
|
||||
|
||||
Reference in New Issue
Block a user