A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
test-lte-handover-target.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2013 Budiarto Herman
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Budiarto Herman <budiarto.herman@magister.fi>
7 *
8 */
9
10#include <ns3/boolean.h>
11#include <ns3/callback.h>
12#include <ns3/config.h>
13#include <ns3/data-rate.h>
14#include <ns3/double.h>
15#include <ns3/internet-stack-helper.h>
16#include <ns3/ipv4-address-helper.h>
17#include <ns3/ipv4-interface-container.h>
18#include <ns3/ipv4-static-routing-helper.h>
19#include <ns3/ipv4-static-routing.h>
20#include <ns3/log.h>
21#include <ns3/lte-enb-net-device.h>
22#include <ns3/lte-enb-phy.h>
23#include <ns3/lte-helper.h>
24#include <ns3/mobility-helper.h>
25#include <ns3/net-device-container.h>
26#include <ns3/node-container.h>
27#include <ns3/nstime.h>
28#include <ns3/point-to-point-epc-helper.h>
29#include <ns3/point-to-point-helper.h>
30#include <ns3/position-allocator.h>
31#include <ns3/simulator.h>
32#include <ns3/test.h>
33#include <ns3/uinteger.h>
34
35using namespace ns3;
36
37NS_LOG_COMPONENT_DEFINE("LteHandoverTargetTest");
38
39/**
40 * @ingroup lte-test
41 *
42 * @brief Testing a handover algorithm, verifying that it selects the right
43 * target cell when more than one options available.
44 *
45 * Part of the `lte-handover-target` test suite.
46 *
47 * The test case will run a 1-second LTE-EPC simulation using the parameters
48 * provided to the constructor function.
49 *
50 * \sa ns3::LteHandoverTargetTestCase
51 */
53{
54 public:
55 /**
56 * @brief Construct a new test case and providing input parameters for the
57 * simulation.
58 * @param name the name of the test case, to be displayed in the test result
59 * @param uePosition the point in (x, y, z) coordinate where the UE will be
60 * placed in the simulation
61 * @param gridSizeX number of eNodeBs in a row
62 * @param gridSizeY number of eNodeBs in a column
63 * @param sourceCellId the cell ID of the eNodeB which the UE will be
64 * initially attached to in the beginning of simulation,
65 * and also the eNodeB which will "shutdown" in the
66 * middle of simulation
67 * @param targetCellId the cell ID of the expected eNodeB where the UE will
68 * perform handover to after the "shutdown" of the source
69 * cell
70 * @param handoverAlgorithmType the type of handover algorithm to be used in
71 * all eNodeBs
72 */
73 LteHandoverTargetTestCase(std::string name,
74 Vector uePosition,
75 uint8_t gridSizeX,
76 uint8_t gridSizeY,
77 uint16_t sourceCellId,
78 uint16_t targetCellId,
79 std::string handoverAlgorithmType);
80
82
83 /**
84 * @brief Triggers when an eNodeB starts a handover and then verifies that
85 * the handover has the right source and target cells.
86 *
87 * The trigger is set up beforehand by connecting to the
88 * `LteEnbRrc::HandoverStart` trace source.
89 *
90 * @param context the context string
91 * @param imsi the IMSI
92 * @param sourceCellId the source cell ID
93 * @param rnti the RNTI
94 * @param targetCellId the target cell ID
95 */
96 void HandoverStartCallback(std::string context,
97 uint64_t imsi,
98 uint16_t sourceCellId,
99 uint16_t rnti,
100 uint16_t targetCellId);
101
102 /**
103 * @brief A trigger that can be scheduled to "shutdown" the cell pointed by
104 * `m_sourceCellId` by reducing its power to 1 dB.
105 */
107
108 private:
109 /**
110 * @brief Run a simulation of a micro-cell network using the parameters
111 * provided to the constructor function.
112 */
113 void DoRun() override;
114
115 /**
116 * @brief Called at the end of simulation and verifies that a handover has
117 * occurred in the simulation.
118 */
119 void DoTeardown() override;
120
121 // simulation parameters
122 Vector m_uePosition; ///< UE positions
123 uint8_t m_gridSizeX; ///< X grid size
124 uint8_t m_gridSizeY; ///< Y grid size
125 uint16_t m_sourceCellId; ///< source cell ID
126 uint16_t m_targetCellId; ///< target cell ID
127 std::string m_handoverAlgorithmType; ///< handover algorithm type
128
129 Ptr<LteEnbNetDevice> m_sourceEnbDev; ///< source ENB device
130 bool m_hasHandoverOccurred; ///< has handover occurred?
131
132}; // end of class LteHandoverTargetTestCase
133
135 Vector uePosition,
136 uint8_t gridSizeX,
137 uint8_t gridSizeY,
138 uint16_t sourceCellId,
139 uint16_t targetCellId,
140 std::string handoverAlgorithmType)
141 : TestCase(name),
142 m_uePosition(uePosition),
143 m_gridSizeX(gridSizeX),
144 m_gridSizeY(gridSizeY),
145 m_sourceCellId(sourceCellId),
146 m_targetCellId(targetCellId),
147 m_handoverAlgorithmType(handoverAlgorithmType),
148 m_sourceEnbDev(nullptr),
149 m_hasHandoverOccurred(false)
150{
151 NS_LOG_INFO(this << " name=" << name);
152
153 // SANITY CHECK
154
155 uint16_t nEnb = gridSizeX * gridSizeY;
156
157 if (sourceCellId > nEnb)
158 {
159 NS_FATAL_ERROR("Invalid source cell ID " << sourceCellId);
160 }
161
162 if (targetCellId > nEnb)
163 {
164 NS_FATAL_ERROR("Invalid target cell ID " << targetCellId);
165 }
166}
167
172
173void
175 uint64_t imsi,
176 uint16_t sourceCellId,
177 uint16_t rnti,
178 uint16_t targetCellId)
179{
180 NS_LOG_FUNCTION(this << context << imsi << sourceCellId << rnti << targetCellId);
181
182 uint64_t timeNowMs = Simulator::Now().GetMilliSeconds();
183 NS_TEST_ASSERT_MSG_GT(timeNowMs, 500, "Handover occurred but too early");
184 NS_TEST_ASSERT_MSG_EQ(sourceCellId,
186 "Handover occurred but with wrong source cell");
187 NS_TEST_ASSERT_MSG_EQ(targetCellId,
189 "Handover occurred but with wrong target cell");
191}
192
193void
195{
196 NS_LOG_FUNCTION(this);
197
198 if (m_sourceEnbDev)
199 {
200 // set the Tx power to 1 dBm
201 NS_ASSERT(m_sourceEnbDev->GetCellId() == m_sourceCellId);
202 NS_LOG_INFO("Shutting down cell " << m_sourceCellId);
203 Ptr<LteEnbPhy> phy = m_sourceEnbDev->GetPhy();
204 phy->SetTxPower(1);
205 }
206}
207
208void
210{
211 NS_LOG_INFO(this << " " << GetName());
212
213 Config::SetDefault("ns3::LteEnbPhy::TxPower", DoubleValue(38)); // micro cell
214 Config::SetDefault("ns3::LteSpectrumPhy::CtrlErrorModelEnabled",
215 BooleanValue(false)); // disable control channel error model
216
219 lteHelper->SetEpcHelper(epcHelper);
220 lteHelper->SetAttribute("PathlossModel", StringValue("ns3::FriisSpectrumPropagationLossModel"));
221 lteHelper->SetAttribute("UseIdealRrc", BooleanValue(true));
222
223 if (m_handoverAlgorithmType == "ns3::A2A4RsrqHandoverAlgorithm")
224 {
225 lteHelper->SetHandoverAlgorithmType("ns3::A2A4RsrqHandoverAlgorithm");
226 lteHelper->SetHandoverAlgorithmAttribute("ServingCellThreshold", UintegerValue(30));
227 lteHelper->SetHandoverAlgorithmAttribute("NeighbourCellOffset", UintegerValue(1));
228 }
229 else if (m_handoverAlgorithmType == "ns3::A3RsrpHandoverAlgorithm")
230 {
231 lteHelper->SetHandoverAlgorithmType("ns3::A3RsrpHandoverAlgorithm");
232 lteHelper->SetHandoverAlgorithmAttribute("Hysteresis", DoubleValue(1.5));
233 lteHelper->SetHandoverAlgorithmAttribute("TimeToTrigger", TimeValue(MilliSeconds(128)));
234 }
235 else
236 {
237 NS_FATAL_ERROR("Unknown handover algorithm " << m_handoverAlgorithmType);
238 }
239
240 // Create Nodes: eNodeB and UE
241 NodeContainer enbNodes;
242 NodeContainer ueNodes;
243 enbNodes.Create(m_gridSizeX * m_gridSizeY);
244 ueNodes.Create(1);
245
246 /*
247 * The size of the grid is determined by m_gridSizeX and m_gridSizeY. The
248 * following figure is the topology when m_gridSizeX = 4 and m_gridSizeY = 3.
249 *
250 * 9 -- 10 -- 11 -- 12
251 * | | | |
252 * | | | |
253 * 5 --- 6 --- 7 --- 8
254 * | | | |
255 * | | | |
256 * (0, 0, 0) ---> 1 --- 2 --- 3 --- 4
257 *
258 * The grid starts at (0, 0, 0) point on the bottom left corner. The distance
259 * between two adjacent eNodeBs is 130 m.
260 */
261
262 // Set up eNodeB position
263 MobilityHelper enbMobility;
264 enbMobility.SetPositionAllocator("ns3::GridPositionAllocator",
265 "MinX",
266 DoubleValue(0.0),
267 "MinY",
268 DoubleValue(0.0),
269 "DeltaX",
270 DoubleValue(130.0),
271 "DeltaY",
272 DoubleValue(130.0),
273 "GridWidth",
275 "LayoutType",
276 StringValue("RowFirst"));
277 enbMobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
278 enbMobility.Install(enbNodes);
279
280 // Setup UE position
282 positionAlloc->Add(m_uePosition);
283 MobilityHelper ueMobility;
284 ueMobility.SetPositionAllocator(positionAlloc);
285 ueMobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
286 ueMobility.Install(ueNodes);
287
288 // Create P-GW node
289 Ptr<Node> pgw = epcHelper->GetPgwNode();
290
291 // Create a single RemoteHost
292 NodeContainer remoteHostContainer;
293 remoteHostContainer.Create(1);
294 Ptr<Node> remoteHost = remoteHostContainer.Get(0);
295 InternetStackHelper internet;
296 internet.Install(remoteHostContainer);
297
298 // Create the Internet
300 p2ph.SetDeviceAttribute("DataRate", DataRateValue(DataRate("100Gb/s")));
301 p2ph.SetDeviceAttribute("Mtu", UintegerValue(1500));
302 p2ph.SetChannelAttribute("Delay", TimeValue(Seconds(0.010)));
303 NetDeviceContainer internetDevices = p2ph.Install(pgw, remoteHost);
304 Ipv4AddressHelper ipv4h;
305 ipv4h.SetBase("1.0.0.0", "255.0.0.0");
306 Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign(internetDevices);
307
308 // Routing of the Internet Host (towards the LTE network)
309 Ipv4StaticRoutingHelper ipv4RoutingHelper;
310 Ptr<Ipv4StaticRouting> remoteHostStaticRouting =
311 ipv4RoutingHelper.GetStaticRouting(remoteHost->GetObject<Ipv4>());
312 remoteHostStaticRouting->AddNetworkRouteTo(Ipv4Address("7.0.0.0"), Ipv4Mask("255.0.0.0"), 1);
313
314 // Create Devices and install them in the Nodes (eNB and UE)
315 NetDeviceContainer enbDevs;
316 NetDeviceContainer ueDevs;
317 enbDevs = lteHelper->InstallEnbDevice(enbNodes);
318 ueDevs = lteHelper->InstallUeDevice(ueNodes);
319
320 // Install the IP stack on the UEs
321 internet.Install(ueNodes);
322 Ipv4InterfaceContainer ueIpIfaces;
323 ueIpIfaces = epcHelper->AssignUeIpv4Address(NetDeviceContainer(ueDevs));
324
325 // Assign IP address to UEs
326 for (uint32_t u = 0; u < ueNodes.GetN(); ++u)
327 {
328 Ptr<Node> ueNode = ueNodes.Get(u);
329 // Set the default gateway for the UE
330 Ptr<Ipv4StaticRouting> ueStaticRouting =
331 ipv4RoutingHelper.GetStaticRouting(ueNode->GetObject<Ipv4>());
332 ueStaticRouting->SetDefaultRoute(epcHelper->GetUeDefaultGatewayAddress(), 1);
333 }
334
335 // Add X2 interface
336 lteHelper->AddX2Interface(enbNodes);
337
338 // Connect to trace sources in all eNodeB
339 Config::Connect("/NodeList/*/DeviceList/*/LteEnbRrc/HandoverStart",
341
342 // Get the source eNodeB
343 Ptr<NetDevice> sourceEnb = enbDevs.Get(m_sourceCellId - 1);
344 m_sourceEnbDev = sourceEnb->GetObject<LteEnbNetDevice>();
346 NS_ASSERT(m_sourceEnbDev->GetCellId() == m_sourceCellId);
347
348 // Attach UE to the source eNodeB
349 lteHelper->Attach(ueDevs.Get(0), sourceEnb);
350
351 // Schedule a "shutdown" of the source eNodeB
353
354 // Run simulation
358
359} // end of void LteX2HandoverTargetTestCase::DoRun ()
360
361void
367
368/**
369 * @brief Test suite ``lte-handover-target``, verifying that handover
370 * algorithms are able to select the right target cell.
371 *
372 * Handover algorithm tested in this test suite:
373 * - A2-A4-RSRQ handover algorithm (ns3::A2A4RsrqHandoverAlgorithm)
374 * - Strongest cell handover algorithm (ns3::A3RsrpHandoverAlgorithm)
375 */
377{
378 public:
380};
381
383 : TestSuite("lte-handover-target", Type::SYSTEM)
384{
385 // LogComponentEnable ("LteHandoverTargetTest", LOG_PREFIX_ALL);
386 // LogComponentEnable ("LteHandoverTargetTest", LOG_LEVEL_ALL);
387 // LogComponentEnable ("A2A4RsrqHandoverAlgorithm", LOG_PREFIX_ALL);
388 // LogComponentEnable ("A2A4RsrqHandoverAlgorithm", LOG_LEVEL_ALL);
389 // LogComponentEnable ("A3RsrpHandoverAlgorithm", LOG_PREFIX_ALL);
390 // LogComponentEnable ("A3RsrpHandoverAlgorithm", LOG_LEVEL_ALL);
391
392 /*
393 * 3 --- 4
394 * | |
395 * |o |
396 * 1 --- 2 o = UE
397 */
398 AddTestCase(new LteHandoverTargetTestCase("4 cells and A2-A4-RSRQ algorithm",
399 Vector(20, 40, 0),
400 2,
401 2,
402 1,
403 3,
404 "ns3::A2A4RsrqHandoverAlgorithm"),
405 TestCase::Duration::QUICK);
406 AddTestCase(new LteHandoverTargetTestCase("4 cells and strongest cell algorithm",
407 Vector(20, 40, 0),
408 2,
409 2,
410 1,
411 3,
412 "ns3::A3RsrpHandoverAlgorithm"),
413 TestCase::Duration::QUICK);
414
415 /*
416 * 4 --- 5 --- 6
417 * | |o |
418 * | | |
419 * 1 --- 2 --- 3 o = UE
420 */
421 AddTestCase(new LteHandoverTargetTestCase("6 cells and A2-A4-RSRQ algorithm",
422 Vector(150, 90, 0),
423 3,
424 2,
425 5,
426 2,
427 "ns3::A2A4RsrqHandoverAlgorithm"),
428 TestCase::Duration::EXTENSIVE);
429 AddTestCase(new LteHandoverTargetTestCase("6 cells and strongest cell algorithm",
430 Vector(150, 90, 0),
431 3,
432 2,
433 5,
434 2,
435 "ns3::A3RsrpHandoverAlgorithm"),
436 TestCase::Duration::EXTENSIVE);
437
438} // end of LteHandoverTargetTestSuite ()
439
440/**
441 * @ingroup lte-test
442 * Static variable for test initialization
443 */
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...
AttributeValue implementation for Boolean.
Definition boolean.h:26
Class for representing data rates.
Definition data-rate.h:78
AttributeValue implementation for DataRate.
Definition data-rate.h:285
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
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.
Access to the IPv4 forwarding table, interfaces, and configuration.
Definition ipv4.h:69
holds a vector of std::pair of Ptr<Ipv4> and interface index.
a class to represent an Ipv4 address mask
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.
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.
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.
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)
Smart pointer class similar to boost::intrusive_ptr.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
static void Run()
Run the simulation.
Definition simulator.cc:167
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition simulator.cc:175
Hold variables of type string.
Definition string.h:45
encapsulates test code
Definition test.h:1050
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:292
std::string GetName() const
Definition test.cc:367
A suite of tests to run.
Definition test.h:1267
Type
Type of test.
Definition test.h:1274
int64_t GetMilliSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:397
AttributeValue implementation for Time.
Definition nstime.h:1431
Hold an unsigned integer type.
Definition uinteger.h:34
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
void SetDefault(std::string name, const AttributeValue &value)
Definition config.cc:883
void Connect(std::string path, const CallbackBase &cb)
Definition config.cc:967
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#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:264
static LteHandoverTargetTestSuite g_lteHandoverTargetTestSuiteInstance
Static variable for test initialization.
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
#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:134
#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:864
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1344
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1356
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:684