A Discrete-Event Network Simulator
API
test-lte-handover-target.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Budiarto Herman
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Budiarto Herman <budiarto.herman@magister.fi>
18  *
19  */
20 
21 #include <ns3/boolean.h>
22 #include <ns3/callback.h>
23 #include <ns3/config.h>
24 #include <ns3/data-rate.h>
25 #include <ns3/double.h>
26 #include <ns3/internet-stack-helper.h>
27 #include <ns3/ipv4-address-helper.h>
28 #include <ns3/ipv4-interface-container.h>
29 #include <ns3/ipv4-static-routing-helper.h>
30 #include <ns3/ipv4-static-routing.h>
31 #include <ns3/log.h>
32 #include <ns3/lte-enb-net-device.h>
33 #include <ns3/lte-enb-phy.h>
34 #include <ns3/lte-helper.h>
35 #include <ns3/mobility-helper.h>
36 #include <ns3/net-device-container.h>
37 #include <ns3/node-container.h>
38 #include <ns3/nstime.h>
39 #include <ns3/point-to-point-epc-helper.h>
40 #include <ns3/point-to-point-helper.h>
41 #include <ns3/position-allocator.h>
42 #include <ns3/simulator.h>
43 #include <ns3/test.h>
44 #include <ns3/uinteger.h>
45 
46 using namespace ns3;
47 
48 NS_LOG_COMPONENT_DEFINE("LteHandoverTargetTest");
49 
64 {
65  public:
84  LteHandoverTargetTestCase(std::string name,
85  Vector uePosition,
86  uint8_t gridSizeX,
87  uint8_t gridSizeY,
88  uint16_t sourceCellId,
89  uint16_t targetCellId,
90  std::string handoverAlgorithmType);
91 
92  ~LteHandoverTargetTestCase() override;
93 
107  void HandoverStartCallback(std::string context,
108  uint64_t imsi,
109  uint16_t sourceCellId,
110  uint16_t rnti,
111  uint16_t targetCellId);
112 
117  void CellShutdownCallback();
118 
119  private:
124  void DoRun() override;
125 
130  void DoTeardown() override;
131 
132  // simulation parameters
133  Vector m_uePosition;
134  uint8_t m_gridSizeX;
135  uint8_t m_gridSizeY;
136  uint16_t m_sourceCellId;
137  uint16_t m_targetCellId;
139 
142 
143 }; // end of class LteHandoverTargetTestCase
144 
146  Vector uePosition,
147  uint8_t gridSizeX,
148  uint8_t gridSizeY,
149  uint16_t sourceCellId,
150  uint16_t targetCellId,
151  std::string handoverAlgorithmType)
152  : TestCase(name),
153  m_uePosition(uePosition),
154  m_gridSizeX(gridSizeX),
155  m_gridSizeY(gridSizeY),
156  m_sourceCellId(sourceCellId),
157  m_targetCellId(targetCellId),
158  m_handoverAlgorithmType(handoverAlgorithmType),
159  m_sourceEnbDev(nullptr),
160  m_hasHandoverOccurred(false)
161 {
162  NS_LOG_INFO(this << " name=" << name);
163 
164  // SANITY CHECK
165 
166  uint16_t nEnb = gridSizeX * gridSizeY;
167 
168  if (sourceCellId > nEnb)
169  {
170  NS_FATAL_ERROR("Invalid source cell ID " << sourceCellId);
171  }
172 
173  if (targetCellId > nEnb)
174  {
175  NS_FATAL_ERROR("Invalid target cell ID " << targetCellId);
176  }
177 }
178 
180 {
181  NS_LOG_FUNCTION(this);
182 }
183 
184 void
186  uint64_t imsi,
187  uint16_t sourceCellId,
188  uint16_t rnti,
189  uint16_t targetCellId)
190 {
191  NS_LOG_FUNCTION(this << context << imsi << sourceCellId << rnti << targetCellId);
192 
193  uint64_t timeNowMs = Simulator::Now().GetMilliSeconds();
194  NS_TEST_ASSERT_MSG_GT(timeNowMs, 500, "Handover occurred but too early");
195  NS_TEST_ASSERT_MSG_EQ(sourceCellId,
197  "Handover occurred but with wrong source cell");
198  NS_TEST_ASSERT_MSG_EQ(targetCellId,
200  "Handover occurred but with wrong target cell");
201  m_hasHandoverOccurred = true;
202 }
203 
204 void
206 {
207  NS_LOG_FUNCTION(this);
208 
209  if (m_sourceEnbDev)
210  {
211  // set the Tx power to 1 dBm
213  NS_LOG_INFO("Shutting down cell " << m_sourceCellId);
215  phy->SetTxPower(1);
216  }
217 }
218 
219 void
221 {
222  NS_LOG_INFO(this << " " << GetName());
223 
224  Config::SetDefault("ns3::LteEnbPhy::TxPower", DoubleValue(38)); // micro cell
225  Config::SetDefault("ns3::LteSpectrumPhy::CtrlErrorModelEnabled",
226  BooleanValue(false)); // disable control channel error model
227 
228  Ptr<LteHelper> lteHelper = CreateObject<LteHelper>();
229  Ptr<PointToPointEpcHelper> epcHelper = CreateObject<PointToPointEpcHelper>();
230  lteHelper->SetEpcHelper(epcHelper);
231  lteHelper->SetAttribute("PathlossModel", StringValue("ns3::FriisSpectrumPropagationLossModel"));
232  lteHelper->SetAttribute("UseIdealRrc", BooleanValue(true));
233 
234  if (m_handoverAlgorithmType == "ns3::A2A4RsrqHandoverAlgorithm")
235  {
236  lteHelper->SetHandoverAlgorithmType("ns3::A2A4RsrqHandoverAlgorithm");
237  lteHelper->SetHandoverAlgorithmAttribute("ServingCellThreshold", UintegerValue(30));
238  lteHelper->SetHandoverAlgorithmAttribute("NeighbourCellOffset", UintegerValue(1));
239  }
240  else if (m_handoverAlgorithmType == "ns3::A3RsrpHandoverAlgorithm")
241  {
242  lteHelper->SetHandoverAlgorithmType("ns3::A3RsrpHandoverAlgorithm");
243  lteHelper->SetHandoverAlgorithmAttribute("Hysteresis", DoubleValue(1.5));
244  lteHelper->SetHandoverAlgorithmAttribute("TimeToTrigger", TimeValue(MilliSeconds(128)));
245  }
246  else
247  {
248  NS_FATAL_ERROR("Unknown handover algorithm " << m_handoverAlgorithmType);
249  }
250 
251  // Create Nodes: eNodeB and UE
252  NodeContainer enbNodes;
253  NodeContainer ueNodes;
254  enbNodes.Create(m_gridSizeX * m_gridSizeY);
255  ueNodes.Create(1);
256 
257  /*
258  * The size of the grid is determined by m_gridSizeX and m_gridSizeY. The
259  * following figure is the topology when m_gridSizeX = 4 and m_gridSizeY = 3.
260  *
261  * 9 -- 10 -- 11 -- 12
262  * | | | |
263  * | | | |
264  * 5 --- 6 --- 7 --- 8
265  * | | | |
266  * | | | |
267  * (0, 0, 0) ---> 1 --- 2 --- 3 --- 4
268  *
269  * The grid starts at (0, 0, 0) point on the bottom left corner. The distance
270  * between two adjacent eNodeBs is 130 m.
271  */
272 
273  // Set up eNodeB position
274  MobilityHelper enbMobility;
275  enbMobility.SetPositionAllocator("ns3::GridPositionAllocator",
276  "MinX",
277  DoubleValue(0.0),
278  "MinY",
279  DoubleValue(0.0),
280  "DeltaX",
281  DoubleValue(130.0),
282  "DeltaY",
283  DoubleValue(130.0),
284  "GridWidth",
286  "LayoutType",
287  StringValue("RowFirst"));
288  enbMobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
289  enbMobility.Install(enbNodes);
290 
291  // Setup UE position
292  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
293  positionAlloc->Add(m_uePosition);
294  MobilityHelper ueMobility;
295  ueMobility.SetPositionAllocator(positionAlloc);
296  ueMobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
297  ueMobility.Install(ueNodes);
298 
299  // Create P-GW node
300  Ptr<Node> pgw = epcHelper->GetPgwNode();
301 
302  // Create a single RemoteHost
303  NodeContainer remoteHostContainer;
304  remoteHostContainer.Create(1);
305  Ptr<Node> remoteHost = remoteHostContainer.Get(0);
307  internet.Install(remoteHostContainer);
308 
309  // Create the Internet
310  PointToPointHelper p2ph;
311  p2ph.SetDeviceAttribute("DataRate", DataRateValue(DataRate("100Gb/s")));
312  p2ph.SetDeviceAttribute("Mtu", UintegerValue(1500));
313  p2ph.SetChannelAttribute("Delay", TimeValue(Seconds(0.010)));
314  NetDeviceContainer internetDevices = p2ph.Install(pgw, remoteHost);
315  Ipv4AddressHelper ipv4h;
316  ipv4h.SetBase("1.0.0.0", "255.0.0.0");
317  Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign(internetDevices);
318 
319  // Routing of the Internet Host (towards the LTE network)
320  Ipv4StaticRoutingHelper ipv4RoutingHelper;
321  Ptr<Ipv4StaticRouting> remoteHostStaticRouting =
322  ipv4RoutingHelper.GetStaticRouting(remoteHost->GetObject<Ipv4>());
323  remoteHostStaticRouting->AddNetworkRouteTo(Ipv4Address("7.0.0.0"), Ipv4Mask("255.0.0.0"), 1);
324 
325  // Create Devices and install them in the Nodes (eNB and UE)
326  NetDeviceContainer enbDevs;
327  NetDeviceContainer ueDevs;
328  enbDevs = lteHelper->InstallEnbDevice(enbNodes);
329  ueDevs = lteHelper->InstallUeDevice(ueNodes);
330 
331  // Install the IP stack on the UEs
332  internet.Install(ueNodes);
333  Ipv4InterfaceContainer ueIpIfaces;
334  ueIpIfaces = epcHelper->AssignUeIpv4Address(NetDeviceContainer(ueDevs));
335 
336  // Assign IP address to UEs
337  for (uint32_t u = 0; u < ueNodes.GetN(); ++u)
338  {
339  Ptr<Node> ueNode = ueNodes.Get(u);
340  // Set the default gateway for the UE
341  Ptr<Ipv4StaticRouting> ueStaticRouting =
342  ipv4RoutingHelper.GetStaticRouting(ueNode->GetObject<Ipv4>());
343  ueStaticRouting->SetDefaultRoute(epcHelper->GetUeDefaultGatewayAddress(), 1);
344  }
345 
346  // Add X2 interface
347  lteHelper->AddX2Interface(enbNodes);
348 
349  // Connect to trace sources in all eNodeB
350  Config::Connect("/NodeList/*/DeviceList/*/LteEnbRrc/HandoverStart",
352 
353  // Get the source eNodeB
354  Ptr<NetDevice> sourceEnb = enbDevs.Get(m_sourceCellId - 1);
355  m_sourceEnbDev = sourceEnb->GetObject<LteEnbNetDevice>();
358 
359  // Attach UE to the source eNodeB
360  lteHelper->Attach(ueDevs.Get(0), sourceEnb);
361 
362  // Schedule a "shutdown" of the source eNodeB
363  Simulator::Schedule(Seconds(0.5), &LteHandoverTargetTestCase::CellShutdownCallback, this);
364 
365  // Run simulation
366  Simulator::Stop(Seconds(1));
367  Simulator::Run();
368  Simulator::Destroy();
369 
370 } // end of void LteX2HandoverTargetTestCase::DoRun ()
371 
372 void
374 {
375  NS_LOG_FUNCTION(this);
376  NS_TEST_ASSERT_MSG_EQ(m_hasHandoverOccurred, true, "Handover did not occur");
377 }
378 
388 {
389  public:
391 };
392 
394  : TestSuite("lte-handover-target", SYSTEM)
395 {
396  // LogComponentEnable ("LteHandoverTargetTest", LOG_PREFIX_ALL);
397  // LogComponentEnable ("LteHandoverTargetTest", LOG_LEVEL_ALL);
398  // LogComponentEnable ("A2A4RsrqHandoverAlgorithm", LOG_PREFIX_ALL);
399  // LogComponentEnable ("A2A4RsrqHandoverAlgorithm", LOG_LEVEL_ALL);
400  // LogComponentEnable ("A3RsrpHandoverAlgorithm", LOG_PREFIX_ALL);
401  // LogComponentEnable ("A3RsrpHandoverAlgorithm", LOG_LEVEL_ALL);
402 
403  /*
404  * 3 --- 4
405  * | |
406  * |o |
407  * 1 --- 2 o = UE
408  */
409  AddTestCase(new LteHandoverTargetTestCase("4 cells and A2-A4-RSRQ algorithm",
410  Vector(20, 40, 0),
411  2,
412  2,
413  1,
414  3,
415  "ns3::A2A4RsrqHandoverAlgorithm"),
416  TestCase::QUICK);
417  AddTestCase(new LteHandoverTargetTestCase("4 cells and strongest cell algorithm",
418  Vector(20, 40, 0),
419  2,
420  2,
421  1,
422  3,
423  "ns3::A3RsrpHandoverAlgorithm"),
424  TestCase::QUICK);
425 
426  /*
427  * 4 --- 5 --- 6
428  * | |o |
429  * | | |
430  * 1 --- 2 --- 3 o = UE
431  */
432  AddTestCase(new LteHandoverTargetTestCase("6 cells and A2-A4-RSRQ algorithm",
433  Vector(150, 90, 0),
434  3,
435  2,
436  5,
437  2,
438  "ns3::A2A4RsrqHandoverAlgorithm"),
439  TestCase::EXTENSIVE);
440  AddTestCase(new LteHandoverTargetTestCase("6 cells and strongest cell algorithm",
441  Vector(150, 90, 0),
442  3,
443  2,
444  5,
445  2,
446  "ns3::A3RsrpHandoverAlgorithm"),
447  TestCase::EXTENSIVE);
448 
449 } // end of LteHandoverTargetTestSuite ()
450 
Testing a handover algorithm, verifying that it selects the right target cell when more than one opti...
Ptr< LteEnbNetDevice > m_sourceEnbDev
source ENB device
std::string m_handoverAlgorithmType
handover algorithm type
bool m_hasHandoverOccurred
has handover occurred?
LteHandoverTargetTestCase(std::string name, Vector uePosition, uint8_t gridSizeX, uint8_t gridSizeY, uint16_t sourceCellId, uint16_t targetCellId, std::string handoverAlgorithmType)
Construct a new test case and providing input parameters for the simulation.
void DoTeardown() override
Called at the end of simulation and verifies that a handover has occurred in the simulation.
void CellShutdownCallback()
A trigger that can be scheduled to "shutdown" the cell pointed by m_sourceCellId by reducing its powe...
uint16_t m_sourceCellId
source cell ID
void HandoverStartCallback(std::string context, uint64_t imsi, uint16_t sourceCellId, uint16_t rnti, uint16_t targetCellId)
Triggers when an eNodeB starts a handover and then verifies that the handover has the right source an...
uint16_t m_targetCellId
target cell ID
void DoRun() override
Run a simulation of a micro-cell network using the parameters provided to the constructor function.
Test suite lte-handover-target, verifying that handover algorithms are able to select the right targe...
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
aggregate IP/TCP/UDP functionality to existing Nodes.
A helper class to make life easier while doing simple IPv4 address assignment in scripts.
void SetBase(Ipv4Address network, Ipv4Mask mask, Ipv4Address base="0.0.0.1")
Set the base network number, network mask and base address.
Ipv4InterfaceContainer Assign(const NetDeviceContainer &c)
Assign IP addresses to the net devices specified in the container based on the current network prefix...
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:42
Access to the IPv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:80
holds a vector of std::pair of Ptr<Ipv4> and interface index.
a class to represent an Ipv4 address mask
Definition: ipv4-address.h:257
Helper class that adds ns3::Ipv4StaticRouting objects.
Ptr< Ipv4StaticRouting > GetStaticRouting(Ptr< Ipv4 > ipv4) const
Try and find the static routing protocol as either the main routing protocol or in the list of routin...
The eNodeB device implementation.
Ptr< LteEnbPhy > GetPhy() const
uint16_t GetCellId() const
void SetEpcHelper(Ptr< EpcHelper > h)
Set the EpcHelper to be used to setup the EPC network in conjunction with the setup of the LTE radio ...
Definition: lte-helper.cc:285
void SetHandoverAlgorithmAttribute(std::string n, const AttributeValue &v)
Set an attribute for the handover algorithm to be created.
Definition: lte-helper.cc:348
NetDeviceContainer InstallEnbDevice(NodeContainer c)
Create a set of eNodeB devices.
Definition: lte-helper.cc:485
void SetHandoverAlgorithmType(std::string type)
Set the type of handover algorithm to be used by eNodeB devices.
Definition: lte-helper.cc:340
void Attach(NetDeviceContainer ueDevices)
Enables automatic attachment of a set of UE devices to a suitable cell using Idle mode initial cell s...
Definition: lte-helper.cc:1039
NetDeviceContainer InstallUeDevice(NodeContainer c)
Create a set of UE devices.
Definition: lte-helper.cc:500
void AddX2Interface(NodeContainer enbNodes)
Create an X2 interface between all the eNBs in a given set.
Definition: lte-helper.cc:1313
Helper class used to assign positions and mobility models to nodes.
void Install(Ptr< Node > node) const
"Layout" a single node according to the current position allocator type.
void SetMobilityModel(std::string type, Ts &&... args)
void SetPositionAllocator(Ptr< PositionAllocator > allocator)
Set the position allocator which will be used to allocate the initial position of every node initiali...
holds a vector of ns3::NetDevice pointers
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
Ptr< Node > GetPgwNode() const override
Get the PGW node.
Ipv4Address GetUeDefaultGatewayAddress() override
Ipv4InterfaceContainer AssignUeIpv4Address(NetDeviceContainer ueDevices) override
Assign IPv4 addresses to UE devices.
keep track of a set of node pointers.
uint32_t GetN() const
Get the number of Ptr<Node> stored in this container.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:204
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
Build a set of PointToPointNetDevice objects.
void SetDeviceAttribute(std::string name, const AttributeValue &value)
Set an attribute value to be propagated to each NetDevice created by the helper.
void SetChannelAttribute(std::string name, const AttributeValue &value)
Set an attribute value to be propagated to each Channel created by the helper.
NetDeviceContainer Install(NodeContainer c)
Hold variables of type string.
Definition: string.h:56
encapsulates test code
Definition: test.h:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
std::string GetName() const
Definition: test.cc:373
A suite of tests to run.
Definition: test.h:1256
int64_t GetMilliSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:408
Hold an unsigned integer type.
Definition: uinteger.h:45
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:890
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:974
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
static LteHandoverTargetTestSuite g_lteHandoverTargetTestSuiteInstance
Static variable for test initialization.
void(* DataRate)(DataRate oldValue, DataRate newValue)
TracedValue callback signature for DataRate.
Definition: data-rate.h:327
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:305
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition: test.h:144
#define NS_TEST_ASSERT_MSG_GT(actual, limit, msg)
Test that an actual value is greater than a limit and report and abort if not.
Definition: test.h:874
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:704
phy
Definition: third.py:89