A Discrete-Event Network Simulator
API
lte-test-ue-measurements.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
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: Manuel Requena <manuel.requena@cttc.es>
18  * Nicola Baldo <nbaldo@cttc.es>
19  * Marco Miozzo <mmiozzo@cttc.es>
20  * Budiarto Herman <budiarto.herman@magister.fi>
21  */
22 
24 
25 #include <ns3/boolean.h>
26 #include <ns3/callback.h>
27 #include <ns3/config.h>
28 #include <ns3/double.h>
29 #include <ns3/enum.h>
30 #include <ns3/ff-mac-scheduler.h>
31 #include <ns3/internet-stack-helper.h>
32 #include <ns3/ipv4-address-helper.h>
33 #include <ns3/ipv4-interface-container.h>
34 #include <ns3/ipv4-static-routing-helper.h>
35 #include <ns3/log.h>
36 #include <ns3/lte-common.h>
37 #include <ns3/lte-enb-net-device.h>
38 #include <ns3/lte-enb-phy.h>
39 #include <ns3/lte-enb-rrc.h>
40 #include <ns3/lte-helper.h>
41 #include <ns3/lte-ue-net-device.h>
42 #include <ns3/lte-ue-phy.h>
43 #include <ns3/lte-ue-rrc.h>
44 #include <ns3/mobility-helper.h>
45 #include <ns3/net-device-container.h>
46 #include <ns3/node-container.h>
47 #include <ns3/point-to-point-epc-helper.h>
48 #include <ns3/point-to-point-helper.h>
49 #include <ns3/simulator.h>
50 #include <ns3/string.h>
51 
52 using namespace ns3;
53 
54 NS_LOG_COMPONENT_DEFINE("LteUeMeasurementsTest");
55 
56 // ===== LTE-UE-MEASUREMENTS TEST SUITE ==================================== //
57 
58 void
60  std::string path,
61  uint16_t rnti,
62  uint16_t cellId,
63  double rsrp,
64  double rsrq,
65  bool servingCell,
66  uint8_t componentCarrierId)
67 {
68  testcase->ReportUeMeasurements(rnti, cellId, rsrp, rsrq, servingCell);
69 }
70 
71 void
73  std::string path,
74  uint64_t imsi,
75  uint16_t cellId,
76  uint16_t rnti,
78 {
79  testcase->RecvMeasurementReport(imsi, cellId, rnti, meas);
80 }
81 
82 /*
83  * Test Suite
84  */
85 
87  : TestSuite("lte-ue-measurements", SYSTEM)
88 {
89  AddTestCase(new LteUeMeasurementsTestCase("d1=10, d2=10000",
90  10.000000,
91  10000.000000,
92  -53.739702,
93  -113.739702,
94  -3.010305,
95  -63.010305),
96  TestCase::EXTENSIVE);
97  AddTestCase(new LteUeMeasurementsTestCase("d1=20, d2=10000",
98  20.000000,
99  10000.000000,
100  -59.760302,
101  -113.739702,
102  -3.010319,
103  -56.989719),
104  TestCase::EXTENSIVE);
105  AddTestCase(new LteUeMeasurementsTestCase("d1=50, d2=10000",
106  50.000000,
107  10000.000000,
108  -67.719102,
109  -113.739702,
110  -3.010421,
111  -49.031021),
112  TestCase::EXTENSIVE);
113  AddTestCase(new LteUeMeasurementsTestCase("d1=100, d2=10000",
114  100.000000,
115  10000.000000,
116  -73.739702,
117  -113.739702,
118  -3.010783,
119  -43.010783),
120  TestCase::EXTENSIVE);
121  AddTestCase(new LteUeMeasurementsTestCase("d1=200, d2=10000",
122  200.000000,
123  10000.000000,
124  -79.760302,
125  -113.739702,
126  -3.012232,
127  -36.991632),
128  TestCase::EXTENSIVE);
129  AddTestCase(new LteUeMeasurementsTestCase("d1=100, d2=10000",
130  100.000000,
131  10000.000000,
132  -73.739702,
133  -113.739702,
134  -3.010783,
135  -43.010783),
136  TestCase::EXTENSIVE);
137  AddTestCase(new LteUeMeasurementsTestCase("d1=200, d2=10000",
138  200.000000,
139  10000.000000,
140  -79.760302,
141  -113.739702,
142  -3.012232,
143  -36.991632),
144  TestCase::EXTENSIVE);
145  AddTestCase(new LteUeMeasurementsTestCase("d1=500, d2=10000",
146  500.000000,
147  10000.000000,
148  -87.719102,
149  -113.739702,
150  -3.022359,
151  -29.042959),
152  TestCase::EXTENSIVE);
153  AddTestCase(new LteUeMeasurementsTestCase("d1=1000, d2=10000",
154  1000.000000,
155  10000.000000,
156  -93.739702,
157  -113.739702,
158  -3.058336,
159  -23.058336),
160  TestCase::EXTENSIVE);
161  AddTestCase(new LteUeMeasurementsTestCase("d1=2000, d2=10000",
162  2000.000000,
163  10000.000000,
164  -99.760302,
165  -113.739702,
166  -3.199337,
167  -17.178738),
168  TestCase::EXTENSIVE);
169  AddTestCase(new LteUeMeasurementsTestCase("d1=5000, d2=10000",
170  5000.000000,
171  10000.000000,
172  -107.719102,
173  -113.739702,
174  -4.075793,
175  -10.096393),
176  TestCase::QUICK);
177  AddTestCase(new LteUeMeasurementsTestCase("d1=10000, d2=10000",
178  10000.000000,
179  10000.000000,
180  -113.739702,
181  -113.739702,
182  -6.257687,
183  -6.257687),
184  TestCase::EXTENSIVE);
185  AddTestCase(new LteUeMeasurementsTestCase("d1=20000, d2=10000",
186  20000.000000,
187  10000.000000,
188  -119.760302,
189  -113.739702,
190  -10.373365,
191  -4.352765),
192  TestCase::EXTENSIVE);
193  AddTestCase(new LteUeMeasurementsTestCase("d1=50000, d2=10000",
194  50000.000000,
195  10000.000000,
196  -127.719102,
197  -113.739702,
198  -17.605046,
199  -3.625645),
200  TestCase::EXTENSIVE);
201  AddTestCase(new LteUeMeasurementsTestCase("d1=100000, d2=10000",
202  100000.000000,
203  10000.000000,
204  -133.739702,
205  -113.739702,
206  -23.511071,
207  -3.511071),
208  TestCase::EXTENSIVE);
209  AddTestCase(new LteUeMeasurementsTestCase("d1=200000, d2=10000",
210  200000.000000,
211  10000.000000,
212  -139.760302,
213  -113.739702,
214  -29.502549,
215  -3.481949),
216  TestCase::EXTENSIVE);
217  AddTestCase(new LteUeMeasurementsTestCase("d1=500000, d2=10000",
218  500000.000000,
219  10000.000000,
220  -147.719102,
221  -113.739702,
222  -37.453160,
223  -3.473760),
224  TestCase::EXTENSIVE);
225  AddTestCase(new LteUeMeasurementsTestCase("d1=1000000, d2=10000",
226  1000000.000000,
227  10000.000000,
228  -153.739702,
229  -113.739702,
230  -43.472589,
231  -3.472589),
232  TestCase::EXTENSIVE);
233 }
234 
240 
241 /*
242  * Test Case
243  */
244 
246  double d1,
247  double d2,
248  double rsrpDbmUe1,
249  double rsrpDbmUe2,
250  double rsrqDbUe1,
251  double rsrqDbUe2)
252  : TestCase(name),
253  m_d1(d1),
254  m_d2(d2),
255  m_rsrpDbmUeServingCell(rsrpDbmUe1),
256  m_rsrpDbmUeNeighborCell(rsrpDbmUe2),
257  m_rsrqDbUeServingCell(rsrqDbUe1),
258  m_rsrqDbUeNeighborCell(rsrqDbUe2)
259 {
260  NS_LOG_INFO("Test UE Measurements d1 = " << d1 << " m. and d2 = " << d2 << " m.");
261 }
262 
264 {
265 }
266 
267 void
269 {
270  NS_LOG_INFO(this << " " << GetName());
271 
272  Config::SetDefault("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue(false));
273  Config::SetDefault("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue(false));
274  Config::SetDefault("ns3::LteAmc::AmcModel", EnumValue(LteAmc::PiroEW2010));
275  Config::SetDefault("ns3::LteAmc::Ber", DoubleValue(0.00005));
276  Ptr<LteHelper> lteHelper = CreateObject<LteHelper>();
277  lteHelper->SetAttribute("PathlossModel", StringValue("ns3::FriisSpectrumPropagationLossModel"));
278  lteHelper->SetAttribute("UseIdealRrc", BooleanValue(false));
279 
280  // Disable Uplink Power Control
281  Config::SetDefault("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue(false));
282 
283  // LogComponentEnable ("LteUeMeasurementsTest", LOG_LEVEL_ALL);
284 
285  // Create Nodes: eNodeB and UE
286  NodeContainer enbNodes;
287  NodeContainer ueNodes1;
288  NodeContainer ueNodes2;
289  enbNodes.Create(2);
290  ueNodes1.Create(1);
291  ueNodes2.Create(1);
292  NodeContainer allNodes = NodeContainer(enbNodes, ueNodes1, ueNodes2);
293 
294  // the topology is the following:
295  // d2
296  // UE1-----------eNB2
297  // | |
298  // d1| |d1
299  // | d2 |
300  // eNB1----------UE2
301  //
302  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
303  positionAlloc->Add(Vector(0.0, 0.0, 0.0)); // eNB1
304  positionAlloc->Add(Vector(m_d2, m_d1, 0.0)); // eNB2
305  positionAlloc->Add(Vector(0.0, m_d1, 0.0)); // UE1
306  positionAlloc->Add(Vector(m_d2, 0.0, 0.0)); // UE2
308  mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
309  mobility.SetPositionAllocator(positionAlloc);
310  mobility.Install(allNodes);
311 
312  // Create Devices and install them in the Nodes (eNB and UE)
313  NetDeviceContainer enbDevs;
314  NetDeviceContainer ueDevs1;
315  NetDeviceContainer ueDevs2;
316  lteHelper->SetSchedulerType("ns3::RrFfMacScheduler");
317  lteHelper->SetSchedulerAttribute("UlCqiFilter", EnumValue(FfMacScheduler::PUSCH_UL_CQI));
318  enbDevs = lteHelper->InstallEnbDevice(enbNodes);
319  ueDevs1 = lteHelper->InstallUeDevice(ueNodes1);
320  ueDevs2 = lteHelper->InstallUeDevice(ueNodes2);
321 
322  // Attach UEs to eNodeBs
323  lteHelper->Attach(ueDevs1, enbDevs.Get(0));
324  lteHelper->Attach(ueDevs2, enbDevs.Get(1));
325 
326  // Activate an EPS bearer
327  enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
328  EpsBearer bearer(q);
329  lteHelper->ActivateDataRadioBearer(ueDevs1, bearer);
330  lteHelper->ActivateDataRadioBearer(ueDevs2, bearer);
331 
333  "/NodeList/2/DeviceList/0/ComponentCarrierMapUe/0/LteUePhy/ReportUeMeasurements",
335  Config::Connect("/NodeList/0/DeviceList/0/LteEnbRrc/RecvMeasurementReport",
337 
339  "/NodeList/3/DeviceList/0/ComponentCarrierMapUe/0/LteUePhy/ReportUeMeasurements",
341  Config::Connect("/NodeList/1/DeviceList/0/LteEnbRrc/RecvMeasurementReport",
343 
344  // need to allow for RRC connection establishment + SRS
345  Simulator::Stop(Seconds(0.800));
346  Simulator::Run();
347 
348  Simulator::Destroy();
349 }
350 
351 void
353  uint16_t cellId,
354  double rsrp,
355  double rsrq,
356  bool servingCell)
357 {
358  // need to allow for RRC connection establishment + CQI feedback reception + UE measurements
359  // filtering (200 ms)
360  if (Simulator::Now() > MilliSeconds(400))
361  {
362  if (servingCell)
363  {
364  NS_LOG_DEBUG("UE serving cellId " << cellId << " Rxed RSRP " << rsrp << " thr "
365  << m_rsrpDbmUeServingCell << " RSRQ " << rsrq
366  << " thr " << m_rsrqDbUeServingCell);
367  NS_TEST_ASSERT_MSG_EQ_TOL(m_rsrpDbmUeServingCell, rsrp, 0.2, "Wrong RSRP UE 1");
368  NS_TEST_ASSERT_MSG_EQ_TOL(m_rsrqDbUeServingCell, rsrq, 0.2, "Wrong RSRQ UE 1");
369  }
370  else
371  {
372  NS_LOG_DEBUG("UE neighbor cellId " << cellId << " Rxed RSRP " << rsrp << " thr "
373  << m_rsrpDbmUeNeighborCell << " RSRQ " << rsrq
374  << " thr " << m_rsrqDbUeNeighborCell);
375  NS_TEST_ASSERT_MSG_EQ_TOL(m_rsrpDbmUeNeighborCell, rsrp, 0.2, "Wrong RSRP UE 2");
376  NS_TEST_ASSERT_MSG_EQ_TOL(m_rsrqDbUeNeighborCell, rsrq, 0.2, "Wrong RSRQ UE ");
377  }
378  }
379 }
380 
381 void
383  uint16_t cellId,
384  uint16_t rnti,
386 {
387  // need to allow for RRC connection establishment + CQI feedback reception + UE measurements
388  // filtering (200 ms)
389  if (Simulator::Now() > MilliSeconds(400))
390  {
391  if (cellId == imsi)
392  {
393  NS_LOG_DEBUG(
394  this << "Serving Cell: received IMSI " << imsi << " CellId " << cellId << " RNTI "
395  << rnti << " thr "
396  << (uint16_t)EutranMeasurementMapping::Dbm2RsrpRange(m_rsrpDbmUeServingCell)
397  << " RSRP " << (uint16_t)meas.measResults.measResultPCell.rsrpResult
398  << " RSRQ " << (uint16_t)meas.measResults.measResultPCell.rsrqResult << " thr "
399  << (uint16_t)EutranMeasurementMapping::Db2RsrqRange(m_rsrqDbUeServingCell));
401  EutranMeasurementMapping::Dbm2RsrpRange(m_rsrpDbmUeServingCell),
402  "Wrong RSRP ");
404  EutranMeasurementMapping::Db2RsrqRange(m_rsrqDbUeServingCell),
405  "Wrong RSRQ ");
406  }
407  else
408  {
409  NS_LOG_DEBUG(
410  this << "Neighbor cell: received IMSI " << imsi << " CellId " << cellId << " RNTI "
411  << rnti << " thr "
412  << (uint16_t)EutranMeasurementMapping::Dbm2RsrpRange(m_rsrpDbmUeNeighborCell)
413  << " RSRP " << (uint16_t)meas.measResults.measResultPCell.rsrpResult
414  << " RSRQ " << (uint16_t)meas.measResults.measResultPCell.rsrqResult << " thr "
415  << (uint16_t)EutranMeasurementMapping::Db2RsrqRange(m_rsrqDbUeNeighborCell));
417  EutranMeasurementMapping::Dbm2RsrpRange(m_rsrpDbmUeNeighborCell),
418  "Wrong RSRP ");
420  EutranMeasurementMapping::Db2RsrqRange(m_rsrqDbUeNeighborCell),
421  "Wrong RSRQ ");
422  }
423  }
424 }
425 
426 // ===== LTE-UE-MEASUREMENTS-PIECEWISE-1 TEST SUITE ======================== //
427 
428 /*
429  * Overloaded operators, for the convenience of defining test cases
430  */
431 
432 std::vector<Time>&
433 operator<<(std::vector<Time>& v, const uint64_t& ms)
434 {
435  /*
436  * Prior attempt to use seconds as unit of choice resulted in precision lost.
437  * Therefore milliseconds are used now instead.
438  */
439  v.push_back(MilliSeconds(ms) + UE_MEASUREMENT_REPORT_DELAY);
440  return v;
441 }
442 
443 std::vector<uint8_t>&
444 operator<<(std::vector<uint8_t>& v, const uint8_t& range)
445 {
446  v.push_back(range);
447  return v;
448 }
449 
450 /*
451  * Test Suite
452  */
453 
455  : TestSuite("lte-ue-measurements-piecewise-1", SYSTEM)
456 {
457  std::vector<Time> expectedTime;
458  std::vector<uint8_t> expectedRsrp;
459 
460  // === Event A1 (serving cell becomes better than threshold) ===
461 
462  // With very low threshold
464  config.triggerType = LteRrcSap::ReportConfigEutra::EVENT;
465  config.eventId = LteRrcSap::ReportConfigEutra::EVENT_A1;
466  config.threshold1.choice = LteRrcSap::ThresholdEutra::THRESHOLD_RSRP;
467  config.threshold1.range = 0;
468  config.triggerQuantity = LteRrcSap::ReportConfigEutra::RSRP;
469  config.reportInterval = LteRrcSap::ReportConfigEutra::MS120;
470  expectedTime.clear();
471  expectedTime << 200 << 320 << 440 << 560 << 680 << 800 << 920 << 1040 << 1160 << 1280 << 1400
472  << 1520 << 1640 << 1760 << 1880 << 2000 << 2120;
473  expectedRsrp.clear();
474  expectedRsrp << 67 << 67 << 57 << 57 << 66 << 47 << 47 << 66 << 66 << 57 << 51 << 51 << 47 << 47
475  << 51 << 57 << 57;
477  "Piecewise test case 1 - Event A1 with very low threshold",
478  config,
479  expectedTime,
480  expectedRsrp),
481  TestCase::EXTENSIVE);
482 
483  // With normal threshold
484  config.threshold1.range = 54;
485  expectedTime.clear();
486  expectedTime << 200 << 320 << 440 << 560 << 680 << 1000 << 1120 << 1240 << 1360 << 2000 << 2120;
487  expectedRsrp.clear();
488  expectedRsrp << 67 << 67 << 57 << 57 << 66 << 66 << 66 << 57 << 57 << 57 << 57;
490  "Piecewise test case 1 - Event A1 with normal threshold",
491  config,
492  expectedTime,
493  expectedRsrp),
494  TestCase::EXTENSIVE);
495 
496  // With short time-to-trigger
497  config.timeToTrigger = 64;
498  expectedTime.clear();
499  expectedTime << 264 << 384 << 504 << 624 << 744 << 1064 << 1184 << 1304 << 1424 << 2064 << 2184;
500  expectedRsrp.clear();
501  expectedRsrp << 67 << 67 << 57 << 66 << 66 << 66 << 66 << 57 << 51 << 57 << 57;
503  "Piecewise test case 1 - Event A1 with short time-to-trigger",
504  config,
505  expectedTime,
506  expectedRsrp),
507  TestCase::QUICK);
508 
509  // With long time-to-trigger
510  config.timeToTrigger = 128;
511  expectedTime.clear();
512  expectedTime << 328 << 448 << 568 << 688 << 808 << 1128 << 1248 << 1368 << 1488 << 2128;
513  expectedRsrp.clear();
514  expectedRsrp << 67 << 57 << 57 << 66 << 47 << 66 << 57 << 57 << 51 << 57;
516  "Piecewise test case 1 - Event A1 with long time-to-trigger",
517  config,
518  expectedTime,
519  expectedRsrp),
520  TestCase::EXTENSIVE);
521 
522  // With super time-to-trigger
523  config.timeToTrigger = 256;
524  expectedTime.clear();
525  expectedTime << 456 << 576 << 696 << 816 << 936 << 1056 << 1176 << 1296 << 1416 << 1536;
526  expectedRsrp.clear();
527  expectedRsrp << 57 << 57 << 66 << 47 << 47 << 66 << 66 << 57 << 51 << 51;
529  "Piecewise test case 1 - Event A1 with super time-to-trigger",
530  config,
531  expectedTime,
532  expectedRsrp),
533  TestCase::EXTENSIVE);
534 
535  // With hysteresis
536  config.hysteresis = 8;
537  config.timeToTrigger = 0;
538  expectedTime.clear();
539  expectedTime << 200 << 320 << 440 << 560 << 680 << 1000 << 1120 << 1240 << 1360 << 1480 << 2200;
540  expectedRsrp.clear();
541  expectedRsrp << 67 << 67 << 57 << 57 << 66 << 66 << 66 << 57 << 57 << 51 << 67;
542  AddTestCase(
543  new LteUeMeasurementsPiecewiseTestCase1("Piecewise test case 1 - Event A1 with hysteresis",
544  config,
545  expectedTime,
546  expectedRsrp),
547  TestCase::QUICK);
548 
549  // With very high threshold
550  config.threshold1.range = 97;
551  config.hysteresis = 0;
552  expectedTime.clear();
553  expectedRsrp.clear();
555  "Piecewise test case 1 - Event A1 with very high threshold",
556  config,
557  expectedTime,
558  expectedRsrp),
559  TestCase::TAKES_FOREVER);
560 
561  // === Event A2 (serving cell becomes worse than threshold) ===
562 
563  // With very low threshold
564  config.eventId = LteRrcSap::ReportConfigEutra::EVENT_A2;
565  config.threshold1.range = 0;
566  expectedTime.clear();
567  expectedRsrp.clear();
569  "Piecewise test case 1 - Event A2 with very low threshold",
570  config,
571  expectedTime,
572  expectedRsrp),
573  TestCase::TAKES_FOREVER);
574 
575  // With normal threshold
576  config.threshold1.range = 54;
577  expectedTime.clear();
578  expectedTime << 800 << 920 << 1400 << 1520 << 1640 << 1760 << 1880;
579  expectedRsrp.clear();
580  expectedRsrp << 47 << 47 << 51 << 51 << 47 << 47 << 51;
582  "Piecewise test case 1 - Event A2 with normal threshold",
583  config,
584  expectedTime,
585  expectedRsrp),
586  TestCase::QUICK);
587 
588  // With short time-to-trigger
589  config.timeToTrigger = 64;
590  expectedTime.clear();
591  expectedTime << 864 << 984 << 1464 << 1584 << 1704 << 1824 << 1944;
592  expectedRsrp.clear();
593  expectedRsrp << 47 << 47 << 51 << 51 << 47 << 51 << 51;
595  "Piecewise test case 1 - Event A2 with short time-to-trigger",
596  config,
597  expectedTime,
598  expectedRsrp),
599  TestCase::EXTENSIVE);
600 
601  // With long time-to-trigger
602  config.timeToTrigger = 128;
603  expectedTime.clear();
604  expectedTime << 928 << 1048 << 1528 << 1648 << 1768 << 1888 << 2008;
605  expectedRsrp.clear();
606  expectedRsrp << 47 << 66 << 51 << 47 << 47 << 51 << 57;
608  "Piecewise test case 1 - Event A2 with long time-to-trigger",
609  config,
610  expectedTime,
611  expectedRsrp),
612  TestCase::TAKES_FOREVER);
613 
614  // With super time-to-trigger
615  config.timeToTrigger = 256;
616  expectedTime.clear();
617  expectedTime << 1656 << 1776 << 1896 << 2016 << 2136;
618  expectedRsrp.clear();
619  expectedRsrp << 47 << 47 << 51 << 57 << 57;
621  "Piecewise test case 1 - Event A2 with super time-to-trigger",
622  config,
623  expectedTime,
624  expectedRsrp),
625  TestCase::QUICK);
626 
627  // With hysteresis
628  config.hysteresis = 8;
629  config.timeToTrigger = 0;
630  expectedTime.clear();
631  expectedTime << 800 << 920 << 1600 << 1720 << 1840 << 1960 << 2080;
632  expectedRsrp.clear();
633  expectedRsrp << 47 << 47 << 47 << 47 << 51 << 51 << 57;
634  AddTestCase(
635  new LteUeMeasurementsPiecewiseTestCase1("Piecewise test case 1 - Event A2 with hysteresis",
636  config,
637  expectedTime,
638  expectedRsrp),
639  TestCase::EXTENSIVE);
640 
641  // With very high threshold
642  config.threshold1.range = 97;
643  config.hysteresis = 0;
644  expectedTime.clear();
645  expectedTime << 200 << 320 << 440 << 560 << 680 << 800 << 920 << 1040 << 1160 << 1280 << 1400
646  << 1520 << 1640 << 1760 << 1880 << 2000 << 2120;
647  expectedRsrp.clear();
648  expectedRsrp << 67 << 67 << 57 << 57 << 66 << 47 << 47 << 66 << 66 << 57 << 51 << 51 << 47 << 47
649  << 51 << 57 << 57;
651  "Piecewise test case 1 - Event A2 with very high threshold",
652  config,
653  expectedTime,
654  expectedRsrp),
655  TestCase::EXTENSIVE);
656 
657  /*
658  * Event A3, A4, and A5 are not tested intensively here because they depend on
659  * the existence of at least one neighbouring cell, which is not available in
660  * this configuration. Piecewise configuration #2 includes a neighbouring
661  * cell, hence more thorough tests on these events are performed there.
662  */
663 
664  expectedTime.clear();
665  expectedRsrp.clear();
666 
667  // === Event A3 (neighbour becomes offset better than PCell) ===
668 
669  config.eventId = LteRrcSap::ReportConfigEutra::EVENT_A3;
670  config.a3Offset = 0;
671  AddTestCase(new LteUeMeasurementsPiecewiseTestCase1("Piecewise test case 1 - Event A3",
672  config,
673  expectedTime,
674  expectedRsrp),
675  TestCase::EXTENSIVE);
676 
677  // === Event A4 (neighbour becomes better than threshold) ===
678 
679  config.eventId = LteRrcSap::ReportConfigEutra::EVENT_A4;
680  config.threshold1.range = 54;
681  AddTestCase(new LteUeMeasurementsPiecewiseTestCase1("Piecewise test case 1 - Event A4",
682  config,
683  expectedTime,
684  expectedRsrp),
685  TestCase::EXTENSIVE);
686 
687  // === Event A5 (PCell becomes worse than absolute threshold1 AND neighbour becomes better than
688  // another absolute threshold2) ===
689 
690  config.eventId = LteRrcSap::ReportConfigEutra::EVENT_A5;
691  config.threshold2.range = 58;
692  AddTestCase(new LteUeMeasurementsPiecewiseTestCase1("Piecewise test case 1 - Event A5",
693  config,
694  expectedTime,
695  expectedRsrp),
696  TestCase::EXTENSIVE);
697 
698 } // end of LteUeMeasurementsPiecewiseTestSuite1::LteUeMeasurementsPiecewiseTestSuite1
699 
705 
706 /*
707  * Test Case
708  */
709 
711  std::string name,
713  std::vector<Time> expectedTime,
714  std::vector<uint8_t> expectedRsrp)
715  : TestCase(name),
716  m_config(config),
717  m_expectedTime(expectedTime),
718  m_expectedRsrp(expectedRsrp)
719 {
720  // input sanity check
721  uint16_t size = m_expectedTime.size();
722 
723  if (size != m_expectedRsrp.size())
724  {
725  NS_FATAL_ERROR("Vectors of expected results are not of the same size");
726  }
727 
730 
731  NS_LOG_INFO(this << " name=" << name);
732 }
733 
735 {
736  NS_LOG_FUNCTION(this);
737 }
738 
739 void
741 {
742  NS_LOG_INFO(this << " " << GetName());
743 
744  Ptr<LteHelper> lteHelper = CreateObject<LteHelper>();
745  lteHelper->SetAttribute("PathlossModel", StringValue("ns3::FriisSpectrumPropagationLossModel"));
746  lteHelper->SetAttribute("UseIdealRrc", BooleanValue(true));
747 
748  // Disable Uplink Power Control
749  Config::SetDefault("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue(false));
750 
751  // Create Nodes: eNodeB and UE
752  NodeContainer enbNodes;
753  NodeContainer ueNodes;
754  enbNodes.Create(1);
755  ueNodes.Create(1);
756 
757  /*
758  * The topology is the following:
759  *
760  * eNodeB UE
761  * | |
762  * x ----- x --------- x --------------- x ------------------- x
763  * 100 m | 200 m | 300 m | 400 m |
764  * | | | |
765  * VeryNear Near Far VeryFar
766  */
767 
768  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
769  positionAlloc->Add(Vector(0.0, 0.0, 0.0)); // eNodeB
770  positionAlloc->Add(Vector(100.0, 0.0, 0.0)); // UE
772  mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
773  mobility.SetPositionAllocator(positionAlloc);
774  mobility.Install(enbNodes);
775  mobility.Install(ueNodes);
776  m_ueMobility = ueNodes.Get(0)->GetObject<MobilityModel>();
777 
778  // Disable layer-3 filtering
779  Config::SetDefault("ns3::LteEnbRrc::RsrpFilterCoefficient", UintegerValue(0));
780 
781  // Create Devices and install them in the Nodes (eNB and UE)
782  NetDeviceContainer enbDevs;
783  NetDeviceContainer ueDevs;
784  lteHelper->SetSchedulerType("ns3::RrFfMacScheduler");
785  lteHelper->SetSchedulerAttribute("UlCqiFilter", EnumValue(FfMacScheduler::PUSCH_UL_CQI));
786  enbDevs = lteHelper->InstallEnbDevice(enbNodes);
787  ueDevs = lteHelper->InstallUeDevice(ueNodes);
788 
789  // Setup UE measurement configuration
790  Ptr<LteEnbRrc> enbRrc = enbDevs.Get(0)->GetObject<LteEnbNetDevice>()->GetRrc();
791  m_expectedMeasId = enbRrc->AddUeMeasReportConfig(m_config).at(0);
792 
793  // Attach UE to eNodeB
794  lteHelper->Attach(ueDevs.Get(0), enbDevs.Get(0));
795 
796  // Activate an EPS bearer
797  enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
798  EpsBearer bearer(q);
799  lteHelper->ActivateDataRadioBearer(ueDevs, bearer);
800 
801  // Connect to trace sources
803  "/NodeList/0/DeviceList/0/LteEnbRrc/RecvMeasurementReport",
805 
806  /*
807  * Schedule "teleports"
808  * 0 1 2
809  * +-------------------+-------------------+---------> time
810  * VeryNear |------ ---- ---- --------
811  * Near | ---- ----
812  * Far | ---- ----
813  * VeryFar | -- ---- ----
814  */
815  Simulator::Schedule(MilliSeconds(301),
817  this);
818  Simulator::Schedule(MilliSeconds(401),
820  this);
821  Simulator::Schedule(MilliSeconds(601),
823  this);
824  Simulator::Schedule(MilliSeconds(801),
826  this);
827  Simulator::Schedule(MilliSeconds(1001),
829  this);
830  Simulator::Schedule(MilliSeconds(1201),
832  this);
833  Simulator::Schedule(MilliSeconds(1401),
835  this);
836  Simulator::Schedule(MilliSeconds(1601),
838  this);
839  Simulator::Schedule(MilliSeconds(1801),
841  this);
842  Simulator::Schedule(MilliSeconds(2001),
844  this);
845 
846  // Run simulation
847  Simulator::Stop(Seconds(2.201));
848  Simulator::Run();
849  Simulator::Destroy();
850 
851 } // end of void LteUeMeasurementsPiecewiseTestCase1::DoRun ()
852 
853 void
855 {
856  NS_LOG_FUNCTION(this);
857  bool hasEnded = m_itExpectedTime == m_expectedTime.end();
858  NS_TEST_ASSERT_MSG_EQ(hasEnded,
859  true,
860  "Reporting should have occurred at " << m_itExpectedTime->As(Time::S));
861  hasEnded = m_itExpectedRsrp == m_expectedRsrp.end();
862  NS_ASSERT(hasEnded);
863 }
864 
865 void
867  std::string context,
868  uint64_t imsi,
869  uint16_t cellId,
870  uint16_t rnti,
872 {
873  NS_LOG_FUNCTION(this << context);
874  NS_ASSERT(rnti == 1);
875  NS_ASSERT(cellId == 1);
876 
877  if (report.measResults.measId == m_expectedMeasId)
878  {
879  // verifying the report completeness
880  LteRrcSap::MeasResults measResults = report.measResults;
881  NS_LOG_DEBUG(
882  this << " rsrp=" << (uint16_t)measResults.measResultPCell.rsrpResult << " ("
883  << EutranMeasurementMapping::RsrpRange2Dbm(measResults.measResultPCell.rsrpResult)
884  << " dBm)"
885  << " rsrq=" << (uint16_t)measResults.measResultPCell.rsrqResult << " ("
886  << EutranMeasurementMapping::RsrqRange2Db(measResults.measResultPCell.rsrqResult)
887  << " dB)");
889  false,
890  "Report should not have neighboring cells information");
891  NS_TEST_ASSERT_MSG_EQ(measResults.measResultListEutra.size(), 0, "Unexpected report size");
892 
893  bool hasEnded = m_itExpectedTime == m_expectedTime.end();
894  NS_TEST_ASSERT_MSG_EQ(hasEnded,
895  false,
896  "Reporting should not have occurred at "
897  << Simulator::Now().As(Time::S));
898  if (!hasEnded)
899  {
900  hasEnded = m_itExpectedRsrp == m_expectedRsrp.end();
901  NS_ASSERT(!hasEnded);
902 
903  // using milliseconds to avoid floating-point comparison
904  uint64_t timeNowMs = Simulator::Now().GetMilliSeconds();
905  uint64_t timeExpectedMs = m_itExpectedTime->GetMilliSeconds();
907 
908  uint16_t observedRsrp = measResults.measResultPCell.rsrpResult;
909  uint16_t referenceRsrp = *m_itExpectedRsrp;
911 
912  NS_TEST_ASSERT_MSG_EQ(timeNowMs,
913  timeExpectedMs,
914  "Reporting should not have occurred at this time");
915  NS_TEST_ASSERT_MSG_EQ(observedRsrp,
916  referenceRsrp,
917  "The RSRP observed differs with the reference RSRP");
918  } // end of if (!hasEnded)
919 
920  } // end of if (measResults.measId == m_expectedMeasId)
921 
922 } // end of LteUeMeasurementsPiecewiseTestCase1::RecvMeasurementReportCallback
923 
924 void
926 {
927  NS_LOG_FUNCTION(this);
928  m_ueMobility->SetPosition(Vector(100.0, 0.0, 0.0));
929 }
930 
931 void
933 {
934  NS_LOG_FUNCTION(this);
935  m_ueMobility->SetPosition(Vector(300.0, 0.0, 0.0));
936 }
937 
938 void
940 {
941  NS_LOG_FUNCTION(this);
942  m_ueMobility->SetPosition(Vector(600.0, 0.0, 0.0));
943 }
944 
945 void
947 {
948  NS_LOG_FUNCTION(this);
949  m_ueMobility->SetPosition(Vector(1000.0, 0.0, 0.0));
950 }
951 
952 // ===== LTE-UE-MEASUREMENTS-PIECEWISE-2 TEST SUITE ======================== //
953 
954 /*
955  * Test Suite
956  */
957 
959  : TestSuite("lte-ue-measurements-piecewise-2", SYSTEM)
960 {
961  std::vector<Time> expectedTime;
962  std::vector<uint8_t> expectedRsrp;
963 
964  /*
965  * Higher level of fullness/duration are given to Event A1 and A2 because they
966  * are supposed to be more intensively tested in Piecewise configuration #1.
967  */
968 
969  // === Event A1 (serving cell becomes better than threshold) ===
970 
971  // With very low threshold
973  config.triggerType = LteRrcSap::ReportConfigEutra::EVENT;
974  config.eventId = LteRrcSap::ReportConfigEutra::EVENT_A1;
975  config.threshold1.choice = LteRrcSap::ThresholdEutra::THRESHOLD_RSRP;
976  config.threshold1.range = 0;
977  config.triggerQuantity = LteRrcSap::ReportConfigEutra::RSRP;
978  config.reportInterval = LteRrcSap::ReportConfigEutra::MS240;
979  expectedTime.clear();
980  expectedTime << 200 << 440 << 680 << 920 << 1160 << 1400 << 1640 << 1880 << 2120;
981  expectedRsrp.clear();
982  expectedRsrp << 73 << 63 << 72 << 52 << 72 << 56 << 52 << 56 << 59;
984  "Piecewise test case 2 - Event A1 with very low threshold",
985  config,
986  expectedTime,
987  expectedRsrp),
988  TestCase::EXTENSIVE);
989 
990  // With normal threshold
991  config.threshold1.range = 58;
992  expectedTime.clear();
993  expectedTime << 200 << 440 << 680 << 1000 << 1240 << 2000;
994  expectedRsrp.clear();
995  expectedRsrp << 73 << 63 << 72 << 72 << 59 << 59;
997  "Piecewise test case 2 - Event A1 with normal threshold",
998  config,
999  expectedTime,
1000  expectedRsrp),
1001  TestCase::TAKES_FOREVER);
1002 
1003  // With hysteresis
1004  config.hysteresis = 6;
1005  expectedTime.clear();
1006  expectedTime << 200 << 440 << 680 << 1000 << 1240 << 1480 << 2200;
1007  expectedRsrp.clear();
1008  expectedRsrp << 73 << 63 << 72 << 72 << 59 << 56 << 72;
1009  AddTestCase(
1010  new LteUeMeasurementsPiecewiseTestCase2("Piecewise test case 2 - Event A1 with hysteresis",
1011  config,
1012  expectedTime,
1013  expectedRsrp),
1014  TestCase::EXTENSIVE);
1015 
1016  // With very high threshold
1017  config.threshold1.range = 97;
1018  config.hysteresis = 0;
1019  expectedTime.clear();
1020  expectedRsrp.clear();
1022  "Piecewise test case 2 - Event A1 with very high threshold",
1023  config,
1024  expectedTime,
1025  expectedRsrp),
1026  TestCase::TAKES_FOREVER);
1027 
1028  // === Event A2 (serving cell becomes worse than threshold) ===
1029 
1030  // With very low threshold
1031  config.eventId = LteRrcSap::ReportConfigEutra::EVENT_A2;
1032  config.threshold1.range = 0;
1033  expectedTime.clear();
1034  expectedRsrp.clear();
1036  "Piecewise test case 2 - Event A2 with very low threshold",
1037  config,
1038  expectedTime,
1039  expectedRsrp),
1040  TestCase::TAKES_FOREVER);
1041 
1042  // With normal threshold
1043  config.threshold1.range = 58;
1044  expectedTime.clear();
1045  expectedTime << 800 << 1400 << 1640 << 1880;
1046  expectedRsrp.clear();
1047  expectedRsrp << 52 << 56 << 52 << 56;
1049  "Piecewise test case 2 - Event A2 with normal threshold",
1050  config,
1051  expectedTime,
1052  expectedRsrp),
1053  TestCase::TAKES_FOREVER);
1054 
1055  // With hysteresis
1056  config.hysteresis = 6;
1057  expectedTime.clear();
1058  expectedTime << 800 << 1600 << 1840 << 2080;
1059  expectedRsrp.clear();
1060  expectedRsrp << 52 << 52 << 56 << 59;
1061  AddTestCase(
1062  new LteUeMeasurementsPiecewiseTestCase2("Piecewise test case 2 - Event A2 with hysteresis",
1063  config,
1064  expectedTime,
1065  expectedRsrp),
1066  TestCase::EXTENSIVE);
1067 
1068  // With very high threshold
1069  config.threshold1.range = 97;
1070  config.hysteresis = 0;
1071  expectedTime.clear();
1072  expectedTime << 200 << 440 << 680 << 920 << 1160 << 1400 << 1640 << 1880 << 2120;
1073  expectedRsrp.clear();
1074  expectedRsrp << 73 << 63 << 72 << 52 << 72 << 56 << 52 << 56 << 59;
1076  "Piecewise test case 2 - Event A2 with very high threshold",
1077  config,
1078  expectedTime,
1079  expectedRsrp),
1080  TestCase::TAKES_FOREVER);
1081 
1082  // === Event A3 (neighbour becomes offset better than PCell) ===
1083 
1084  // With positive offset
1085  config.eventId = LteRrcSap::ReportConfigEutra::EVENT_A3;
1086  config.threshold1.range = 0;
1087  config.a3Offset = 7;
1088  expectedTime.clear();
1089  expectedTime << 800 << 1600;
1090  expectedRsrp.clear();
1091  expectedRsrp << 52 << 52;
1093  "Piecewise test case 2 - Event A3 with positive offset",
1094  config,
1095  expectedTime,
1096  expectedRsrp),
1097  TestCase::QUICK);
1098 
1099  // With zero offset
1100  config.a3Offset = 0;
1101  expectedTime.clear();
1102  expectedTime << 800 << 1400 << 1640 << 1880;
1103  expectedRsrp.clear();
1104  expectedRsrp << 52 << 56 << 52 << 56;
1105  AddTestCase(
1106  new LteUeMeasurementsPiecewiseTestCase2("Piecewise test case 2 - Event A3 with zero offset",
1107  config,
1108  expectedTime,
1109  expectedRsrp),
1110  TestCase::EXTENSIVE);
1111 
1112  // With short time-to-trigger
1113  config.timeToTrigger = 160;
1114  expectedTime.clear();
1115  expectedTime << 960 << 1560 << 1800 << 2040;
1116  expectedRsrp.clear();
1117  expectedRsrp << 52 << 56 << 56 << 59;
1119  "Piecewise test case 2 - Event A3 with short time-to-trigger",
1120  config,
1121  expectedTime,
1122  expectedRsrp),
1123  TestCase::EXTENSIVE);
1124 
1125  // With super time-to-trigger
1126  config.timeToTrigger = 320;
1127  expectedTime.clear();
1128  expectedTime << 1720 << 1960 << 2200;
1129  expectedRsrp.clear();
1130  expectedRsrp << 52 << 56 << 72;
1132  "Piecewise test case 2 - Event A3 with super time-to-trigger",
1133  config,
1134  expectedTime,
1135  expectedRsrp),
1136  TestCase::QUICK);
1137 
1138  // With hysteresis and reportOnLeave
1139  config.hysteresis = 6;
1140  config.reportOnLeave = true;
1141  config.timeToTrigger = 0;
1142  expectedTime.clear();
1143  expectedTime << 800 << 1000 << 1600 << 1840 << 2080 << 2200;
1144  expectedRsrp.clear();
1145  expectedRsrp << 52 << 72 << 52 << 56 << 59 << 72;
1146  AddTestCase(
1147  new LteUeMeasurementsPiecewiseTestCase2("Piecewise test case 2 - Event A3 with hysteresis",
1148  config,
1149  expectedTime,
1150  expectedRsrp),
1151  TestCase::QUICK);
1152 
1153  // With negative offset
1154  config.a3Offset = -7;
1155  config.hysteresis = 0;
1156  config.reportOnLeave = false;
1157  expectedTime.clear();
1158  expectedTime << 400 << 800 << 1200 << 1440 << 1680 << 1920 << 2160;
1159  expectedRsrp.clear();
1160  expectedRsrp << 63 << 52 << 59 << 56 << 52 << 56 << 59;
1162  "Piecewise test case 2 - Event A3 with negative offset",
1163  config,
1164  expectedTime,
1165  expectedRsrp),
1166  TestCase::EXTENSIVE);
1167 
1168  // === Event A4 (neighbour becomes better than threshold) ===
1169 
1170  // With very low threshold
1171  config.eventId = LteRrcSap::ReportConfigEutra::EVENT_A4;
1172  config.threshold1.range = 0;
1173  config.a3Offset = 0;
1174  expectedTime.clear();
1175  expectedTime << 200 << 440 << 680 << 920 << 1160 << 1400 << 1640 << 1880 << 2120;
1176  expectedRsrp.clear();
1177  expectedRsrp << 73 << 63 << 72 << 52 << 72 << 56 << 52 << 56 << 59;
1179  "Piecewise test case 2 - Event A4 with very low threshold",
1180  config,
1181  expectedTime,
1182  expectedRsrp),
1183  TestCase::QUICK);
1184 
1185  // With normal threshold
1186  config.threshold1.range = 58;
1187  expectedTime.clear();
1188  expectedTime << 400 << 800 << 1400 << 1640 << 1880;
1189  expectedRsrp.clear();
1190  expectedRsrp << 63 << 52 << 56 << 52 << 56;
1192  "Piecewise test case 2 - Event A4 with normal threshold",
1193  config,
1194  expectedTime,
1195  expectedRsrp),
1196  TestCase::EXTENSIVE);
1197 
1198  // With short time-to-trigger
1199  config.timeToTrigger = 160;
1200  expectedTime.clear();
1201  expectedTime << 560 << 960 << 1560 << 1800 << 2040;
1202  expectedRsrp.clear();
1203  expectedRsrp << 63 << 52 << 56 << 56 << 59;
1205  "Piecewise test case 2 - Event A4 with short time-to-trigger",
1206  config,
1207  expectedTime,
1208  expectedRsrp),
1209  TestCase::QUICK);
1210 
1211  // With super time-to-trigger
1212  config.timeToTrigger = 320;
1213  expectedTime.clear();
1214  expectedTime << 1720 << 1960 << 2200;
1215  expectedRsrp.clear();
1216  expectedRsrp << 52 << 56 << 72;
1218  "Piecewise test case 2 - Event A4 with super time-to-trigger",
1219  config,
1220  expectedTime,
1221  expectedRsrp),
1222  TestCase::TAKES_FOREVER);
1223 
1224  // With hysteresis
1225  config.hysteresis = 6;
1226  config.timeToTrigger = 0;
1227  expectedTime.clear();
1228  expectedTime << 400 << 800 << 1600 << 1840 << 2080;
1229  expectedRsrp.clear();
1230  expectedRsrp << 63 << 52 << 52 << 56 << 59;
1231  AddTestCase(
1232  new LteUeMeasurementsPiecewiseTestCase2("Piecewise test case 2 - Event A4 with hysteresis",
1233  config,
1234  expectedTime,
1235  expectedRsrp),
1236  TestCase::QUICK);
1237 
1238  // With very high threshold
1239  config.threshold1.range = 97;
1240  config.hysteresis = 0;
1241  expectedTime.clear();
1242  expectedRsrp.clear();
1244  "Piecewise test case 2 - Event A4 with very high threshold",
1245  config,
1246  expectedTime,
1247  expectedRsrp),
1248  TestCase::TAKES_FOREVER);
1249 
1250  // === Event A5 (PCell becomes worse than absolute threshold1 AND neighbour becomes better than
1251  // another absolute threshold2) ===
1252 
1253  // With low-low threshold
1254  config.eventId = LteRrcSap::ReportConfigEutra::EVENT_A5;
1255  config.threshold1.range = 0;
1256  config.threshold2.range = 0;
1257  expectedTime.clear();
1258  expectedRsrp.clear();
1260  "Piecewise test case 2 - Event A5 with low-low threshold",
1261  config,
1262  expectedTime,
1263  expectedRsrp),
1264  TestCase::EXTENSIVE);
1265 
1266  // With low-normal threshold
1267  config.threshold2.range = 58;
1269  "Piecewise test case 2 - Event A5 with low-normal threshold",
1270  config,
1271  expectedTime,
1272  expectedRsrp),
1273  TestCase::TAKES_FOREVER);
1274 
1275  // With low-high threshold
1276  config.threshold2.range = 97;
1278  "Piecewise test case 2 - Event A5 with low-high threshold",
1279  config,
1280  expectedTime,
1281  expectedRsrp),
1282  TestCase::TAKES_FOREVER);
1283 
1284  // With normal-low threshold
1285  config.threshold1.range = 58;
1286  config.threshold2.range = 0;
1287  expectedTime.clear();
1288  expectedTime << 800 << 1400 << 1640 << 1880;
1289  expectedRsrp.clear();
1290  expectedRsrp << 52 << 56 << 52 << 56;
1292  "Piecewise test case 2 - Event A5 with normal-low threshold",
1293  config,
1294  expectedTime,
1295  expectedRsrp),
1296  TestCase::EXTENSIVE);
1297 
1298  // With normal-normal threshold
1299  config.threshold2.range = 58;
1300  expectedTime.clear();
1301  expectedTime << 800 << 1400 << 1640 << 1880;
1302  expectedRsrp.clear();
1303  expectedRsrp << 52 << 56 << 52 << 56;
1305  "Piecewise test case 2 - Event A5 with normal-normal threshold",
1306  config,
1307  expectedTime,
1308  expectedRsrp),
1309  TestCase::EXTENSIVE);
1310 
1311  // With short time-to-trigger
1312  config.timeToTrigger = 160;
1313  expectedTime.clear();
1314  expectedTime << 960 << 1560 << 1800 << 2040;
1315  expectedRsrp.clear();
1316  expectedRsrp << 52 << 56 << 56 << 59;
1318  "Piecewise test case 2 - Event A5 with short time-to-trigger",
1319  config,
1320  expectedTime,
1321  expectedRsrp),
1322  TestCase::TAKES_FOREVER);
1323 
1324  // With super time-to-trigger
1325  config.timeToTrigger = 320;
1326  expectedTime.clear();
1327  expectedTime << 1720 << 1960 << 2200;
1328  expectedRsrp.clear();
1329  expectedRsrp << 52 << 56 << 72;
1331  "Piecewise test case 2 - Event A5 with super time-to-trigger",
1332  config,
1333  expectedTime,
1334  expectedRsrp),
1335  TestCase::QUICK);
1336 
1337  // With hysteresis
1338  config.hysteresis = 6;
1339  config.timeToTrigger = 0;
1340  expectedTime.clear();
1341  expectedTime << 800 << 1600 << 1840 << 2080;
1342  expectedRsrp.clear();
1343  expectedRsrp << 52 << 52 << 56 << 59;
1344  AddTestCase(
1345  new LteUeMeasurementsPiecewiseTestCase2("Piecewise test case 2 - Event A5 with hysteresis",
1346  config,
1347  expectedTime,
1348  expectedRsrp),
1349  TestCase::QUICK);
1350 
1351  // With normal-high threshold
1352  config.threshold2.range = 97;
1353  config.hysteresis = 0;
1354  expectedTime.clear();
1355  expectedRsrp.clear();
1357  "Piecewise test case 2 - Event A5 with normal-high threshold",
1358  config,
1359  expectedTime,
1360  expectedRsrp),
1361  TestCase::TAKES_FOREVER);
1362 
1363  // With high-low threshold
1364  config.threshold1.range = 97;
1365  config.threshold2.range = 0;
1366  expectedTime.clear();
1367  expectedTime << 200 << 440 << 680 << 920 << 1160 << 1400 << 1640 << 1880 << 2120;
1368  expectedRsrp.clear();
1369  expectedRsrp << 73 << 63 << 72 << 52 << 72 << 56 << 52 << 56 << 59;
1371  "Piecewise test case 2 - Event A5 with high-low threshold",
1372  config,
1373  expectedTime,
1374  expectedRsrp),
1375  TestCase::EXTENSIVE);
1376 
1377  // With high-normal threshold
1378  config.threshold2.range = 58;
1379  expectedTime.clear();
1380  expectedTime << 400 << 800 << 1400 << 1640 << 1880;
1381  expectedRsrp.clear();
1382  expectedRsrp << 63 << 52 << 56 << 52 << 56;
1384  "Piecewise test case 2 - Event A5 with high-normal threshold",
1385  config,
1386  expectedTime,
1387  expectedRsrp),
1388  TestCase::TAKES_FOREVER);
1389 
1390  // With high-high threshold
1391  config.threshold2.range = 97;
1392  expectedTime.clear();
1393  expectedRsrp.clear();
1395  "Piecewise test case 2 - Event A5 with high-high threshold",
1396  config,
1397  expectedTime,
1398  expectedRsrp),
1399  TestCase::EXTENSIVE);
1400 
1401 } // end of LteUeMeasurementsPiecewiseTestSuite2::LteUeMeasurementsPiecewiseTestSuite2
1402 
1408 
1409 /*
1410  * Test Case
1411  */
1412 
1414  std::string name,
1416  std::vector<Time> expectedTime,
1417  std::vector<uint8_t> expectedRsrp)
1418  : TestCase(name),
1419  m_config(config),
1420  m_expectedTime(expectedTime),
1421  m_expectedRsrp(expectedRsrp)
1422 {
1423  // input sanity check
1424  uint16_t size = m_expectedTime.size();
1425 
1426  if (size != m_expectedRsrp.size())
1427  {
1428  NS_FATAL_ERROR("Vectors of expected results are not of the same size");
1429  }
1430 
1431  m_itExpectedTime = m_expectedTime.begin();
1432  m_itExpectedRsrp = m_expectedRsrp.begin();
1433 
1434  NS_LOG_INFO(this << " name=" << name);
1435 }
1436 
1438 {
1439  NS_LOG_FUNCTION(this);
1440 }
1441 
1442 void
1444 {
1445  NS_LOG_INFO(this << " " << GetName());
1446 
1447  Ptr<LteHelper> lteHelper = CreateObject<LteHelper>();
1448  lteHelper->SetAttribute("PathlossModel", StringValue("ns3::FriisSpectrumPropagationLossModel"));
1449  lteHelper->SetAttribute("UseIdealRrc", BooleanValue(true));
1450 
1451  // Disable Uplink Power Control
1452  Config::SetDefault("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue(false));
1453 
1454  // Create Nodes: eNodeB and UE
1455  NodeContainer enbNodes;
1456  NodeContainer ueNodes;
1457  enbNodes.Create(2);
1458  ueNodes.Create(1);
1459 
1460  /*
1461  * The topology is the following:
1462  *
1463  * eNodeB UE eNodeB
1464  * | | |
1465  * x ---- x --------------- x ------- x --------------- x ---- x
1466  * 50 m | 200 m | 100 m | 200 m | 50 m
1467  * | | | |
1468  * VeryNear Near Far VeryFar
1469  */
1470 
1471  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
1472  positionAlloc->Add(Vector(0.0, 0.0, 0.0)); // Serving eNodeB
1473  positionAlloc->Add(Vector(600.0, 0.0, 0.0)); // Neighbour eNodeB
1474  positionAlloc->Add(Vector(50.0, 0.0, 0.0)); // UE
1476  mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
1477  mobility.SetPositionAllocator(positionAlloc);
1478  mobility.Install(enbNodes);
1479  mobility.Install(ueNodes);
1480  m_ueMobility = ueNodes.Get(0)->GetObject<MobilityModel>();
1481 
1482  // Disable layer-3 filtering
1483  Config::SetDefault("ns3::LteEnbRrc::RsrpFilterCoefficient", UintegerValue(0));
1484 
1485  // Create Devices and install them in the Nodes (eNB and UE)
1486  NetDeviceContainer enbDevs;
1487  NetDeviceContainer ueDevs;
1488  lteHelper->SetSchedulerType("ns3::RrFfMacScheduler");
1489  lteHelper->SetSchedulerAttribute("UlCqiFilter", EnumValue(FfMacScheduler::PUSCH_UL_CQI));
1490  enbDevs = lteHelper->InstallEnbDevice(enbNodes);
1491  ueDevs = lteHelper->InstallUeDevice(ueNodes);
1492 
1493  // Setup UE measurement configuration in serving cell
1494  Ptr<LteEnbRrc> enbRrc1 = enbDevs.Get(0)->GetObject<LteEnbNetDevice>()->GetRrc();
1495  m_expectedMeasId = enbRrc1->AddUeMeasReportConfig(m_config).at(0);
1496 
1497  // Disable handover in neighbour cell
1498  Ptr<LteEnbRrc> enbRrc2 = enbDevs.Get(1)->GetObject<LteEnbNetDevice>()->GetRrc();
1499  enbRrc2->SetAttribute("AdmitHandoverRequest", BooleanValue(false));
1500 
1501  // Attach UE to serving eNodeB
1502  lteHelper->Attach(ueDevs.Get(0), enbDevs.Get(0));
1503 
1504  // Activate an EPS bearer
1505  enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
1506  EpsBearer bearer(q);
1507  lteHelper->ActivateDataRadioBearer(ueDevs, bearer);
1508 
1509  // Connect to trace sources in serving eNodeB
1511  "/NodeList/0/DeviceList/0/LteEnbRrc/RecvMeasurementReport",
1513 
1514  /*
1515  * Schedule "teleports"
1516  * 0 1 2
1517  * +-------------------+-------------------+---------> time
1518  * VeryNear |------ ---- ---- --------
1519  * Near | ---- ----
1520  * Far | ---- ----
1521  * VeryFar | -- ---- ----
1522  */
1523  Simulator::Schedule(MilliSeconds(301),
1525  this);
1526  Simulator::Schedule(MilliSeconds(401),
1528  this);
1529  Simulator::Schedule(MilliSeconds(601),
1531  this);
1532  Simulator::Schedule(MilliSeconds(801),
1534  this);
1535  Simulator::Schedule(MilliSeconds(1001),
1537  this);
1538  Simulator::Schedule(MilliSeconds(1201),
1540  this);
1541  Simulator::Schedule(MilliSeconds(1401),
1543  this);
1544  Simulator::Schedule(MilliSeconds(1601),
1546  this);
1547  Simulator::Schedule(MilliSeconds(1801),
1549  this);
1550  Simulator::Schedule(MilliSeconds(2001),
1552  this);
1553 
1554  // Run simulation
1555  Simulator::Stop(Seconds(2.201));
1556  Simulator::Run();
1557  Simulator::Destroy();
1558 
1559 } // end of void LteUeMeasurementsPiecewiseTestCase2::DoRun ()
1560 
1561 void
1563 {
1564  NS_LOG_FUNCTION(this);
1565  bool hasEnded = m_itExpectedTime == m_expectedTime.end();
1566  NS_TEST_ASSERT_MSG_EQ(hasEnded,
1567  true,
1568  "Reporting should have occurred at " << m_itExpectedTime->As(Time::S));
1569  hasEnded = m_itExpectedRsrp == m_expectedRsrp.end();
1570  NS_ASSERT(hasEnded);
1571 }
1572 
1573 void
1575  std::string context,
1576  uint64_t imsi,
1577  uint16_t cellId,
1578  uint16_t rnti,
1580 {
1581  NS_LOG_FUNCTION(this << context);
1582  NS_ASSERT(rnti == 1);
1583  NS_ASSERT(cellId == 1);
1584 
1585  if (report.measResults.measId == m_expectedMeasId)
1586  {
1587  // verifying the report completeness
1588  LteRrcSap::MeasResults measResults = report.measResults;
1589  NS_LOG_DEBUG(
1590  this << " Serving cellId=" << cellId
1591  << " rsrp=" << (uint16_t)measResults.measResultPCell.rsrpResult << " ("
1592  << EutranMeasurementMapping::RsrpRange2Dbm(measResults.measResultPCell.rsrpResult)
1593  << " dBm)"
1594  << " rsrq=" << (uint16_t)measResults.measResultPCell.rsrqResult << " ("
1595  << EutranMeasurementMapping::RsrqRange2Db(measResults.measResultPCell.rsrqResult)
1596  << " dB)");
1597 
1598  // verifying reported best cells
1599  if (measResults.measResultListEutra.empty())
1600  {
1602  false,
1603  "Unexpected report content");
1604  }
1605  else
1606  {
1608  true,
1609  "Unexpected report content");
1610  std::list<LteRrcSap::MeasResultEutra>::iterator it =
1611  measResults.measResultListEutra.begin();
1612  NS_ASSERT(it != measResults.measResultListEutra.end());
1613  NS_ASSERT(it->physCellId == 2);
1614  NS_TEST_ASSERT_MSG_EQ(it->haveCgiInfo,
1615  false,
1616  "Report contains cgi-info, which is not supported");
1617  NS_TEST_ASSERT_MSG_EQ(it->haveRsrpResult,
1618  true,
1619  "Report does not contain measured RSRP result");
1620  NS_TEST_ASSERT_MSG_EQ(it->haveRsrqResult,
1621  true,
1622  "Report does not contain measured RSRQ result");
1623  NS_LOG_DEBUG(this << " Neighbour cellId=" << it->physCellId
1624  << " rsrp=" << (uint16_t)it->rsrpResult << " ("
1625  << EutranMeasurementMapping::RsrpRange2Dbm(it->rsrpResult) << " dBm)"
1626  << " rsrq=" << (uint16_t)it->rsrqResult << " ("
1627  << EutranMeasurementMapping::RsrqRange2Db(it->rsrqResult) << " dB)");
1628 
1629  } // end of else of if (measResults.measResultListEutra.size () == 0)
1630 
1631  // verifying the report timing
1632  bool hasEnded = m_itExpectedTime == m_expectedTime.end();
1633  NS_TEST_ASSERT_MSG_EQ(hasEnded,
1634  false,
1635  "Reporting should not have occurred at "
1636  << Simulator::Now().As(Time::S));
1637  if (!hasEnded)
1638  {
1639  hasEnded = m_itExpectedRsrp == m_expectedRsrp.end();
1640  NS_ASSERT(!hasEnded);
1641 
1642  // using milliseconds to avoid floating-point comparison
1643  uint64_t timeNowMs = Simulator::Now().GetMilliSeconds();
1644  uint64_t timeExpectedMs = m_itExpectedTime->GetMilliSeconds();
1645  m_itExpectedTime++;
1646 
1647  uint16_t observedRsrp = measResults.measResultPCell.rsrpResult;
1648  uint16_t referenceRsrp = *m_itExpectedRsrp;
1649  m_itExpectedRsrp++;
1650 
1651  NS_TEST_ASSERT_MSG_EQ(timeNowMs,
1652  timeExpectedMs,
1653  "Reporting should not have occurred at this time");
1654  NS_TEST_ASSERT_MSG_EQ(observedRsrp,
1655  referenceRsrp,
1656  "The RSRP observed differs with the reference RSRP");
1657 
1658  } // end of if (!hasEnded)
1659 
1660  } // end of if (report.measResults.measId == m_expectedMeasId)
1661 
1662 } // end of void LteUeMeasurementsPiecewiseTestCase2::RecvMeasurementReportCallback
1663 
1664 void
1666 {
1667  NS_LOG_FUNCTION(this);
1668  m_ueMobility->SetPosition(Vector(50.0, 0.0, 0.0));
1669 }
1670 
1671 void
1673 {
1674  NS_LOG_FUNCTION(this);
1675  m_ueMobility->SetPosition(Vector(250.0, 0.0, 0.0));
1676 }
1677 
1678 void
1680 {
1681  NS_LOG_FUNCTION(this);
1682  m_ueMobility->SetPosition(Vector(350.0, 0.0, 0.0));
1683 }
1684 
1685 void
1687 {
1688  NS_LOG_FUNCTION(this);
1689  m_ueMobility->SetPosition(Vector(550.0, 0.0, 0.0));
1690 }
1691 
1692 // ===== LTE-UE-MEASUREMENTS-PIECEWISE-3 TEST SUITE ======================== //
1693 
1694 /*
1695  * Test Suite
1696  */
1697 
1699  : TestSuite("lte-ue-measurements-piecewise-3", SYSTEM)
1700 {
1701  std::vector<Time> expectedTime;
1702 
1703  // === Event A4 (neighbor becomes better than threshold) ===
1704 
1705  // The threshold value was chosen to achieve the following:
1706  // 1. Neighbor 1 (eNB2) RSRP would be above the chosen threshold, hence,
1707  // the UE will include it in its reports to its eNB (eNB1) from the beginning
1708  // of the simulation.
1709  // 2. When neighbor 2 (eNB3) is placed at a very far position, its RSRP would
1710  // be less than the chosen threshold, hence, UE will not include it in its
1711  // initial report(s) to its eNB.
1712  // 3. When neighbor 2 (eNB3) is placed at a near position, its RSRP would
1713  // always be above the chosen threshold, hence, the UE will include it in its
1714  // reports to its eNB (eNB1).
1716  config.triggerType = LteRrcSap::ReportConfigEutra::EVENT;
1717  config.eventId = LteRrcSap::ReportConfigEutra::EVENT_A4;
1718  config.threshold1.choice = LteRrcSap::ThresholdEutra::THRESHOLD_RSRP;
1719  config.threshold1.range = 6;
1720  config.triggerQuantity = LteRrcSap::ReportConfigEutra::RSRP;
1721  config.reportInterval = LteRrcSap::ReportConfigEutra::MS240;
1722  expectedTime.clear();
1723  expectedTime << 200 << 440 << 680 << 920 << 1160 << 1400 << 1640 << 1880 << 2120;
1724 
1725  AddTestCase(new LteUeMeasurementsPiecewiseTestCase3("Piecewise test case 3 - Event A4",
1726  config,
1727  expectedTime),
1728  TestCase::QUICK);
1729 } // end of LteUeMeasurementsPiecewiseTestSuite3::LteUeMeasurementsPiecewiseTestSuite3
1730 
1736 
1737 /*
1738  * Test Case
1739  */
1740 
1742  std::string name,
1744  std::vector<Time> expectedTime)
1745  : TestCase(name),
1746  m_config(config),
1747  m_expectedTime(expectedTime)
1748 {
1750 
1751  m_itExpectedTime = m_expectedTime.begin();
1752 
1753  NS_LOG_INFO(this << " name=" << name);
1754 }
1755 
1757 {
1758  NS_LOG_FUNCTION(this);
1759 }
1760 
1761 void
1763 {
1764  NS_LOG_INFO(this << " " << GetName());
1765 
1766  Ptr<LteHelper> lteHelper = CreateObject<LteHelper>();
1767  lteHelper->SetAttribute("PathlossModel", StringValue("ns3::FriisSpectrumPropagationLossModel"));
1768  lteHelper->SetAttribute("UseIdealRrc", BooleanValue(true));
1769 
1770  // Disable Uplink Power Control
1771  Config::SetDefault("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue(false));
1772 
1773  // Create Nodes: eNodeB and UE
1774  NodeContainer enbNodes;
1775  NodeContainer ueNodes;
1776  enbNodes.Create(3);
1777  ueNodes.Create(1);
1778 
1779  /*
1780  * The topology is the following:
1781  *
1782  * We place the 3rd eNB initially very far so it does not fulfills
1783  * the entry condition to be reported.
1784  *
1785  * eNodeB UE eNodeB eNodeB
1786  * | | | |
1787  * x ---- x --------------- x -------------- x ---------------------x
1788  * 50 m 100 m 500 | 1000000
1789  * Near
1790  */
1791 
1792  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
1793  positionAlloc->Add(Vector(0.0, 0.0, 0.0)); // Serving eNodeB
1794  positionAlloc->Add(Vector(200.0, 0.0, 0.0)); // Neighbour eNodeB1
1795  positionAlloc->Add(Vector(1000700.0, 0.0, 0.0)); // Neighbour eNodeB2
1796  positionAlloc->Add(Vector(50.0, 0.0, 0.0)); // UE
1798  mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
1799  mobility.SetPositionAllocator(positionAlloc);
1800  mobility.Install(enbNodes);
1801  mobility.Install(ueNodes);
1802  m_enbMobility = enbNodes.Get(2)->GetObject<MobilityModel>();
1803 
1804  // Disable layer-3 filtering
1805  Config::SetDefault("ns3::LteEnbRrc::RsrpFilterCoefficient", UintegerValue(0));
1806 
1807  // Create Devices and install them in the Nodes (eNB and UE)
1808  NetDeviceContainer enbDevs;
1809  NetDeviceContainer ueDevs;
1810  lteHelper->SetSchedulerType("ns3::RrFfMacScheduler");
1811  lteHelper->SetSchedulerAttribute("UlCqiFilter", EnumValue(FfMacScheduler::PUSCH_UL_CQI));
1812  enbDevs = lteHelper->InstallEnbDevice(enbNodes);
1813  ueDevs = lteHelper->InstallUeDevice(ueNodes);
1814 
1815  // Setup UE measurement configuration in serving cell
1816  Ptr<LteEnbRrc> enbRrc1 = enbDevs.Get(0)->GetObject<LteEnbNetDevice>()->GetRrc();
1817  m_expectedMeasId = enbRrc1->AddUeMeasReportConfig(m_config).at(0);
1818 
1819  // Disable handover in neighbour cells
1820  Ptr<LteEnbRrc> enbRrc2 = enbDevs.Get(1)->GetObject<LteEnbNetDevice>()->GetRrc();
1821  enbRrc2->SetAttribute("AdmitHandoverRequest", BooleanValue(false));
1822  Ptr<LteEnbRrc> enbRrc3 = enbDevs.Get(2)->GetObject<LteEnbNetDevice>()->GetRrc();
1823  enbRrc3->SetAttribute("AdmitHandoverRequest", BooleanValue(false));
1824 
1825  // Attach UE to serving eNodeB
1826  lteHelper->Attach(ueDevs.Get(0), enbDevs.Get(0));
1827 
1828  // Activate an EPS bearer
1829  enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
1830  EpsBearer bearer(q);
1831  lteHelper->ActivateDataRadioBearer(ueDevs, bearer);
1832 
1833  // Connect to trace sources in serving eNodeB
1835  "/NodeList/0/DeviceList/0/LteEnbRrc/RecvMeasurementReport",
1837  /*
1838  * Schedule "teleport" for the 2nd neighbour
1839  *
1840  * We bring the 2nd neighbour near once the UE has already scheduled the periodic
1841  * reporting after detecting the 1st neighbour, which ideally should be at
1842  * 200 ms.
1843  */
1844  Simulator::Schedule(MilliSeconds(301),
1846  this);
1847 
1848  // Run simulation
1849  Simulator::Stop(Seconds(2.201));
1850  Simulator::Run();
1851  Simulator::Destroy();
1852 
1853 } // end of void LteUeMeasurementsPiecewiseTestCase3::DoRun ()
1854 
1855 void
1857 {
1858  NS_LOG_FUNCTION(this);
1859  bool hasEnded = m_itExpectedTime == m_expectedTime.end();
1860  NS_TEST_ASSERT_MSG_EQ(hasEnded,
1861  true,
1862  "Reporting should have occurred at " << m_itExpectedTime->GetSeconds()
1863  << "s");
1864 }
1865 
1866 void
1868  std::string context,
1869  uint64_t imsi,
1870  uint16_t cellId,
1871  uint16_t rnti,
1873 {
1874  NS_LOG_FUNCTION(this << context);
1875  NS_ASSERT(rnti == 1);
1876  NS_ASSERT(cellId == 1);
1877 
1878  if (report.measResults.measId == m_expectedMeasId)
1879  {
1880  // verifying the report completeness
1881  LteRrcSap::MeasResults measResults = report.measResults;
1882  NS_LOG_DEBUG(
1883  this << " Serving cellId=" << cellId
1884  << " rsrp=" << (uint16_t)measResults.measResultPCell.rsrpResult << " ("
1885  << EutranMeasurementMapping::RsrpRange2Dbm(measResults.measResultPCell.rsrpResult)
1886  << " dBm)"
1887  << " rsrq=" << (uint16_t)measResults.measResultPCell.rsrqResult << " ("
1888  << EutranMeasurementMapping::RsrqRange2Db(measResults.measResultPCell.rsrqResult)
1889  << " dB)");
1890 
1891  // verifying reported best cells
1892  if (measResults.measResultListEutra.empty())
1893  {
1895  false,
1896  "Unexpected report content");
1897  }
1898  else
1899  {
1901  true,
1902  "Unexpected report content");
1903  std::list<LteRrcSap::MeasResultEutra>::iterator it =
1904  measResults.measResultListEutra.begin();
1905  NS_ASSERT(it != measResults.measResultListEutra.end());
1906  for (const auto& it : measResults.measResultListEutra)
1907  {
1908  NS_ASSERT(it.physCellId == 2 || it.physCellId == 3);
1909  NS_TEST_ASSERT_MSG_EQ(it.haveCgiInfo,
1910  false,
1911  "Report contains cgi-info, which is not supported");
1912  NS_TEST_ASSERT_MSG_EQ(it.haveRsrpResult,
1913  true,
1914  "Report does not contain measured RSRP result");
1915  NS_TEST_ASSERT_MSG_EQ(it.haveRsrqResult,
1916  true,
1917  "Report does not contain measured RSRQ result");
1918  NS_LOG_DEBUG(
1919  this << " Neighbour cellId=" << it.physCellId
1920  << " rsrp=" << (uint16_t)it.rsrpResult << " ("
1921  << EutranMeasurementMapping::RsrpRange2Dbm(it.rsrpResult) << " dBm)"
1922  << " rsrq=" << (uint16_t)it.rsrqResult << " ("
1923  << EutranMeasurementMapping::RsrqRange2Db(it.rsrqResult) << " dB)");
1924  }
1925 
1926  } // end of else of if (measResults.measResultListEutra.size () == 0)
1927 
1928  // verifying the report timing
1929  bool hasEnded = m_itExpectedTime == m_expectedTime.end();
1930  NS_TEST_ASSERT_MSG_EQ(hasEnded,
1931  false,
1932  "Reporting should not have occurred at "
1933  << Simulator::Now().GetSeconds() << "s");
1934  if (!hasEnded)
1935  {
1936  // using milliseconds to avoid floating-point comparison
1937  uint64_t timeNowMs = Simulator::Now().GetMilliSeconds();
1938  uint64_t timeExpectedMs = m_itExpectedTime->GetMilliSeconds();
1939  m_itExpectedTime++;
1940 
1941  NS_TEST_ASSERT_MSG_EQ(timeNowMs,
1942  timeExpectedMs,
1943  "Reporting should not have occurred at this time");
1944 
1945  } // end of if (!hasEnded)
1946 
1947  } // end of if (report.measResults.measId == m_expectedMeasId)
1948 
1949 } // end of void LteUeMeasurementsPiecewiseTestCase3::RecvMeasurementReportCallback
1950 
1951 void
1953 {
1954  NS_LOG_FUNCTION(this);
1955  m_enbMobility->SetPosition(Vector(700.0, 0.0, 0.0));
1956 }
1957 
1958 // ===== LTE-UE-MEASUREMENTS-HANDOVER TEST SUITE =========================== //
1959 
1960 /*
1961  * Test Suite
1962  */
1963 
1965  : TestSuite("lte-ue-measurements-handover", SYSTEM)
1966 {
1967  std::list<LteRrcSap::ReportConfigEutra> sourceConfigList;
1968  std::list<LteRrcSap::ReportConfigEutra> targetConfigList;
1969  std::vector<Time> expectedTime;
1970  std::vector<uint8_t> expectedRsrp;
1971 
1972  LteRrcSap::ReportConfigEutra sourceConfig;
1973  sourceConfig.triggerType = LteRrcSap::ReportConfigEutra::EVENT;
1974  sourceConfig.eventId = LteRrcSap::ReportConfigEutra::EVENT_A1;
1975  sourceConfig.threshold1.choice = LteRrcSap::ThresholdEutra::THRESHOLD_RSRP;
1976  sourceConfig.threshold1.range = 0;
1977  sourceConfig.triggerQuantity = LteRrcSap::ReportConfigEutra::RSRP;
1978  sourceConfig.reportInterval = LteRrcSap::ReportConfigEutra::MS240;
1979  sourceConfigList.push_back(sourceConfig);
1980 
1981  LteRrcSap::ReportConfigEutra targetConfig;
1982  targetConfig.triggerType = LteRrcSap::ReportConfigEutra::EVENT;
1983  targetConfig.eventId = LteRrcSap::ReportConfigEutra::EVENT_A1;
1984  targetConfig.threshold1.choice = LteRrcSap::ThresholdEutra::THRESHOLD_RSRP;
1985  targetConfig.threshold1.range = 0;
1986  targetConfig.triggerQuantity = LteRrcSap::ReportConfigEutra::RSRP;
1987  targetConfig.reportInterval = LteRrcSap::ReportConfigEutra::MS240;
1988  targetConfigList.push_back(targetConfig);
1989 
1990  // === Report interval difference ===
1991 
1992  // decreasing report interval
1993  sourceConfigList.front().reportInterval = LteRrcSap::ReportConfigEutra::MS480;
1994  targetConfigList.front().reportInterval = LteRrcSap::ReportConfigEutra::MS240;
1995  expectedTime.clear();
1996  expectedTime << 200 << 680 << 1200 << 1440 << 1680 << 1920;
1997  expectedRsrp.clear();
1998  expectedRsrp << 55 << 55 << 53 << 53 << 53 << 53;
1999  AddTestCase(
2000  new LteUeMeasurementsHandoverTestCase("Handover test case - decreasing report interval",
2001  sourceConfigList,
2002  targetConfigList,
2003  expectedTime,
2004  expectedRsrp,
2005  Seconds(2)),
2006  TestCase::TAKES_FOREVER);
2007 
2008  // increasing report interval
2009  sourceConfigList.front().reportInterval = LteRrcSap::ReportConfigEutra::MS120;
2010  targetConfigList.front().reportInterval = LteRrcSap::ReportConfigEutra::MS640;
2011  expectedTime.clear();
2012  expectedTime << 200 << 320 << 440 << 560 << 680 << 800 << 920 << 1200 << 1840;
2013  expectedRsrp.clear();
2014  expectedRsrp << 55 << 55 << 55 << 55 << 55 << 55 << 55 << 53 << 53;
2015  AddTestCase(
2016  new LteUeMeasurementsHandoverTestCase("Handover test case - increasing report interval",
2017  sourceConfigList,
2018  targetConfigList,
2019  expectedTime,
2020  expectedRsrp,
2021  Seconds(2)),
2022  TestCase::QUICK);
2023 
2024  // === Event difference ===
2025 
2026  sourceConfigList.front().reportInterval = LteRrcSap::ReportConfigEutra::MS240;
2027  targetConfigList.front().reportInterval = LteRrcSap::ReportConfigEutra::MS240;
2028  sourceConfigList.front().threshold1.range = 54;
2029  sourceConfigList.front().threshold2.range = 54;
2030  sourceConfigList.front().a3Offset = 1;
2031  targetConfigList.front().threshold1.range = 54;
2032  targetConfigList.front().threshold2.range = 54;
2033  targetConfigList.front().a3Offset = 1;
2034 
2035  // Event A1 to Event A2
2036  sourceConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A1;
2037  targetConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A2;
2038  expectedTime.clear();
2039  expectedTime << 200 << 440 << 680 << 920 << 1200 << 1440 << 1680 << 1920;
2040  expectedRsrp.clear();
2041  expectedRsrp << 55 << 55 << 55 << 55 << 53 << 53 << 53 << 53;
2042  AddTestCase(new LteUeMeasurementsHandoverTestCase("Handover test case - Event A1 to Event A2",
2043  sourceConfigList,
2044  targetConfigList,
2045  expectedTime,
2046  expectedRsrp,
2047  Seconds(2)),
2048  TestCase::EXTENSIVE);
2049 
2050  // Event A2 to Event A1
2051  sourceConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A2;
2052  targetConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A1;
2053  expectedTime.clear();
2054  expectedRsrp.clear();
2055  AddTestCase(new LteUeMeasurementsHandoverTestCase("Handover test case - Event A2 to Event A1",
2056  sourceConfigList,
2057  targetConfigList,
2058  expectedTime,
2059  expectedRsrp,
2060  Seconds(2)),
2061  TestCase::TAKES_FOREVER);
2062 
2063  // Event A3 to Event A4
2064  sourceConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A3;
2065  targetConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A4;
2066  expectedTime.clear();
2067  expectedTime << 1200 << 1440 << 1680 << 1920;
2068  expectedRsrp.clear();
2069  expectedRsrp << 53 << 53 << 53 << 53;
2070  AddTestCase(new LteUeMeasurementsHandoverTestCase("Handover test case - Event A3 to Event A4",
2071  sourceConfigList,
2072  targetConfigList,
2073  expectedTime,
2074  expectedRsrp,
2075  Seconds(2)),
2076  TestCase::TAKES_FOREVER);
2077 
2078  // Event A4 to Event A3
2079  sourceConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A4;
2080  targetConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A3;
2081  expectedTime.clear();
2082  expectedTime << 1200 << 1440 << 1680 << 1920;
2083  expectedRsrp.clear();
2084  expectedRsrp << 53 << 53 << 53 << 53;
2085  AddTestCase(new LteUeMeasurementsHandoverTestCase("Handover test case - Event A4 to Event A3",
2086  sourceConfigList,
2087  targetConfigList,
2088  expectedTime,
2089  expectedRsrp,
2090  Seconds(2)),
2091  TestCase::QUICK);
2092 
2093  // Event A2 to Event A3
2094  sourceConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A2;
2095  targetConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A3;
2096  expectedTime.clear();
2097  expectedTime << 1200 << 1440 << 1680 << 1920;
2098  expectedRsrp.clear();
2099  expectedRsrp << 53 << 53 << 53 << 53;
2100  AddTestCase(new LteUeMeasurementsHandoverTestCase("Handover test case - Event A2 to Event A3",
2101  sourceConfigList,
2102  targetConfigList,
2103  expectedTime,
2104  expectedRsrp,
2105  Seconds(2)),
2106  TestCase::EXTENSIVE);
2107 
2108  // Event A3 to Event A2
2109  sourceConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A3;
2110  targetConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A2;
2111  expectedTime.clear();
2112  expectedTime << 1200 << 1440 << 1680 << 1920;
2113  expectedRsrp.clear();
2114  expectedRsrp << 53 << 53 << 53 << 53;
2115  AddTestCase(new LteUeMeasurementsHandoverTestCase("Handover test case - Event A3 to Event A2",
2116  sourceConfigList,
2117  targetConfigList,
2118  expectedTime,
2119  expectedRsrp,
2120  Seconds(2)),
2121  TestCase::TAKES_FOREVER);
2122 
2123  // Event A4 to Event A5
2124  sourceConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A4;
2125  targetConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A5;
2126  expectedTime.clear();
2127  expectedTime << 1200 << 1440 << 1680 << 1920;
2128  expectedRsrp.clear();
2129  expectedRsrp << 53 << 53 << 53 << 53;
2130  AddTestCase(new LteUeMeasurementsHandoverTestCase("Handover test case - Event A4 to Event A5",
2131  sourceConfigList,
2132  targetConfigList,
2133  expectedTime,
2134  expectedRsrp,
2135  Seconds(2)),
2136  TestCase::TAKES_FOREVER);
2137 
2138  // Event A5 to Event A4
2139  sourceConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A5;
2140  targetConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A4;
2141  expectedTime.clear();
2142  expectedTime << 1200 << 1440 << 1680 << 1920;
2143  expectedRsrp.clear();
2144  expectedRsrp << 53 << 53 << 53 << 53;
2145  AddTestCase(new LteUeMeasurementsHandoverTestCase("Handover test case - Event A5 to Event A4",
2146  sourceConfigList,
2147  targetConfigList,
2148  expectedTime,
2149  expectedRsrp,
2150  Seconds(2)),
2151  TestCase::EXTENSIVE);
2152 
2153  // === Threshold/offset difference ===
2154 
2155  sourceConfigList.front().threshold1.range = 52;
2156  targetConfigList.front().threshold1.range = 56;
2157 
2158  // Event A1
2159  sourceConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A1;
2160  targetConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A1;
2161  expectedTime.clear();
2162  expectedTime << 200 << 440 << 680 << 920;
2163  expectedRsrp.clear();
2164  expectedRsrp << 55 << 55 << 55 << 55;
2165  AddTestCase(
2166  new LteUeMeasurementsHandoverTestCase("Handover test case - Event A1 threshold difference",
2167  sourceConfigList,
2168  targetConfigList,
2169  expectedTime,
2170  expectedRsrp,
2171  Seconds(2)),
2172  TestCase::EXTENSIVE);
2173 
2174  // Event A2
2175  sourceConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A2;
2176  targetConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A2;
2177  expectedTime.clear();
2178  expectedTime << 1200 << 1440 << 1680 << 1920;
2179  expectedRsrp.clear();
2180  expectedRsrp << 53 << 53 << 53 << 53;
2181  AddTestCase(
2182  new LteUeMeasurementsHandoverTestCase("Handover test case - Event A2 threshold difference",
2183  sourceConfigList,
2184  targetConfigList,
2185  expectedTime,
2186  expectedRsrp,
2187  Seconds(2)),
2188  TestCase::QUICK);
2189 
2190  // Event A3
2191  sourceConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A3;
2192  sourceConfigList.front().a3Offset = -30;
2193  targetConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A3;
2194  targetConfigList.front().a3Offset = 30;
2195  expectedTime.clear();
2196  expectedTime << 200 << 440 << 680 << 920;
2197  expectedRsrp.clear();
2198  expectedRsrp << 55 << 55 << 55 << 55;
2199  AddTestCase(
2200  new LteUeMeasurementsHandoverTestCase("Handover test case - Event A3 offset difference",
2201  sourceConfigList,
2202  targetConfigList,
2203  expectedTime,
2204  expectedRsrp,
2205  Seconds(2)),
2206  TestCase::QUICK);
2207 
2208  // Event A4
2209  sourceConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A4;
2210  targetConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A4;
2211  expectedTime.clear();
2212  expectedTime << 200 << 440 << 680 << 920;
2213  expectedRsrp.clear();
2214  expectedRsrp << 55 << 55 << 55 << 55;
2215  AddTestCase(
2216  new LteUeMeasurementsHandoverTestCase("Handover test case - Event A4 threshold difference",
2217  sourceConfigList,
2218  targetConfigList,
2219  expectedTime,
2220  expectedRsrp,
2221  Seconds(2)),
2222  TestCase::EXTENSIVE);
2223 
2224  // Event A5
2225  sourceConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A5;
2226  sourceConfigList.front().threshold2.range = 52;
2227  targetConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A5;
2228  targetConfigList.front().threshold2.range = 56;
2229  expectedTime.clear();
2230  expectedRsrp.clear();
2231  AddTestCase(
2232  new LteUeMeasurementsHandoverTestCase("Handover test case - Event A5 threshold difference",
2233  sourceConfigList,
2234  targetConfigList,
2235  expectedTime,
2236  expectedRsrp,
2237  Seconds(2)),
2238  TestCase::EXTENSIVE);
2239 
2240  // === Time-to-trigger (TTT) difference ===
2241 
2242  sourceConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A1;
2243  sourceConfigList.front().a3Offset = 1;
2244  sourceConfigList.front().threshold1.range = 0;
2245  sourceConfigList.front().threshold2.range = 0;
2246  targetConfigList.front().eventId = LteRrcSap::ReportConfigEutra::EVENT_A1;
2247  targetConfigList.front().a3Offset = 1;
2248  targetConfigList.front().threshold1.range = 0;
2249  targetConfigList.front().threshold2.range = 0;
2250 
2251  // decreasing time-to-trigger (short duration)
2252  sourceConfigList.front().timeToTrigger = 1024;
2253  targetConfigList.front().timeToTrigger = 100;
2254  expectedTime.clear();
2255  expectedTime << 1300 << 1540 << 1780;
2256  expectedRsrp.clear();
2257  expectedRsrp << 53 << 53 << 53;
2258  AddTestCase(new LteUeMeasurementsHandoverTestCase("Handover test case - decreasing TTT (short)",
2259  sourceConfigList,
2260  targetConfigList,
2261  expectedTime,
2262  expectedRsrp,
2263  Seconds(2)),
2264  TestCase::QUICK);
2265 
2266  // decreasing time-to-trigger (longer duration)
2267  sourceConfigList.front().timeToTrigger = 1024;
2268  targetConfigList.front().timeToTrigger = 640;
2269  expectedTime.clear();
2270  expectedTime << 1224 << 1464 << 1704 << 1944 << 2840 << 3080 << 3320 << 3560 << 3800 << 4040;
2271  expectedRsrp.clear();
2272  expectedRsrp << 55 << 55 << 55 << 55 << 53 << 53 << 53 << 53 << 53 << 53;
2273  AddTestCase(new LteUeMeasurementsHandoverTestCase("Handover test case - decreasing TTT (long)",
2274  sourceConfigList,
2275  targetConfigList,
2276  expectedTime,
2277  expectedRsrp,
2278  Seconds(4.2)),
2279  TestCase::EXTENSIVE);
2280 
2281 } // end of LteUeMeasurementsHandoverTestSuite::LteUeMeasurementsHandoverTestSuite
2282 
2288 
2289 /*
2290  * Test Case
2291  */
2292 
2294  std::string name,
2295  std::list<LteRrcSap::ReportConfigEutra> sourceConfigList,
2296  std::list<LteRrcSap::ReportConfigEutra> targetConfigList,
2297  std::vector<Time> expectedTime,
2298  std::vector<uint8_t> expectedRsrp,
2299  Time duration)
2300  : TestCase(name),
2301  m_sourceConfigList(sourceConfigList),
2302  m_targetConfigList(targetConfigList),
2303  m_expectedTime(expectedTime),
2304  m_expectedRsrp(expectedRsrp),
2305  m_duration(duration)
2306 {
2307  // input sanity check
2308  uint16_t size = m_expectedTime.size();
2309 
2310  if (size != m_expectedRsrp.size())
2311  {
2312  NS_FATAL_ERROR("Vectors of expected results are not of the same size");
2313  }
2314 
2315  m_itExpectedTime = m_expectedTime.begin();
2316  m_itExpectedRsrp = m_expectedRsrp.begin();
2317 
2318  NS_LOG_INFO(this << " name=" << name);
2319 }
2320 
2322 {
2323  NS_LOG_FUNCTION(this);
2324 }
2325 
2326 void
2328 {
2329  NS_LOG_INFO(this << " " << GetName());
2330 
2331  Ptr<LteHelper> lteHelper = CreateObject<LteHelper>();
2332  Ptr<PointToPointEpcHelper> epcHelper = CreateObject<PointToPointEpcHelper>();
2333  lteHelper->SetEpcHelper(epcHelper);
2334  lteHelper->SetAttribute("PathlossModel", StringValue("ns3::FriisSpectrumPropagationLossModel"));
2335  lteHelper->SetAttribute("UseIdealRrc", BooleanValue(true));
2336 
2337  // Disable Uplink Power Control
2338  Config::SetDefault("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue(false));
2339 
2340  // Create Nodes: eNodeB and UE
2341  NodeContainer enbNodes;
2342  NodeContainer ueNodes;
2343  enbNodes.Create(2);
2344  ueNodes.Create(1);
2345 
2346  /*
2347  * The topology is the following:
2348  *
2349  * eNodeB UE eNodeB
2350  * | | |
2351  * x ------------------- x ----------------------- x
2352  * 400 m 500 m
2353  */
2354 
2355  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
2356  positionAlloc->Add(Vector(0.0, 0.0, 0.0)); // Source eNodeB
2357  positionAlloc->Add(Vector(900.0, 0.0, 0.0)); // Target eNodeB
2358  positionAlloc->Add(Vector(400.0, 0.0, 0.0)); // UE
2360  mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
2361  mobility.SetPositionAllocator(positionAlloc);
2362  mobility.Install(enbNodes);
2363  mobility.Install(ueNodes);
2364 
2365  // Create P-GW node
2366  Ptr<Node> pgw = epcHelper->GetPgwNode();
2367 
2368  // Create a single RemoteHost
2369  NodeContainer remoteHostContainer;
2370  remoteHostContainer.Create(1);
2371  Ptr<Node> remoteHost = remoteHostContainer.Get(0);
2372  InternetStackHelper internet;
2373  internet.Install(remoteHostContainer);
2374 
2375  // Create the Internet
2376  PointToPointHelper p2ph;
2377  p2ph.SetDeviceAttribute("DataRate", DataRateValue(DataRate("100Gb/s")));
2378  p2ph.SetDeviceAttribute("Mtu", UintegerValue(1500));
2379  p2ph.SetChannelAttribute("Delay", TimeValue(Seconds(0.010)));
2380  NetDeviceContainer internetDevices = p2ph.Install(pgw, remoteHost);
2381  Ipv4AddressHelper ipv4h;
2382  ipv4h.SetBase("1.0.0.0", "255.0.0.0");
2383  Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign(internetDevices);
2384 
2385  // Routing of the Internet Host (towards the LTE network)
2386  Ipv4StaticRoutingHelper ipv4RoutingHelper;
2387  Ptr<Ipv4StaticRouting> remoteHostStaticRouting =
2388  ipv4RoutingHelper.GetStaticRouting(remoteHost->GetObject<Ipv4>());
2389  remoteHostStaticRouting->AddNetworkRouteTo(Ipv4Address("7.0.0.0"), Ipv4Mask("255.0.0.0"), 1);
2390 
2391  // Enable layer-3 filtering
2392  Config::SetDefault("ns3::LteEnbRrc::RsrpFilterCoefficient", UintegerValue(4));
2393 
2394  // Disable control channel error model
2395  Config::SetDefault("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue(false));
2396 
2397  // Create Devices and install them in the Nodes (eNB and UE)
2398  NetDeviceContainer enbDevs;
2399  NetDeviceContainer ueDevs;
2400  enbDevs = lteHelper->InstallEnbDevice(enbNodes);
2401  ueDevs = lteHelper->InstallUeDevice(ueNodes);
2402 
2403  // Setup UE measurement configuration in eNodeBs
2404  uint8_t measId;
2405  std::list<LteRrcSap::ReportConfigEutra>::const_iterator itReportConfig;
2406  Ptr<LteEnbRrc> enbRrc1 = enbDevs.Get(0)->GetObject<LteEnbNetDevice>()->GetRrc();
2407  Ptr<LteEnbRrc> enbRrc2 = enbDevs.Get(1)->GetObject<LteEnbNetDevice>()->GetRrc();
2408 
2409  for (itReportConfig = m_sourceConfigList.begin(); itReportConfig != m_sourceConfigList.end();
2410  itReportConfig++)
2411  {
2412  measId = enbRrc1->AddUeMeasReportConfig(*itReportConfig).at(0);
2413  m_expectedSourceCellMeasId.insert(measId);
2414  }
2415 
2416  for (itReportConfig = m_targetConfigList.begin(); itReportConfig != m_targetConfigList.end();
2417  itReportConfig++)
2418  {
2419  measId = enbRrc2->AddUeMeasReportConfig(*itReportConfig).at(0);
2420  m_expectedTargetCellMeasId.insert(measId);
2421  }
2422 
2423  // Install the IP stack on the UEs
2424  internet.Install(ueNodes);
2425  Ipv4InterfaceContainer ueIpIfaces;
2426  ueIpIfaces = epcHelper->AssignUeIpv4Address(NetDeviceContainer(ueDevs));
2427 
2428  // Assign IP address to UEs
2429  for (uint32_t u = 0; u < ueNodes.GetN(); ++u)
2430  {
2431  Ptr<Node> ueNode = ueNodes.Get(u);
2432  // Set the default gateway for the UE
2433  Ptr<Ipv4StaticRouting> ueStaticRouting =
2434  ipv4RoutingHelper.GetStaticRouting(ueNode->GetObject<Ipv4>());
2435  ueStaticRouting->SetDefaultRoute(epcHelper->GetUeDefaultGatewayAddress(), 1);
2436  }
2437 
2438  // Attach UE to serving eNodeB
2439  lteHelper->Attach(ueDevs.Get(0), enbDevs.Get(0));
2440 
2441  // Add X2 interface
2442  lteHelper->AddX2Interface(enbNodes);
2443 
2444  // Connect to trace sources in source eNodeB
2446  "/NodeList/3/DeviceList/0/LteEnbRrc/RecvMeasurementReport",
2448 
2449  // Connect to trace sources in target eNodeB
2451  "/NodeList/4/DeviceList/0/LteEnbRrc/RecvMeasurementReport",
2453 
2454  // Schedule handover
2456  ueDevs.Get(0),
2457  enbDevs.Get(0),
2458  enbDevs.Get(1));
2459 
2460  // Run simulation
2461  Simulator::Stop(m_duration);
2462  Simulator::Run();
2463  Simulator::Destroy();
2464 
2465 } // end of void LteUeMeasurementsHandoverTestCase::DoRun ()
2466 
2467 void
2469 {
2470  NS_LOG_FUNCTION(this);
2471  bool hasEnded = m_itExpectedTime == m_expectedTime.end();
2472  NS_TEST_ASSERT_MSG_EQ(hasEnded,
2473  true,
2474  "Reporting should have occurred at " << m_itExpectedTime->As(Time::S));
2475  hasEnded = m_itExpectedRsrp == m_expectedRsrp.end();
2476  NS_ASSERT(hasEnded);
2477 }
2478 
2479 void
2481  std::string context,
2482  uint64_t imsi,
2483  uint16_t cellId,
2484  uint16_t rnti,
2486 {
2487  uint8_t measId = report.measResults.measId;
2488  NS_LOG_FUNCTION(this << context << (uint16_t)measId);
2489 
2490  bool isCorrectMeasId;
2491  if (cellId == 1)
2492  {
2493  std::set<uint8_t>::iterator itMeasId = m_expectedSourceCellMeasId.find(measId);
2494  isCorrectMeasId = (itMeasId != m_expectedSourceCellMeasId.end());
2495  }
2496  else if (cellId == 2)
2497  {
2498  std::set<uint8_t>::iterator itMeasId = m_expectedTargetCellMeasId.find(measId);
2499  isCorrectMeasId = (itMeasId != m_expectedTargetCellMeasId.end());
2500  }
2501  else
2502  {
2503  NS_FATAL_ERROR("Invalid cell ID " << cellId);
2504  }
2505 
2506  if (isCorrectMeasId)
2507  {
2508  // verifying the report completeness
2509  LteRrcSap::MeasResults measResults = report.measResults;
2510  NS_LOG_DEBUG(
2511  this << " Serving cellId=" << cellId
2512  << " rsrp=" << (uint16_t)measResults.measResultPCell.rsrpResult << " ("
2513  << EutranMeasurementMapping::RsrpRange2Dbm(measResults.measResultPCell.rsrpResult)
2514  << " dBm)"
2515  << " rsrq=" << (uint16_t)measResults.measResultPCell.rsrqResult << " ("
2516  << EutranMeasurementMapping::RsrqRange2Db(measResults.measResultPCell.rsrqResult)
2517  << " dB)");
2518 
2519  // verifying reported best cells
2520  if (measResults.measResultListEutra.empty())
2521  {
2523  false,
2524  "Unexpected report content");
2525  }
2526  else
2527  {
2529  true,
2530  "Unexpected report content");
2531  std::list<LteRrcSap::MeasResultEutra>::iterator it =
2532  measResults.measResultListEutra.begin();
2533  NS_ASSERT(it != measResults.measResultListEutra.end());
2534  NS_ASSERT(it->physCellId != cellId);
2535  NS_ASSERT(it->physCellId <= 2);
2536  NS_TEST_ASSERT_MSG_EQ(it->haveCgiInfo,
2537  false,
2538  "Report contains cgi-info, which is not supported");
2539  NS_TEST_ASSERT_MSG_EQ(it->haveRsrpResult,
2540  true,
2541  "Report does not contain measured RSRP result");
2542  NS_TEST_ASSERT_MSG_EQ(it->haveRsrqResult,
2543  true,
2544  "Report does not contain measured RSRQ result");
2545  NS_LOG_DEBUG(this << " Neighbour cellId=" << it->physCellId
2546  << " rsrp=" << (uint16_t)it->rsrpResult << " ("
2547  << EutranMeasurementMapping::RsrpRange2Dbm(it->rsrpResult) << " dBm)"
2548  << " rsrq=" << (uint16_t)it->rsrqResult << " ("
2549  << EutranMeasurementMapping::RsrqRange2Db(it->rsrqResult) << " dB)");
2550 
2551  } // end of else of if (measResults.measResultListEutra.size () == 0)
2552 
2553  // verifying the report timing
2554  bool hasEnded = m_itExpectedTime == m_expectedTime.end();
2555  NS_TEST_ASSERT_MSG_EQ(hasEnded,
2556  false,
2557  "Reporting should not have occurred at "
2558  << Simulator::Now().As(Time::S));
2559  if (!hasEnded)
2560  {
2561  hasEnded = m_itExpectedRsrp == m_expectedRsrp.end();
2562  NS_ASSERT(!hasEnded);
2563 
2564  // using milliseconds to avoid floating-point comparison
2565  uint64_t timeNowMs = Simulator::Now().GetMilliSeconds();
2566  uint64_t timeExpectedMs = m_itExpectedTime->GetMilliSeconds();
2567  m_itExpectedTime++;
2568 
2569  uint16_t observedRsrp = measResults.measResultPCell.rsrpResult;
2570  uint16_t referenceRsrp = *m_itExpectedRsrp;
2571  m_itExpectedRsrp++;
2572 
2573  NS_TEST_ASSERT_MSG_EQ(timeNowMs,
2574  timeExpectedMs,
2575  "Reporting should not have occurred at this time");
2576  NS_TEST_ASSERT_MSG_EQ(observedRsrp,
2577  referenceRsrp,
2578  "The RSRP observed differs with the reference RSRP");
2579 
2580  } // end of if (!hasEnded)
2581 
2582  } // end of if (report.measResults.measId == correctMeasId)
2583 
2584 } // end of void LteUeMeasurementsHandoverTestCase::RecvMeasurementReportCallback
#define max(a, b)
Definition: 80211b.c:43
Testing UE measurements in LTE with simulation of 2 eNodeB and 1 UE in a handover configuration.
std::vector< uint8_t >::iterator m_itExpectedRsrp
Pointer to the element of m_expectedRsrp which is expected to occur next in the simulation.
std::vector< Time > m_expectedTime
The list of expected time when measurement reports are received by eNodeB.
std::list< LteRrcSap::ReportConfigEutra > m_sourceConfigList
The list of active report triggering configuration for the source eNodeB.
void DoRun() override
Setup the simulation with the intended UE measurement reporting configuration, run it,...
std::set< uint8_t > m_expectedTargetCellMeasId
The list of measurement identities being tested in the target cell.
LteUeMeasurementsHandoverTestCase(std::string name, std::list< LteRrcSap::ReportConfigEutra > sourceConfigList, std::list< LteRrcSap::ReportConfigEutra > targetConfigList, std::vector< Time > expectedTime, std::vector< uint8_t > expectedRsrp, Time duration)
Constructor.
void RecvMeasurementReportCallback(std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti, LteRrcSap::MeasurementReport report)
Triggers when either one of the eNodeBs receives measurement report from UE, then perform verificatio...
void DoTeardown() override
Runs at the end of the simulation, verifying that all expected measurement reports have been examined...
Time m_duration
Duration of simulation.
std::vector< Time >::iterator m_itExpectedTime
Pointer to the element of m_expectedTime which is expected to occur next in the simulation.
std::list< LteRrcSap::ReportConfigEutra > m_targetConfigList
The list of active report triggering configuration for the target eNodeB.
std::set< uint8_t > m_expectedSourceCellMeasId
The list of measurement identities being tested in the source cell.
std::vector< uint8_t > m_expectedRsrp
The list of expected values of RSRP (in 3GPP range unit) from the measurement reports received.
Test suite for generating calls to UE measurements test case ns3::LteUeMeasurementsHandoverTestCase.
Testing UE measurements in LTE with simulation of 1 eNodeB and 1 UE in piecewise configuration and 12...
std::vector< Time > m_expectedTime
The list of expected time when measurement reports are received by eNodeB.
void TeleportVeryFar()
Teleport far function.
LteRrcSap::ReportConfigEutra m_config
The active report triggering configuration.
uint8_t m_expectedMeasId
The measurement identity being tested.
LteUeMeasurementsPiecewiseTestCase1(std::string name, LteRrcSap::ReportConfigEutra config, std::vector< Time > expectedTime, std::vector< uint8_t > expectedRsrp)
Constructor.
std::vector< Time >::iterator m_itExpectedTime
Pointer to the element of m_expectedTime which is expected to occur next in the simulation.
Ptr< MobilityModel > m_ueMobility
the mobility model
void TeleportVeryNear()
Teleport very near function.
void TeleportNear()
Teleport near function.
std::vector< uint8_t > m_expectedRsrp
The list of expected values of RSRP (in 3GPP range unit) from the measurement reports received.
void DoTeardown() override
Runs at the end of the simulation, verifying that all expected measurement reports have been examined...
std::vector< uint8_t >::iterator m_itExpectedRsrp
Pointer to the element of m_expectedRsrp which is expected to occur next in the simulation.
void RecvMeasurementReportCallback(std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti, LteRrcSap::MeasurementReport report)
Triggers when eNodeB receives measurement report from UE, then perform verification on it.
void DoRun() override
Setup the simulation with the intended UE measurement reporting configuration, run it,...
Testing UE measurements in LTE with simulation of 2 eNodeB and 1 UE in piecewise configuration and 24...
Ptr< MobilityModel > m_ueMobility
the mobility model
std::vector< Time >::iterator m_itExpectedTime
Pointer to the element of m_expectedTime which is expected to occur next in the simulation.
void TeleportVeryNear()
Teleport very near function.
std::vector< uint8_t > m_expectedRsrp
The list of expected values of RSRP (in 3GPP range unit) from the measurement reports received.
void DoTeardown() override
Runs at the end of the simulation, verifying that all expected measurement reports have been examined...
LteUeMeasurementsPiecewiseTestCase2(std::string name, LteRrcSap::ReportConfigEutra config, std::vector< Time > expectedTime, std::vector< uint8_t > expectedRsrp)
Constructor.
LteRrcSap::ReportConfigEutra m_config
The active report triggering configuration.
void DoRun() override
Setup the simulation with the intended UE measurement reporting configuration, run it,...
void RecvMeasurementReportCallback(std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti, LteRrcSap::MeasurementReport report)
Triggers when eNodeB receives measurement report from UE, then perform verification on it.
void TeleportVeryFar()
Teleport very far function.
void TeleportNear()
Teleport near function.
std::vector< uint8_t >::iterator m_itExpectedRsrp
Pointer to the element of m_expectedRsrp which is expected to occur next in the simulation.
uint8_t m_expectedMeasId
The measurement identity being tested.
std::vector< Time > m_expectedTime
The list of expected time when measurement reports are received by eNodeB.
Testing UE measurements in LTE with simulation of 3 eNodeB and 1 UE in piecewise configuration and 24...
Ptr< MobilityModel > m_enbMobility
the mobility model
LteUeMeasurementsPiecewiseTestCase3(std::string name, LteRrcSap::ReportConfigEutra config, std::vector< Time > expectedTime)
Constructor.
void DoTeardown() override
Runs at the end of the simulation, verifying that all expected measurement reports have been examined...
void DoRun() override
Setup the simulation with the intended UE measurement reporting configuration, run it,...
void RecvMeasurementReportCallback(std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti, LteRrcSap::MeasurementReport report)
Triggers when eNodeB receives measurement report from UE, then perform verification on it.
LteRrcSap::ReportConfigEutra m_config
The active report triggering configuration.
uint8_t m_expectedMeasId
The measurement identity being tested.
std::vector< Time > m_expectedTime
The list of expected time when measurement reports are received by eNodeB.
void TeleportEnbNear()
Teleport the eNb near function.
std::vector< Time >::iterator m_itExpectedTime
Pointer to the element of m_expectedTime which is expected to occur next in the simulation.
Test suite for generating calls to UE measurements test case ns3::LteUeMeasurementsPiecewiseTestCase1...
Test suite for generating calls to UE measurements test case ns3::LteUeMeasurementsPiecewiseTestCase2...
Test suite for generating calls to UE measurements test case ns3::LteUeMeasurementsPiecewiseTestCase3...
Test that UE measurements calculation works properly in a scenario with 2 eNodeBs and 2UEs.
double m_d1
distance between UE and ENB node pair
double m_rsrqDbUeServingCell
RSRQ in dBm UE 1.
double m_rsrpDbmUeServingCell
RSRP in dBm UE 1.
LteUeMeasurementsTestCase(std::string name, double d1, double d2, double rsrpDbmUe1, double rsrpDbmUe2, double rsrqDbUe1, double rsrqDbUe2)
Constructor.
void ReportUeMeasurements(uint16_t rnti, uint16_t cellId, double rsrp, double rsrq, bool servingCell)
Report UE measurements function.
void DoRun() override
Implementation to actually run this TestCase.
double m_rsrqDbUeNeighborCell
RSRQ in dBm UE 2.
double m_d2
distance between UE and other ENB node
double m_rsrpDbmUeNeighborCell
RSRP in dBm UE 2.
void RecvMeasurementReport(uint64_t imsi, uint16_t cellId, uint16_t rnti, LteRrcSap::MeasurementReport meas)
Reeive measurement report function.
Test that UE Measurements (see 36.214) calculation works fine in a multi-cell interference scenario.
AttributeValue implementation for Boolean.
Definition: boolean.h:37
AttributeValue implementation for DataRate.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
Hold variables of type enum.
Definition: enum.h:56
This class contains the specification of EPS Bearers.
Definition: eps-bearer.h:91
Qci
QoS Class Indicator.
Definition: eps-bearer.h:106
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...
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:43
Access to the IPv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:79
holds a vector of std::pair of Ptr<Ipv4> and interface index.
a class to represent an Ipv4 address mask
Definition: ipv4-address.h:258
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.
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:282
void SetSchedulerAttribute(std::string n, const AttributeValue &v)
Set an attribute for the scheduler to be created.
Definition: lte-helper.cc:303
void HandoverRequest(Time hoTime, Ptr< NetDevice > ueDev, Ptr< NetDevice > sourceEnbDev, Ptr< NetDevice > targetEnbDev)
Manually trigger an X2-based handover.
Definition: lte-helper.cc:1343
NetDeviceContainer InstallEnbDevice(NodeContainer c)
Create a set of eNodeB devices.
Definition: lte-helper.cc:482
void SetSchedulerType(std::string type)
Set the type of scheduler to be used by eNodeB devices.
Definition: lte-helper.cc:289
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:1044
void ActivateDataRadioBearer(NetDeviceContainer ueDevices, EpsBearer bearer)
Activate a Data Radio Bearer on a given UE devices (for LTE-only simulation).
Definition: lte-helper.cc:1441
NetDeviceContainer InstallUeDevice(NodeContainer c)
Create a set of UE devices.
Definition: lte-helper.cc:497
void AddX2Interface(NodeContainer enbNodes)
Create an X2 interface between all the eNBs in a given set.
Definition: lte-helper.cc:1318
Helper class used to assign positions and mobility models to nodes.
Keep track of the current position and velocity of an object.
void SetPosition(const Vector &position)
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:200
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:305
std::string GetName() const
Definition: test.cc:377
A suite of tests to run.
Definition: test.h:1256
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
int64_t GetMilliSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:407
AttributeValue implementation for Time.
Definition: nstime.h:1423
std::ostream & operator<<(std::ostream &os, TypeId tid)
Output streamer.
Definition: type-id.cc:1229
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:891
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:975
#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_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#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 LteUeMeasurementsPiecewiseTestSuite2 lteUeMeasurementsPiecewiseTestSuite2
Static variable for test initialization.
static LteUeMeasurementsHandoverTestSuite lteUeMeasurementsHandoverTestSuite
Static variable for test initialization.
static LteUeMeasurementsTestSuite lteUeMeasurementsTestSuite
Static variable for test initialization.
static LteUeMeasurementsPiecewiseTestSuite1 lteUeMeasurementsPiecewiseTestSuite1
Static variable for test initialization.
static LteUeMeasurementsPiecewiseTestSuite3 lteUeMeasurementsPiecewiseTestSuite3
Static variable for test initialization.
auto MakeBoundCallback(R(*fnPtr)(Args...), BArgs &&... bargs)
Make Callbacks with varying number of bound arguments.
Definition: callback.h:768
void(* DataRate)(DataRate oldValue, DataRate newValue)
TracedValue callback signature for DataRate.
Definition: data-rate.h:328
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:296
#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_EQ_TOL(actual, limit, tol, msg)
Test that actual and expected (limit) values are equal to plus or minus some tolerance and report and...
Definition: test.h:337
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1348
void ReportUeMeasurementsCallback(LteUeMeasurementsTestCase *testcase, std::string path, uint16_t rnti, uint16_t cellId, double rsrp, double rsrq, bool servingCell, uint8_t componentCarrierId)
void RecvMeasurementReportCallback(LteUeMeasurementsTestCase *testcase, std::string path, uint64_t imsi, uint16_t cellId, uint16_t rnti, LteRrcSap::MeasurementReport meas)
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:707
static const Time UE_MEASUREMENT_REPORT_DELAY
Artificial delay of UE measurements procedure.
Definition: lte-ue-rrc.h:66
mobility
Definition: third.py:96
uint8_t rsrqResult
the RSRQ result
Definition: lte-rrc-sap.h:675
uint8_t rsrpResult
the RSRP result
Definition: lte-rrc-sap.h:674
MeasResults structure.
Definition: lte-rrc-sap.h:717
uint8_t measId
measure ID
Definition: lte-rrc-sap.h:718
bool haveMeasResultNeighCells
have measure result neighbor cells
Definition: lte-rrc-sap.h:720
std::list< MeasResultEutra > measResultListEutra
measure result list eutra
Definition: lte-rrc-sap.h:721
MeasResultPCell measResultPCell
measurement result primary cell
Definition: lte-rrc-sap.h:719
MeasurementReport structure.
Definition: lte-rrc-sap.h:948
MeasResults measResults
measure results
Definition: lte-rrc-sap.h:949
Specifies criteria for triggering of an E-UTRA measurement reporting event.
Definition: lte-rrc-sap.h:373
bool reportOnLeave
Indicates whether or not the UE shall initiate the measurement reporting procedure when the leaving c...
Definition: lte-rrc-sap.h:399
uint8_t hysteresis
Parameter used within the entry and leave condition of an event triggered reporting condition.
Definition: lte-rrc-sap.h:407
enum ns3::LteRrcSap::ReportConfigEutra::@68 reportInterval
Report interval enumeration.
ThresholdEutra threshold2
Threshold for event A5.
Definition: lte-rrc-sap.h:394
enum ns3::LteRrcSap::ReportConfigEutra::@64 triggerType
Trigger enumeration.
enum ns3::LteRrcSap::ReportConfigEutra::@65 eventId
Event enumeration.
enum ns3::LteRrcSap::ReportConfigEutra::@66 triggerQuantity
Trigger type enumeration.
ThresholdEutra threshold1
Threshold for event A1, A2, A4, and A5.
Definition: lte-rrc-sap.h:393
int8_t a3Offset
Offset value for Event A3.
Definition: lte-rrc-sap.h:403
uint16_t timeToTrigger
Time during which specific criteria for the event needs to be met in order to trigger a measurement r...
Definition: lte-rrc-sap.h:411
uint8_t range
Value range used in RSRP/RSRQ threshold.
Definition: lte-rrc-sap.h:368
enum ns3::LteRrcSap::ThresholdEutra::@63 choice
Threshold enumeration.