A Discrete-Event Network Simulator
API
test-lte-handover-failure.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Magister Solutions (original test-lte-handover-delay.cc)
3  * Copyright (c) 2021 University of Washington (handover failure cases)
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Sachin Nayak <sachinnn@uw.edu>
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/internet-stack-helper.h>
26 #include <ns3/ipv4-address-helper.h>
27 #include <ns3/ipv4-interface-container.h>
28 #include <ns3/ipv4-static-routing-helper.h>
29 #include <ns3/ipv4-static-routing.h>
30 #include <ns3/log.h>
31 #include <ns3/lte-helper.h>
32 #include <ns3/mobility-helper.h>
33 #include <ns3/net-device-container.h>
34 #include <ns3/node-container.h>
35 #include <ns3/nstime.h>
36 #include <ns3/point-to-point-epc-helper.h>
37 #include <ns3/point-to-point-helper.h>
38 #include <ns3/position-allocator.h>
39 #include <ns3/rng-seed-manager.h>
40 #include <ns3/simulator.h>
41 #include <ns3/test.h>
42 
43 using namespace ns3;
44 
45 NS_LOG_COMPONENT_DEFINE("LteHandoverFailureTest");
46 
62 {
63  public:
93  LteHandoverFailureTestCase(std::string name,
94  bool useIdealRrc,
95  Time handoverTime,
96  Time simulationDuration,
97  uint8_t numberOfRaPreambles,
98  uint8_t preambleTransMax,
99  uint8_t raResponseWindowSize,
100  Time handoverJoiningTimeout,
101  Time handoverLeavingTimeout,
102  uint16_t targeteNodeBPosition)
103  : TestCase(name),
104  m_useIdealRrc(useIdealRrc),
105  m_handoverTime(handoverTime),
106  m_simulationDuration(simulationDuration),
107  m_numberOfRaPreambles(numberOfRaPreambles),
108  m_preambleTransMax(preambleTransMax),
109  m_raResponseWindowSize(raResponseWindowSize),
110  m_handoverJoiningTimeout(handoverJoiningTimeout),
111  m_handoverLeavingTimeout(handoverLeavingTimeout),
112  m_targeteNodeBPosition(targeteNodeBPosition),
113  m_hasHandoverFailureOccurred(false)
114  {
115  }
116 
117  private:
122  void DoRun() override;
123 
128  void DoTeardown() override;
129 
138  void UeHandoverStartCallback(std::string context,
139  uint64_t imsi,
140  uint16_t sourceCellId,
141  uint16_t rnti,
142  uint16_t targetCellId);
143 
151  void HandoverFailureMaxRach(std::string context,
152  uint64_t imsi,
153  uint16_t rnti,
154  uint16_t targetCellId);
155 
163  void HandoverFailureNoPreamble(std::string context,
164  uint64_t imsi,
165  uint16_t rnti,
166  uint16_t targetCellId);
167 
175  void HandoverFailureJoining(std::string context,
176  uint64_t imsi,
177  uint16_t rnti,
178  uint16_t targetCellId);
179 
187  void HandoverFailureLeaving(std::string context,
188  uint64_t imsi,
189  uint16_t rnti,
190  uint16_t targetCellId);
191 
203 
204 }; // end of class LteHandoverFailureTestCase
205 
206 void
208 {
209  NS_LOG_INFO(this << " " << GetName());
210  uint32_t previousSeed = RngSeedManager::GetSeed();
211  uint64_t previousRun = RngSeedManager::GetRun();
214 
215  /*
216  * Helpers.
217  */
218  auto epcHelper = CreateObject<PointToPointEpcHelper>();
219 
220  auto lteHelper = CreateObject<LteHelper>();
221  lteHelper->SetEpcHelper(epcHelper);
222 
223  // Set parameters for helpers based on the test case parameters.
224  lteHelper->SetAttribute("UseIdealRrc", BooleanValue(m_useIdealRrc));
225  Config::SetDefault("ns3::LteEnbMac::NumberOfRaPreambles", UintegerValue(m_numberOfRaPreambles));
226  Config::SetDefault("ns3::LteEnbMac::PreambleTransMax", UintegerValue(m_preambleTransMax));
227  Config::SetDefault("ns3::LteEnbMac::RaResponseWindowSize",
228  UintegerValue(m_raResponseWindowSize));
229  Config::SetDefault("ns3::LteEnbRrc::HandoverJoiningTimeoutDuration",
230  TimeValue(m_handoverJoiningTimeout));
231  Config::SetDefault("ns3::LteEnbRrc::HandoverLeavingTimeoutDuration",
232  TimeValue(m_handoverLeavingTimeout));
233 
234  // Set PHY model to drastically decrease with distance.
235  lteHelper->SetPathlossModelType(TypeId::LookupByName("ns3::LogDistancePropagationLossModel"));
236  lteHelper->SetPathlossModelAttribute("Exponent", DoubleValue(3.5));
237  lteHelper->SetPathlossModelAttribute("ReferenceLoss", DoubleValue(35));
238  /*
239  * Physical layer.
240  *
241  * eNodeB 0 UE eNodeB 1
242  *
243  * x ----------------------- x -------------------------- x
244  * 200 m m_targeteNodeBPosition
245  * source target
246  */
247  // Create nodes.
248  NodeContainer enbNodes;
249  enbNodes.Create(2);
250  auto ueNode = CreateObject<Node>();
251 
252  // Setup mobility
253  auto posAlloc = CreateObject<ListPositionAllocator>();
254  posAlloc->Add(Vector(0, 0, 0));
255  posAlloc->Add(Vector(m_targeteNodeBPosition, 0, 0));
256  posAlloc->Add(Vector(200, 0, 0));
257 
258  MobilityHelper mobilityHelper;
259  mobilityHelper.SetMobilityModel("ns3::ConstantPositionMobilityModel");
260  mobilityHelper.SetPositionAllocator(posAlloc);
261  mobilityHelper.Install(enbNodes);
262  mobilityHelper.Install(ueNode);
263 
264  /*
265  * Link layer.
266  */
267  auto enbDevs = lteHelper->InstallEnbDevice(enbNodes);
268  auto ueDev = lteHelper->InstallUeDevice(ueNode).Get(0);
269 
270  /*
271  * Network layer.
272  */
273  InternetStackHelper inetStackHelper;
274  inetStackHelper.Install(ueNode);
276  ueIfs = epcHelper->AssignUeIpv4Address(ueDev);
277 
278  // Setup traces.
279  Config::Connect("/NodeList/*/DeviceList/*/LteUeRrc/HandoverStart",
281  Config::Connect("/NodeList/*/DeviceList/*/LteEnbRrc/HandoverFailureMaxRach",
283  Config::Connect("/NodeList/*/DeviceList/*/LteEnbRrc/HandoverFailureNoPreamble",
285  Config::Connect("/NodeList/*/DeviceList/*/LteEnbRrc/HandoverFailureJoining",
287  Config::Connect("/NodeList/*/DeviceList/*/LteEnbRrc/HandoverFailureLeaving",
289 
290  // Prepare handover.
291  lteHelper->AddX2Interface(enbNodes);
292  lteHelper->Attach(ueDev, enbDevs.Get(0));
293  lteHelper->HandoverRequest(m_handoverTime, ueDev, enbDevs.Get(0), enbDevs.Get(1));
294 
295  // Run simulation.
296  Simulator::Stop(m_simulationDuration);
297  Simulator::Run();
299 
300  RngSeedManager::SetSeed(previousSeed);
301  RngSeedManager::SetRun(previousRun);
302 } // end of void LteHandoverFailureTestCase::DoRun ()
303 
304 void
306  uint64_t imsi,
307  uint16_t sourceCellId,
308  uint16_t rnti,
309  uint16_t targetCellId)
310 {
311  NS_LOG_FUNCTION(this << " " << context << " IMSI-" << imsi << " sourceCellID-" << sourceCellId
312  << " RNTI-" << rnti << " targetCellID-" << targetCellId);
313  NS_LOG_INFO("HANDOVER COMMAND received through at UE "
314  << imsi << " to handover from " << sourceCellId << " to " << targetCellId);
315 }
316 
317 void
319  uint64_t imsi,
320  uint16_t rnti,
321  uint16_t targetCellId)
322 {
323  NS_LOG_FUNCTION(this << context << imsi << rnti << targetCellId);
324  m_hasHandoverFailureOccurred = true;
325 }
326 
327 void
329  uint64_t imsi,
330  uint16_t rnti,
331  uint16_t targetCellId)
332 {
333  NS_LOG_FUNCTION(this << context << imsi << rnti << targetCellId);
334  m_hasHandoverFailureOccurred = true;
335 }
336 
337 void
339  uint64_t imsi,
340  uint16_t rnti,
341  uint16_t targetCellId)
342 {
343  NS_LOG_FUNCTION(this << context << imsi << rnti << targetCellId);
344  m_hasHandoverFailureOccurred = true;
345 }
346 
347 void
349  uint64_t imsi,
350  uint16_t rnti,
351  uint16_t targetCellId)
352 {
353  NS_LOG_FUNCTION(this << context << imsi << rnti << targetCellId);
354  m_hasHandoverFailureOccurred = true;
355 }
356 
357 void
359 {
360  NS_LOG_FUNCTION(this);
361  NS_TEST_ASSERT_MSG_EQ(m_hasHandoverFailureOccurred, true, "Handover failure did not occur");
362 }
363 
373 {
374  public:
376  : TestSuite("lte-handover-failure", TestSuite::SYSTEM)
377  {
378  // Argument sequence for all test cases: useIdealRrc, handoverTime, simulationDuration,
379  // numberOfRaPreambles, preambleTransMax, raResponseWindowSize,
380  // handoverJoiningTimeout, handoverLeavingTimeout
381 
382  // Test cases for REAL RRC protocol
383  AddTestCase(new LteHandoverFailureTestCase("REAL Handover failure due to maximum RACH "
384  "transmissions reached from UE to target eNodeB",
385  false,
386  Seconds(0.200),
387  Seconds(0.300),
388  52,
389  3,
390  3,
391  MilliSeconds(200),
392  MilliSeconds(500),
393  2500),
395  AddTestCase(new LteHandoverFailureTestCase(
396  "REAL Handover failure due to non-allocation of non-contention preamble at "
397  "target eNodeB due to max number reached",
398  false,
399  Seconds(0.100),
400  Seconds(0.200),
401  64,
402  50,
403  3,
404  MilliSeconds(200),
405  MilliSeconds(500),
406  1500),
408  AddTestCase(new LteHandoverFailureTestCase(
409  "REAL Handover failure due to HANDOVER JOINING timeout before reception of "
410  "RRC CONNECTION RECONFIGURATION at source eNodeB",
411  false,
412  Seconds(0.100),
413  Seconds(0.200),
414  52,
415  50,
416  3,
417  MilliSeconds(0),
418  MilliSeconds(500),
419  1500),
421  AddTestCase(new LteHandoverFailureTestCase(
422  "REAL Handover failure due to HANDOVER JOINING timeout before completion "
423  "of non-contention RACH process to target eNodeB",
424  false,
425  Seconds(0.100),
426  Seconds(0.200),
427  52,
428  50,
429  3,
430  MilliSeconds(15),
431  MilliSeconds(500),
432  1500),
434  AddTestCase(new LteHandoverFailureTestCase(
435  "REAL Handover failure due to HANDOVER JOINING timeout before reception of "
436  "RRC CONNECTION RECONFIGURATION COMPLETE at target eNodeB",
437  false,
438  Seconds(0.100),
439  Seconds(0.200),
440  52,
441  50,
442  3,
443  MilliSeconds(18),
444  MilliSeconds(500),
445  500),
447  AddTestCase(new LteHandoverFailureTestCase(
448  "REAL Handover failure due to HANDOVER LEAVING timeout before reception of "
449  "RRC CONNECTION RECONFIGURATION at source eNodeB",
450  false,
451  Seconds(0.100),
452  Seconds(0.200),
453  52,
454  50,
455  3,
456  MilliSeconds(200),
457  MilliSeconds(0),
458  1500),
460  AddTestCase(new LteHandoverFailureTestCase(
461  "REAL Handover failure due to HANDOVER LEAVING timeout before completion "
462  "of non-contention RACH process to target eNodeB",
463  false,
464  Seconds(0.100),
465  Seconds(0.200),
466  52,
467  50,
468  3,
469  MilliSeconds(200),
470  MilliSeconds(15),
471  1500),
473  AddTestCase(new LteHandoverFailureTestCase(
474  "REAL Handover failure due to HANDOVER LEAVING timeout before reception of "
475  "RRC CONNECTION RECONFIGURATION COMPLETE at target eNodeB",
476  false,
477  Seconds(0.100),
478  Seconds(0.200),
479  52,
480  50,
481  3,
482  MilliSeconds(200),
483  MilliSeconds(18),
484  500),
486 
487  // Test cases for IDEAL RRC protocol
488  AddTestCase(new LteHandoverFailureTestCase("IDEAL Handover failure due to maximum RACH "
489  "transmissions reached from UE to target eNodeB",
490  true,
491  Seconds(0.100),
492  Seconds(0.200),
493  52,
494  3,
495  3,
496  MilliSeconds(200),
497  MilliSeconds(500),
498  1500),
500  AddTestCase(new LteHandoverFailureTestCase(
501  "IDEAL Handover failure due to non-allocation of non-contention preamble "
502  "at target eNodeB due to max number reached",
503  true,
504  Seconds(0.100),
505  Seconds(0.200),
506  64,
507  50,
508  3,
509  MilliSeconds(200),
510  MilliSeconds(500),
511  1500),
513  AddTestCase(new LteHandoverFailureTestCase(
514  "IDEAL Handover failure due to HANDOVER JOINING timeout before reception "
515  "of RRC CONNECTION RECONFIGURATION at source eNodeB",
516  true,
517  Seconds(0.100),
518  Seconds(0.200),
519  52,
520  50,
521  3,
522  MilliSeconds(0),
523  MilliSeconds(500),
524  1500),
526  AddTestCase(new LteHandoverFailureTestCase(
527  "IDEAL Handover failure due to HANDOVER JOINING timeout before completion "
528  "of non-contention RACH process to target eNodeB",
529  true,
530  Seconds(0.100),
531  Seconds(0.200),
532  52,
533  50,
534  3,
535  MilliSeconds(10),
536  MilliSeconds(500),
537  1500),
539  AddTestCase(new LteHandoverFailureTestCase(
540  "IDEAL Handover failure due to HANDOVER JOINING timeout before reception "
541  "of RRC CONNECTION RECONFIGURATION COMPLETE at target eNodeB",
542  true,
543  Seconds(0.100),
544  Seconds(0.200),
545  52,
546  50,
547  3,
548  MilliSeconds(4),
549  MilliSeconds(500),
550  500),
552  AddTestCase(new LteHandoverFailureTestCase(
553  "IDEAL Handover failure due to HANDOVER LEAVING timeout before reception "
554  "of RRC CONNECTION RECONFIGURATION at source eNodeB",
555  true,
556  Seconds(0.100),
557  Seconds(0.200),
558  52,
559  50,
560  3,
561  MilliSeconds(500),
562  MilliSeconds(0),
563  1500),
565  AddTestCase(new LteHandoverFailureTestCase(
566  "IDEAL Handover failure due to HANDOVER LEAVING timeout before completion "
567  "of non-contention RACH process to target eNodeB",
568  true,
569  Seconds(0.100),
570  Seconds(0.200),
571  52,
572  50,
573  3,
574  MilliSeconds(500),
575  MilliSeconds(10),
576  1500),
578  AddTestCase(new LteHandoverFailureTestCase(
579  "IDEAL Handover failure due to HANDOVER LEAVING timeout before reception "
580  "of RRC CONNECTION RECONFIGURATION COMPLETE at target eNodeB",
581  true,
582  Seconds(0.100),
583  Seconds(0.200),
584  52,
585  50,
586  3,
587  MilliSeconds(500),
588  MilliSeconds(4),
589  500),
591  }
Verifying that a handover failure occurs due to various causes.
LteHandoverFailureTestCase(std::string name, bool useIdealRrc, Time handoverTime, Time simulationDuration, uint8_t numberOfRaPreambles, uint8_t preambleTransMax, uint8_t raResponseWindowSize, Time handoverJoiningTimeout, Time handoverLeavingTimeout, uint16_t targeteNodeBPosition)
Constructor.
Time m_handoverJoiningTimeout
handover joining timeout duration at target eNodeB
Time m_handoverLeavingTimeout
handover leaving timeout duration at source eNodeB
uint8_t m_preambleTransMax
max number of RACH preambles possible from UE to eNodeB
uint8_t m_numberOfRaPreambles
number of random access preambles for contention based RACH process
void HandoverFailureMaxRach(std::string context, uint64_t imsi, uint16_t rnti, uint16_t targetCellId)
Handover failure callback due to maximum RACH transmissions reached from UE to target eNodeB.
void DoRun() override
Run a simulation of a two eNodeB network using the parameters provided to the constructor function.
uint16_t m_targeteNodeBPosition
position of the target eNodeB
void HandoverFailureJoining(std::string context, uint64_t imsi, uint16_t rnti, uint16_t targetCellId)
Handover failure callback due to handover joining timeout at target eNodeB.
void HandoverFailureNoPreamble(std::string context, uint64_t imsi, uint16_t rnti, uint16_t targetCellId)
Handover failure callback due to non-allocation of non-contention preamble at target eNodeB.
void HandoverFailureLeaving(std::string context, uint64_t imsi, uint16_t rnti, uint16_t targetCellId)
Handover failure callback due to handover leaving timeout at source eNodeB.
bool m_hasHandoverFailureOccurred
has handover failure occurred in simulation
void UeHandoverStartCallback(std::string context, uint64_t imsi, uint16_t sourceCellId, uint16_t rnti, uint16_t targetCellId)
UE handover start callback function to indicate start of handover.
void DoTeardown() override
Called at the end of simulation and verifies that a handover and a handover failure has occurred in t...
uint8_t m_raResponseWindowSize
window length for reception of RAR
Time m_simulationDuration
the simulation duration
The following log components can be used to debug this test's behavior: LteHandoverFailureTest:LteEnb...
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.
void Install(std::string nodeName) const
Aggregate implementations of the ns3::Ipv4, ns3::Ipv6, ns3::Udp, and ns3::Tcp classes onto the provid...
holds a vector of std::pair of Ptr<Ipv4> and interface index.
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...
keep track of a set of node pointers.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
static void SetRun(uint64_t run)
Set the run number of simulation.
static void SetSeed(uint32_t seed)
Set the seed.
static uint64_t GetRun()
Get the current run number.
static uint32_t GetSeed()
Get the current seed value which will be used by all subsequently instantiated RandomVariableStream o...
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:142
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
encapsulates test code
Definition: test.h:1060
@ QUICK
Fast test.
Definition: test.h:1065
A suite of tests to run.
Definition: test.h:1256
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:835
Hold an unsigned integer type.
Definition: uinteger.h:45
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_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
LteHandoverFailureTestSuite g_lteHandoverFailureTestSuite
end of LteHandoverFailureTestSuite ()
#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
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