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 * 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
46using namespace ns3;
47
48NS_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
93
107 void HandoverStartCallback(std::string context,
108 uint64_t imsi,
109 uint16_t sourceCellId,
110 uint16_t rnti,
111 uint16_t targetCellId);
112
118
119 private:
124 void DoRun() override;
125
130 void DoTeardown() override;
131
132 // simulation parameters
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
184void
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");
202}
203
204void
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
219void
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);
306 InternetStackHelper internet;
307 internet.Install(remoteHostContainer);
308
309 // Create the Internet
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
364
365 // Run simulation
369
370} // end of void LteX2HandoverTargetTestCase::DoRun ()
371
372void
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", Type::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::Duration::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::Duration::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::Duration::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::Duration::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...
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Class for representing data rates.
Definition: data-rate.h:89
AttributeValue implementation for DataRate.
Definition: data-rate.h:296
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
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.
Definition: ptr.h:77
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:142
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
static void Run()
Run the simulation.
Definition: simulator.cc:178
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:186
Hold variables of type string.
Definition: string.h:56
encapsulates test code
Definition: test.h:1061
void AddTestCase(TestCase *testCase, Duration duration=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:1268
Type
Type of test.
Definition: test.h:1275
int64_t GetMilliSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:408
AttributeValue implementation for Time.
Definition: nstime.h:1413
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:894
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:978
#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.
#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:145
#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:875
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