/* -*- 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/lte-helper.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/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/boolean.h"
#include "ns3/uinteger.h"
#include "ns3/double.h"
#include "ns3/abort.h"
#include "ns3/mobility-helper.h"
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("LteEpcE2eData");
struct BearerTestData
{
BearerTestData (uint32_t n, uint32_t s);
uint32_t numPkts;
uint32_t pktSize;
Ptr<PacketSink> dlServerApp;
Ptr<Application> dlClientApp;
Ptr<PacketSink> ulServerApp;
Ptr<Application> ulClientApp;
};
BearerTestData::BearerTestData (uint32_t n, uint32_t s)
: numPkts (n),
pktSize (s)
{
}
struct UeTestData
{
std::vector<BearerTestData> bearers;
};
struct EnbTestData
{
std::vector<UeTestData> ues;
};
class LteEpcE2eDataTestCase : public TestCase
{
public:
LteEpcE2eDataTestCase (std::string name, std::vector<EnbTestData> v);
virtual ~LteEpcE2eDataTestCase ();
private:
virtual void DoRun (void);
std::vector<EnbTestData> m_enbTestData;
};
LteEpcE2eDataTestCase::LteEpcE2eDataTestCase (std::string name, std::vector<EnbTestData> v)
: TestCase (name),
m_enbTestData (v)
{
}
LteEpcE2eDataTestCase::~LteEpcE2eDataTestCase ()
{
}
void
LteEpcE2eDataTestCase::DoRun ()
{
Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
Ptr<EpcHelper> epcHelper = CreateObject<EpcHelper> ();
lteHelper->SetEpcHelper (epcHelper);
lteHelper->SetAttribute("PathlossModel",
StringValue("ns3::FriisPropagationLossModel"));
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;
p2ph.SetDeviceAttribute ("DataRate", DataRateValue (DataRate ("100Gb/s")));
p2ph.SetDeviceAttribute ("Mtu", UintegerValue (1500));
p2ph.SetChannelAttribute ("Delay", TimeValue (Seconds (0.010)));
NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost);
Ipv4AddressHelper ipv4h;
ipv4h.SetBase ("1.0.0.0", "255.0.0.0");
Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign (internetDevices);
Ipv4Address remoteHostAddr = internetIpIfaces.GetAddress (1);
// 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;
enbs.Create (m_enbTestData.size ());
MobilityHelper enbMobility;
enbMobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
enbMobility.SetPositionAllocator ("ns3::GridPositionAllocator",
"MinX", DoubleValue (0.0),
"MinY", DoubleValue (0.0),
"DeltaX", DoubleValue (10000.0),
"DeltaY", DoubleValue (10000.0),
"GridWidth", UintegerValue (3),
"LayoutType", StringValue ("RowFirst"));
enbMobility.Install (enbs);
NetDeviceContainer enbLteDevs = lteHelper->InstallEnbDevice (enbs);
NetDeviceContainer::Iterator enbLteDevIt = enbLteDevs.Begin ();
uint16_t ulPort = 1000;
for (std::vector<EnbTestData>::iterator enbit = m_enbTestData.begin ();
enbit < m_enbTestData.end ();
++enbit, ++enbLteDevIt)
{
NS_ABORT_IF (enbLteDevIt == enbLteDevs.End ());
NodeContainer ues;
ues.Create (enbit->ues.size ());
Vector enbPosition = (*enbLteDevIt)->GetNode ()->GetObject<MobilityModel> ()->GetPosition ();
MobilityHelper ueMobility;
ueMobility.SetPositionAllocator ("ns3::UniformDiscPositionAllocator",
"X", DoubleValue (enbPosition.x),
"Y", DoubleValue (enbPosition.y),
"rho", DoubleValue (100.0));
ueMobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
ueMobility.Install (ues);
NetDeviceContainer ueLteDevs = lteHelper->InstallUeDevice (ues);
lteHelper->Attach (ueLteDevs, *enbLteDevIt);
// we install the IP stack on the UEs
InternetStackHelper internet;
internet.Install (ues);
// assign IP address to UEs, and install applications
for (uint32_t u = 0; u < ues.GetN (); ++u)
{
Ptr<Node> ue = ues.Get (u);
Ptr<NetDevice> ueLteDevice = ueLteDevs.Get (u);
Ipv4InterfaceContainer ueIpIface = epcHelper->AssignUeIpv4Address (NetDeviceContainer (ueLteDevice));
// set the default gateway for the UE
Ptr<Ipv4StaticRouting> ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ue->GetObject<Ipv4> ());
ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress (), 1);
uint16_t dlPort = 2000;
for (uint32_t b = 0; b < enbit->ues.at (u).bearers.size (); ++b)
{
BearerTestData& bearerTestData = enbit->ues.at (u).bearers.at (b);
{ // Downlink
++dlPort;
PacketSinkHelper packetSinkHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), dlPort));
ApplicationContainer apps = packetSinkHelper.Install (ue);
apps.Start (Seconds (0.01));
bearerTestData.dlServerApp = apps.Get (0)->GetObject<PacketSink> ();
Time interPacketInterval = Seconds (0.01);
UdpClientHelper client (ueIpIface.GetAddress (0), dlPort);
client.SetAttribute ("MaxPackets", UintegerValue (bearerTestData.numPkts));
client.SetAttribute ("Interval", TimeValue (interPacketInterval));
client.SetAttribute ("PacketSize", UintegerValue (bearerTestData.pktSize));
apps = client.Install (remoteHost);
apps.Start (Seconds (0.01));
bearerTestData.dlClientApp = apps.Get (0);
}
{ // Uplink
++ulPort;
PacketSinkHelper packetSinkHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), ulPort));
ApplicationContainer apps = packetSinkHelper.Install (remoteHost);
apps.Start (Seconds (0.5));
bearerTestData.ulServerApp = apps.Get (0)->GetObject<PacketSink> ();
Time interPacketInterval = Seconds (0.01);
UdpClientHelper client (remoteHostAddr, ulPort);
client.SetAttribute ("MaxPackets", UintegerValue (bearerTestData.numPkts));
client.SetAttribute ("Interval", TimeValue (interPacketInterval));
client.SetAttribute ("PacketSize", UintegerValue (bearerTestData.pktSize));
apps = client.Install (ue);
apps.Start (Seconds (0.5));
bearerTestData.ulClientApp = apps.Get (0);
}
EpsBearer epsBearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT);
Ptr<EpcTft> tft = Create<EpcTft> ();
EpcTft::PacketFilter dlpf;
dlpf.localPortStart = dlPort;
dlpf.localPortEnd = dlPort;
tft->Add (dlpf);
EpcTft::PacketFilter ulpf;
ulpf.remotePortStart = ulPort;
ulpf.remotePortEnd = ulPort;
tft->Add (ulpf);
lteHelper->ActivateEpsBearer (ueLteDevice, epsBearer, tft);
}
}
}
lteHelper->EnableRlcTraces ();
lteHelper->EnablePdcpTraces ();
Time simulationTime = Seconds (2.0);
lteHelper->GetPdcpStats ()->SetAttribute ("EpochDuration", TimeValue (simulationTime));
Simulator::Stop (simulationTime);
Simulator::Run ();
static uint64_t imsiCounter = 0;
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)
{
uint64_t imsi = ++imsiCounter;
for (uint32_t b = 0; b < ueit->bearers.size (); ++b)
{
uint8_t lcid = b+1;
NS_TEST_ASSERT_MSG_EQ (lteHelper->GetPdcpStats ()->GetDlTxPackets (imsi, lcid),
ueit->bearers.at (b).numPkts,
"wrong TX PDCP packets in downlink for IMSI=" << imsi << " LCID=" << (uint16_t) lcid);
NS_TEST_ASSERT_MSG_EQ (lteHelper->GetPdcpStats ()->GetDlRxPackets (imsi, lcid),
ueit->bearers.at (b).numPkts,
"wrong RX PDCP packets in downlink for IMSI=" << imsi << " LCID=" << (uint16_t) lcid);
NS_TEST_ASSERT_MSG_EQ (lteHelper->GetPdcpStats ()->GetUlTxPackets (imsi, lcid),
ueit->bearers.at (b).numPkts,
"wrong TX PDCP packets in uplink for IMSI=" << imsi << " LCID=" << (uint16_t) lcid);
NS_TEST_ASSERT_MSG_EQ (lteHelper->GetPdcpStats ()->GetUlRxPackets (imsi, lcid),
ueit->bearers.at (b).numPkts,
"wrong RX PDCP packets in uplink for IMSI=" << imsi << " LCID=" << (uint16_t) lcid);
NS_TEST_ASSERT_MSG_EQ (ueit->bearers.at (b).dlServerApp->GetTotalRx (),
(ueit->bearers.at (b).numPkts) * (ueit->bearers.at (b).pktSize),
"wrong total received bytes in downlink");
NS_TEST_ASSERT_MSG_EQ (ueit->bearers.at (b).ulServerApp->GetTotalRx (),
(ueit->bearers.at (b).numPkts) * (ueit->bearers.at (b).pktSize),
"wrong total received bytes in uplink");
}
}
}
Simulator::Destroy ();
}
/**
* Test that the S1-U interface implementation works correctly
*/
class LteEpcE2eDataTestSuite : public TestSuite
{
public:
LteEpcE2eDataTestSuite ();
} g_lteEpcE2eDataTestSuite;
LteEpcE2eDataTestSuite::LteEpcE2eDataTestSuite ()
: TestSuite ("lte-epc-e2e-data", SYSTEM)
{
std::vector<EnbTestData> v1;
EnbTestData e1;
UeTestData u1;
BearerTestData f1 (1, 100);
u1.bearers.push_back (f1);
e1.ues.push_back (u1);
v1.push_back (e1);
AddTestCase (new LteEpcE2eDataTestCase ("1 eNB, 1UE", v1));
std::vector<EnbTestData> v2;
EnbTestData e2;
UeTestData u2_1;
BearerTestData f2_1 (1, 100);
u2_1.bearers.push_back (f2_1);
e2.ues.push_back (u2_1);
UeTestData u2_2;
BearerTestData f2_2 (2, 200);
u2_2.bearers.push_back (f2_2);
e2.ues.push_back (u2_2);
v2.push_back (e2);
AddTestCase (new LteEpcE2eDataTestCase ("1 eNB, 2UEs", v2));
std::vector<EnbTestData> v3;
v3.push_back (e1);
v3.push_back (e2);
AddTestCase (new LteEpcE2eDataTestCase ("2 eNBs", v3));
EnbTestData e4;
UeTestData u4_1;
BearerTestData f4_1 (3, 50);
u4_1.bearers.push_back (f4_1);
e4.ues.push_back (u4_1);
UeTestData u4_2;
BearerTestData f4_2 (5, 1400);
u4_2.bearers.push_back (f4_2);
e4.ues.push_back (u4_2);
UeTestData u4_3;
BearerTestData f4_3 (1, 12);
u4_3.bearers.push_back (f4_3);
e4.ues.push_back (u4_3);
std::vector<EnbTestData> v4;
v4.push_back (e4);
v4.push_back (e1);
v4.push_back (e2);
AddTestCase (new LteEpcE2eDataTestCase ("3 eNBs", v4));
EnbTestData e5;
UeTestData u5;
BearerTestData f5 (5, 1000);
u5.bearers.push_back (f5);
e5.ues.push_back (u5);
std::vector<EnbTestData> v5;
v5.push_back (e5);
AddTestCase (new LteEpcE2eDataTestCase ("1 eNB, 1UE with 1000 byte packets", v5));
EnbTestData e6;
UeTestData u6;
BearerTestData f6 (5, 1400);
u6.bearers.push_back (f6);
e6.ues.push_back (u6);
std::vector<EnbTestData> v6;
v6.push_back (e6);
AddTestCase (new LteEpcE2eDataTestCase ("1 eNB, 1UE with 1400 byte packets", v6));
EnbTestData e7;
UeTestData u7;
BearerTestData f7_1 (1, 1400);
u7.bearers.push_back (f7_1);
BearerTestData f7_2 (1, 100);
u7.bearers.push_back (f7_2);
e7.ues.push_back (u7);
std::vector<EnbTestData> v7;
v7.push_back (e7);
AddTestCase (new LteEpcE2eDataTestCase ("1 eNB, 1UE with 2 bearers", v7));
}
} // namespace ns3