5G-LENA nr-v3.3-159-ga6832aa7
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
nr-test-ue-measurements.cc
1// Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
2//
3// SPDX-License-Identifier: GPL-2.0-only
4//
5// Author: Manuel Requena <manuel.requena@cttc.es>
6// Nicola Baldo <nbaldo@cttc.es>
7// Marco Miozzo <mmiozzo@cttc.es>
8// adapt lte-test-interference.cc to lte-ue-measurements.cc
9// Budiarto Herman <budiarto.herman@magister.fi>
10
11#include "nr-test-ue-measurements.h"
12
13#include "ns3/boolean.h"
14#include "ns3/callback.h"
15#include "ns3/config.h"
16#include "ns3/double.h"
17#include "ns3/enum.h"
18#include "ns3/ff-mac-scheduler.h"
19#include "ns3/internet-stack-helper.h"
20#include "ns3/ipv4-address-helper.h"
21#include "ns3/ipv4-interface-container.h"
22#include "ns3/ipv4-static-routing-helper.h"
23#include "ns3/log.h"
24#include "ns3/mobility-helper.h"
25#include "ns3/net-device-container.h"
26#include "ns3/node-container.h"
27#include "ns3/nr-common.h"
28#include "ns3/nr-epc-helper.h"
29#include "ns3/nr-gnb-net-device.h"
30#include "ns3/nr-gnb-phy.h"
31#include "ns3/nr-gnb-rrc.h"
32#include "ns3/nr-helper.h"
33#include "ns3/nr-point-to-point-epc-helper.h"
34#include "ns3/nr-ue-net-device.h"
35#include "ns3/nr-ue-phy.h"
36#include "ns3/nr-ue-rrc.h"
37#include "ns3/point-to-point-epc-helper.h"
38#include "ns3/point-to-point-helper.h"
39#include "ns3/simulator.h"
40#include "ns3/string.h"
41
42using namespace ns3;
43
44NS_LOG_COMPONENT_DEFINE("NrUeMeasurementsTest");
45
46// ===== LTE-UE-MEASUREMENTS TEST SUITE ==================================== //
47
48void
49ReportUeMeasurementsCallback(NrUeMeasurementsTestCase* testcase,
50 std::string path,
51 uint16_t rnti,
52 uint16_t cellId,
53 double rsrp,
54 double rsrq,
55 bool servingCell,
56 uint8_t componentCarrierId)
57{
58 testcase->ReportUeMeasurements(rnti, cellId, rsrp, rsrq, servingCell);
59}
60
61void
62RecvMeasurementReportCallback(NrUeMeasurementsTestCase* testcase,
63 std::string path,
64 uint64_t imsi,
65 uint16_t cellId,
66 uint16_t rnti,
68{
69 testcase->RecvMeasurementReport(imsi, cellId, rnti, meas);
70}
71
72/*
73 * Test Suite
74 */
75
76NrUeMeasurementsTestSuite::NrUeMeasurementsTestSuite()
77 : TestSuite("nr-ue-measurements", Type::SYSTEM)
78{
79 AddTestCase(new NrUeMeasurementsTestCase("d1=10, d2=10000",
80 10.000000,
81 10000.000000,
82 -53.739702,
83 -113.739702,
84 -3.010305,
85 -63.010305),
86 TestCase::Duration::EXTENSIVE);
87 AddTestCase(new NrUeMeasurementsTestCase("d1=20, d2=10000",
88 20.000000,
89 10000.000000,
90 -59.760302,
91 -113.739702,
92 -3.010319,
93 -56.989719),
94 TestCase::Duration::EXTENSIVE);
95 AddTestCase(new NrUeMeasurementsTestCase("d1=50, d2=10000",
96 50.000000,
97 10000.000000,
98 -67.719102,
99 -113.739702,
100 -3.010421,
101 -49.031021),
102 TestCase::Duration::EXTENSIVE);
103 AddTestCase(new NrUeMeasurementsTestCase("d1=100, d2=10000",
104 100.000000,
105 10000.000000,
106 -73.739702,
107 -113.739702,
108 -3.010783,
109 -43.010783),
110 TestCase::Duration::EXTENSIVE);
111 AddTestCase(new NrUeMeasurementsTestCase("d1=200, d2=10000",
112 200.000000,
113 10000.000000,
114 -79.760302,
115 -113.739702,
116 -3.012232,
117 -36.991632),
118 TestCase::Duration::EXTENSIVE);
119 AddTestCase(new NrUeMeasurementsTestCase("d1=100, d2=10000",
120 100.000000,
121 10000.000000,
122 -73.739702,
123 -113.739702,
124 -3.010783,
125 -43.010783),
126 TestCase::Duration::EXTENSIVE);
127 AddTestCase(new NrUeMeasurementsTestCase("d1=200, d2=10000",
128 200.000000,
129 10000.000000,
130 -79.760302,
131 -113.739702,
132 -3.012232,
133 -36.991632),
134 TestCase::Duration::EXTENSIVE);
135 AddTestCase(new NrUeMeasurementsTestCase("d1=500, d2=10000",
136 500.000000,
137 10000.000000,
138 -87.719102,
139 -113.739702,
140 -3.022359,
141 -29.042959),
142 TestCase::Duration::EXTENSIVE);
143 AddTestCase(new NrUeMeasurementsTestCase("d1=1000, d2=10000",
144 1000.000000,
145 10000.000000,
146 -93.739702,
147 -113.739702,
148 -3.058336,
149 -23.058336),
150 TestCase::Duration::EXTENSIVE);
151 AddTestCase(new NrUeMeasurementsTestCase("d1=2000, d2=10000",
152 2000.000000,
153 10000.000000,
154 -99.760302,
155 -113.739702,
156 -3.199337,
157 -17.178738),
158 TestCase::Duration::EXTENSIVE);
159 AddTestCase(new NrUeMeasurementsTestCase("d1=5000, d2=10000",
160 5000.000000,
161 10000.000000,
162 -107.719102,
163 -113.739702,
164 -4.075793,
165 -10.096393),
166 TestCase::Duration::QUICK);
167 AddTestCase(new NrUeMeasurementsTestCase("d1=10000, d2=10000",
168 10000.000000,
169 10000.000000,
170 -113.739702,
171 -113.739702,
172 -6.257687,
173 -6.257687),
174 TestCase::Duration::EXTENSIVE);
175 AddTestCase(new NrUeMeasurementsTestCase("d1=20000, d2=10000",
176 20000.000000,
177 10000.000000,
178 -119.760302,
179 -113.739702,
180 -10.373365,
181 -4.352765),
182 TestCase::Duration::EXTENSIVE);
183 AddTestCase(new NrUeMeasurementsTestCase("d1=50000, d2=10000",
184 50000.000000,
185 10000.000000,
186 -127.719102,
187 -113.739702,
188 -17.605046,
189 -3.625645),
190 TestCase::Duration::EXTENSIVE);
191 AddTestCase(new NrUeMeasurementsTestCase("d1=100000, d2=10000",
192 100000.000000,
193 10000.000000,
194 -133.739702,
195 -113.739702,
196 -23.511071,
197 -3.511071),
198 TestCase::Duration::EXTENSIVE);
199 AddTestCase(new NrUeMeasurementsTestCase("d1=200000, d2=10000",
200 200000.000000,
201 10000.000000,
202 -139.760302,
203 -113.739702,
204 -29.502549,
205 -3.481949),
206 TestCase::Duration::EXTENSIVE);
207 AddTestCase(new NrUeMeasurementsTestCase("d1=500000, d2=10000",
208 500000.000000,
209 10000.000000,
210 -147.719102,
211 -113.739702,
212 -37.453160,
213 -3.473760),
214 TestCase::Duration::EXTENSIVE);
215 AddTestCase(new NrUeMeasurementsTestCase("d1=1000000, d2=10000",
216 1000000.000000,
217 10000.000000,
218 -153.739702,
219 -113.739702,
220 -43.472589,
221 -3.472589),
222 TestCase::Duration::EXTENSIVE);
223}
224
230
231/*
232 * Test Case
233 */
234
236 double d1,
237 double d2,
238 double rsrpDbmUe1,
239 double rsrpDbmUe2,
240 double rsrqDbUe1,
241 double rsrqDbUe2)
242 : TestCase(name),
243 m_d1(d1),
244 m_d2(d2),
245 m_rsrpDbmUeServingCell(rsrpDbmUe1),
246 m_rsrpDbmUeNeighborCell(rsrpDbmUe2),
247 m_rsrqDbUeServingCell(rsrqDbUe1),
248 m_rsrqDbUeNeighborCell(rsrqDbUe2)
249{
250 NS_LOG_INFO("Test UE Measurements d1 = " << d1 << " m. and d2 = " << d2 << " m.");
251}
252
253NrUeMeasurementsTestCase::~NrUeMeasurementsTestCase()
254{
255}
256
257void
258NrUeMeasurementsTestCase::DoRun()
259{
260 NS_LOG_INFO(this << " " << GetName());
261
262 Config::SetDefault("ns3::NrSpectrumPhy::DataErrorModelEnabled", BooleanValue(false));
263 Config::SetDefault("ns3::NrAmc::AmcModel", EnumValue(NrAmc::ShannonModel));
264 Ptr<NrHelper> nrHelper = CreateObject<NrHelper>();
265 nrHelper->SetAttribute("UseIdealRrc", BooleanValue(false));
266 Config::SetDefault("ns3::NrGnbPhy::TxPower", DoubleValue(30));
267 Config::SetDefault("ns3::NrUePhy::TxPower", DoubleValue(23));
268
269 // Disable Uplink Power Control
270 Config::SetDefault("ns3::NrUePhy::EnableUplinkPowerControl", BooleanValue(false));
271
272 // LogComponentEnable ("NrUeMeasurementsTest", LOG_LEVEL_ALL);
273
274 // Create Nodes: eNodeB and UE
275 NodeContainer nrNodes;
276 NodeContainer ueNodes1;
277 NodeContainer ueNodes2;
278 nrNodes.Create(2);
279 ueNodes1.Create(1);
280 ueNodes2.Create(1);
281 NodeContainer allNodes = NodeContainer(nrNodes, ueNodes1, ueNodes2);
282
283 // the topology is the following:
284 // d2
285 // UE1-----------gNB2
286 // | |
287 // d1| |d1
288 // | d2 |
289 // gNB1----------UE2
290 //
291 Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
292 positionAlloc->Add(Vector(0.0, 0.0, 0.0)); // gNB1
293 positionAlloc->Add(Vector(m_d2, m_d1, 0.0)); // gNB2
294 positionAlloc->Add(Vector(0.0, m_d1, 0.0)); // UE1
295 positionAlloc->Add(Vector(m_d2, 0.0, 0.0)); // UE2
296 MobilityHelper mobility;
297 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
298 mobility.SetPositionAllocator(positionAlloc);
299 mobility.Install(allNodes);
300
301 auto bandwidthAndBWPPair = nrHelper->CreateBandwidthParts({{2.8e9, 5e6, 1}}, "UMa");
302 // Create Devices and install them in the Nodes (gNB and UE)
303 NetDeviceContainer nrDevs;
304 NetDeviceContainer ueDevs1;
305 NetDeviceContainer ueDevs2;
306 nrHelper->SetSchedulerTypeId(TypeId::LookupByName("ns3::NrMacSchedulerTdmaRR"));
307 nrDevs = nrHelper->InstallGnbDevice(nrNodes, bandwidthAndBWPPair.second);
308 ueDevs1 = nrHelper->InstallUeDevice(ueNodes1, bandwidthAndBWPPair.second);
309 ueDevs2 = nrHelper->InstallUeDevice(ueNodes2, bandwidthAndBWPPair.second);
310
311 // Attach UEs to eNodeBs
312 for (uint32_t i = 0; i < ueDevs1.GetN(); i++)
313 {
314 nrHelper->AttachToGnb(ueDevs1.Get(i), nrDevs.Get(0));
315 }
316 for (uint32_t i = 0; i < ueDevs2.GetN(); i++)
317 {
318 nrHelper->AttachToGnb(ueDevs2.Get(i), nrDevs.Get(1));
319 }
320
321 // Activate an EPS bearer
323 NrEpsBearer bearer(q);
324 nrHelper->ActivateDataRadioBearer(ueDevs1, bearer);
325 nrHelper->ActivateDataRadioBearer(ueDevs2, bearer);
326
327 Config::Connect("/NodeList/2/DeviceList/0/$ns3::NrNetDevice/$ns3::NrUeNetDevice/"
328 "ComponentCarrierMapUe/*/NrUePhy/ReportUeMeasurements",
329 MakeBoundCallback(&ReportUeMeasurementsCallback, this));
330 Config::Connect("/NodeList/0/DeviceList/0/NrGnbRrc/RecvMeasurementReport",
331 MakeBoundCallback(&RecvMeasurementReportCallback, this));
332
333 Config::Connect("/NodeList/3/DeviceList/0/$ns3::NrNetDevice/$ns3::NrUeNetDevice/"
334 "ComponentCarrierMapUe/*/NrUePhy/ReportUeMeasurements",
335 MakeBoundCallback(&ReportUeMeasurementsCallback, this));
336 Config::Connect("/NodeList/1/DeviceList/0/NrGnbRrc/RecvMeasurementReport",
337 MakeBoundCallback(&RecvMeasurementReportCallback, this));
338
339 // need to allow for RRC connection establishment + SRS
340 Simulator::Stop(Seconds(0.800));
341 Simulator::Run();
342
343 Simulator::Destroy();
344}
345
346void
348 uint16_t cellId,
349 double rsrp,
350 double rsrq,
351 bool servingCell)
352{
353 // need to allow for RRC connection establishment + CQI feedback reception + UE measurements
354 // filtering (200 ms)
355 if (Simulator::Now() > MilliSeconds(400))
356 {
357 if (servingCell)
358 {
359 NS_LOG_DEBUG("UE serving cellId " << cellId << " Rxed RSRP " << rsrp << " thr "
360 << m_rsrpDbmUeServingCell << " RSRQ " << rsrq
361 << " thr " << m_rsrqDbUeServingCell);
362 NS_TEST_ASSERT_MSG_EQ_TOL(m_rsrpDbmUeServingCell, rsrp, 0.2, "Wrong RSRP UE 1");
363 NS_TEST_ASSERT_MSG_EQ_TOL(m_rsrqDbUeServingCell, rsrq, 0.2, "Wrong RSRQ UE 1");
364 }
365 else
366 {
367 NS_LOG_DEBUG("UE neighbor cellId " << cellId << " Rxed RSRP " << rsrp << " thr "
368 << m_rsrpDbmUeNeighborCell << " RSRQ " << rsrq
369 << " thr " << m_rsrqDbUeNeighborCell);
370 NS_TEST_ASSERT_MSG_EQ_TOL(m_rsrpDbmUeNeighborCell, rsrp, 0.2, "Wrong RSRP UE 2");
371 NS_TEST_ASSERT_MSG_EQ_TOL(m_rsrqDbUeNeighborCell, rsrq, 0.2, "Wrong RSRQ UE ");
372 }
373 }
374}
375
376void
378 uint16_t cellId,
379 uint16_t rnti,
381{
382 // need to allow for RRC connection establishment + CQI feedback reception + UE measurements
383 // filtering (200 ms)
384 if (Simulator::Now() > MilliSeconds(400))
385 {
386 if (cellId == imsi)
387 {
388 NS_LOG_DEBUG(this << "Serving Cell: received IMSI " << imsi << " CellId " << cellId
389 << " RNTI " << rnti << " thr "
391 m_rsrpDbmUeServingCell)
392 << " RSRP " << (uint16_t)meas.measResults.measResultPCell.rsrpResult
393 << " RSRQ " << (uint16_t)meas.measResults.measResultPCell.rsrqResult
394 << " thr "
396 m_rsrqDbUeServingCell));
397 NS_TEST_ASSERT_MSG_EQ(
399 nr::EutranMeasurementMapping::Dbm2RsrpRange(m_rsrpDbmUeServingCell),
400 "Wrong RSRP ");
401 NS_TEST_ASSERT_MSG_EQ(meas.measResults.measResultPCell.rsrqResult,
402 nr::EutranMeasurementMapping::Db2RsrqRange(m_rsrqDbUeServingCell),
403 "Wrong RSRQ ");
404 }
405 else
406 {
407 NS_LOG_DEBUG(this << "Neighbor cell: received IMSI " << imsi << " CellId " << cellId
408 << " RNTI " << rnti << " thr "
410 m_rsrpDbmUeNeighborCell)
411 << " RSRP " << (uint16_t)meas.measResults.measResultPCell.rsrpResult
412 << " RSRQ " << (uint16_t)meas.measResults.measResultPCell.rsrqResult
413 << " thr "
415 m_rsrqDbUeNeighborCell));
416 NS_TEST_ASSERT_MSG_EQ(
418 nr::EutranMeasurementMapping::Dbm2RsrpRange(m_rsrpDbmUeNeighborCell),
419 "Wrong RSRP ");
420 NS_TEST_ASSERT_MSG_EQ(
422 nr::EutranMeasurementMapping::Db2RsrqRange(m_rsrqDbUeNeighborCell),
423 "Wrong RSRQ ");
424 }
425 }
426}
427
428// ===== LTE-UE-MEASUREMENTS-PIECEWISE-1 TEST SUITE ======================== //
429
430/*
431 * Overloaded operators, for the convenience of defining test cases
432 */
433
434std::vector<Time>&
435operator<<(std::vector<Time>& v, const uint64_t& ms)
436{
437 /*
438 * Prior attempt to use seconds as unit of choice resunrd in precision lost.
439 * Therefore milliseconds are used now instead.
440 */
441 v.push_back(MilliSeconds(ms) + NR_UE_MEASUREMENT_REPORT_DELAY);
442 return v;
443}
444
445std::vector<uint8_t>&
446operator<<(std::vector<uint8_t>& v, const uint8_t& range)
447{
448 v.push_back(range);
449 return v;
450}
451
452/*
453 * Test Suite
454 */
455
456NrUeMeasurementsPiecewiseTestSuite1::NrUeMeasurementsPiecewiseTestSuite1()
457 : TestSuite("nr-ue-measurements-piecewise-1", Type::SYSTEM)
458{
459 std::vector<Time> expectedTime;
460 std::vector<uint8_t> expectedRsrp;
461
462 // === Event A1 (serving cell becomes better than threshold) ===
463
464 // With very low threshold
469 config.threshold1.range = 0;
471 config.reportInterval = NrRrcSap::ReportConfigEutra::MS120;
472 expectedTime.clear();
473 expectedTime << 200 << 320 << 440 << 560 << 680 << 800 << 920 << 1040 << 1160 << 1280 << 1400
474 << 1520 << 1640 << 1760 << 1880 << 2000 << 2120;
475 expectedRsrp.clear();
476 expectedRsrp << 67 << 67 << 57 << 57 << 66 << 47 << 47 << 66 << 66 << 57 << 51 << 51 << 47 << 47
477 << 51 << 57 << 57;
479 "Piecewise test case 1 - Event A1 with very low threshold",
480 config,
481 expectedTime,
482 expectedRsrp),
483 TestCase::Duration::EXTENSIVE);
484
485 // With normal threshold
486 config.threshold1.range = 54;
487 expectedTime.clear();
488 expectedTime << 200 << 320 << 440 << 560 << 680 << 1000 << 1120 << 1240 << 1360 << 2000 << 2120;
489 expectedRsrp.clear();
490 expectedRsrp << 67 << 67 << 57 << 57 << 66 << 66 << 66 << 57 << 57 << 57 << 57;
492 "Piecewise test case 1 - Event A1 with normal threshold",
493 config,
494 expectedTime,
495 expectedRsrp),
496 TestCase::Duration::EXTENSIVE);
497
498 // With short time-to-trigger
499 config.timeToTrigger = 64;
500 expectedTime.clear();
501 expectedTime << 264 << 384 << 504 << 624 << 744 << 1064 << 1184 << 1304 << 1424 << 2064 << 2184;
502 expectedRsrp.clear();
503 expectedRsrp << 67 << 67 << 57 << 66 << 66 << 66 << 66 << 57 << 51 << 57 << 57;
505 "Piecewise test case 1 - Event A1 with short time-to-trigger",
506 config,
507 expectedTime,
508 expectedRsrp),
509 TestCase::Duration::QUICK);
510
511 // With long time-to-trigger
512 config.timeToTrigger = 128;
513 expectedTime.clear();
514 expectedTime << 328 << 448 << 568 << 688 << 808 << 1128 << 1248 << 1368 << 1488 << 2128;
515 expectedRsrp.clear();
516 expectedRsrp << 67 << 57 << 57 << 66 << 47 << 66 << 57 << 57 << 51 << 57;
518 "Piecewise test case 1 - Event A1 with long time-to-trigger",
519 config,
520 expectedTime,
521 expectedRsrp),
522 TestCase::Duration::EXTENSIVE);
523
524 // With super time-to-trigger
525 config.timeToTrigger = 256;
526 expectedTime.clear();
527 expectedTime << 456 << 576 << 696 << 816 << 936 << 1056 << 1176 << 1296 << 1416 << 1536;
528 expectedRsrp.clear();
529 expectedRsrp << 57 << 57 << 66 << 47 << 47 << 66 << 66 << 57 << 51 << 51;
531 "Piecewise test case 1 - Event A1 with super time-to-trigger",
532 config,
533 expectedTime,
534 expectedRsrp),
535 TestCase::Duration::EXTENSIVE);
536
537 // With hysteresis
538 config.hysteresis = 8;
539 config.timeToTrigger = 0;
540 expectedTime.clear();
541 expectedTime << 200 << 320 << 440 << 560 << 680 << 1000 << 1120 << 1240 << 1360 << 1480 << 2200;
542 expectedRsrp.clear();
543 expectedRsrp << 67 << 67 << 57 << 57 << 66 << 66 << 66 << 57 << 57 << 51 << 67;
544 AddTestCase(
545 new NrUeMeasurementsPiecewiseTestCase1("Piecewise test case 1 - Event A1 with hysteresis",
546 config,
547 expectedTime,
548 expectedRsrp),
549 TestCase::Duration::QUICK);
550
551 // With very high threshold
552 config.threshold1.range = 97;
553 config.hysteresis = 0;
554 expectedTime.clear();
555 expectedRsrp.clear();
557 "Piecewise test case 1 - Event A1 with very high threshold",
558 config,
559 expectedTime,
560 expectedRsrp),
561 TestCase::Duration::TAKES_FOREVER);
562
563 // === Event A2 (serving cell becomes worse than threshold) ===
564
565 // With very low threshold
567 config.threshold1.range = 0;
568 expectedTime.clear();
569 expectedRsrp.clear();
571 "Piecewise test case 1 - Event A2 with very low threshold",
572 config,
573 expectedTime,
574 expectedRsrp),
575 TestCase::Duration::TAKES_FOREVER);
576
577 // With normal threshold
578 config.threshold1.range = 54;
579 expectedTime.clear();
580 expectedTime << 800 << 920 << 1400 << 1520 << 1640 << 1760 << 1880;
581 expectedRsrp.clear();
582 expectedRsrp << 47 << 47 << 51 << 51 << 47 << 47 << 51;
584 "Piecewise test case 1 - Event A2 with normal threshold",
585 config,
586 expectedTime,
587 expectedRsrp),
588 TestCase::Duration::QUICK);
589
590 // With short time-to-trigger
591 config.timeToTrigger = 64;
592 expectedTime.clear();
593 expectedTime << 864 << 984 << 1464 << 1584 << 1704 << 1824 << 1944;
594 expectedRsrp.clear();
595 expectedRsrp << 47 << 47 << 51 << 51 << 47 << 51 << 51;
597 "Piecewise test case 1 - Event A2 with short time-to-trigger",
598 config,
599 expectedTime,
600 expectedRsrp),
601 TestCase::Duration::EXTENSIVE);
602
603 // With long time-to-trigger
604 config.timeToTrigger = 128;
605 expectedTime.clear();
606 expectedTime << 928 << 1048 << 1528 << 1648 << 1768 << 1888 << 2008;
607 expectedRsrp.clear();
608 expectedRsrp << 47 << 66 << 51 << 47 << 47 << 51 << 57;
610 "Piecewise test case 1 - Event A2 with long time-to-trigger",
611 config,
612 expectedTime,
613 expectedRsrp),
614 TestCase::Duration::TAKES_FOREVER);
615
616 // With super time-to-trigger
617 config.timeToTrigger = 256;
618 expectedTime.clear();
619 expectedTime << 1656 << 1776 << 1896 << 2016 << 2136;
620 expectedRsrp.clear();
621 expectedRsrp << 47 << 47 << 51 << 57 << 57;
623 "Piecewise test case 1 - Event A2 with super time-to-trigger",
624 config,
625 expectedTime,
626 expectedRsrp),
627 TestCase::Duration::QUICK);
628
629 // With hysteresis
630 config.hysteresis = 8;
631 config.timeToTrigger = 0;
632 expectedTime.clear();
633 expectedTime << 800 << 920 << 1600 << 1720 << 1840 << 1960 << 2080;
634 expectedRsrp.clear();
635 expectedRsrp << 47 << 47 << 47 << 47 << 51 << 51 << 57;
636 AddTestCase(
637 new NrUeMeasurementsPiecewiseTestCase1("Piecewise test case 1 - Event A2 with hysteresis",
638 config,
639 expectedTime,
640 expectedRsrp),
641 TestCase::Duration::EXTENSIVE);
642
643 // With very high threshold
644 config.threshold1.range = 97;
645 config.hysteresis = 0;
646 expectedTime.clear();
647 expectedTime << 200 << 320 << 440 << 560 << 680 << 800 << 920 << 1040 << 1160 << 1280 << 1400
648 << 1520 << 1640 << 1760 << 1880 << 2000 << 2120;
649 expectedRsrp.clear();
650 expectedRsrp << 67 << 67 << 57 << 57 << 66 << 47 << 47 << 66 << 66 << 57 << 51 << 51 << 47 << 47
651 << 51 << 57 << 57;
653 "Piecewise test case 1 - Event A2 with very high threshold",
654 config,
655 expectedTime,
656 expectedRsrp),
657 TestCase::Duration::EXTENSIVE);
658
659 /*
660 * Event A3, A4, and A5 are not tested intensively here because they depend on
661 * the existence of at least one neighbouring cell, which is not available in
662 * this configuration. Piecewise configuration #2 includes a neighbouring
663 * cell, hence more thorough tests on these events are performed there.
664 */
665
666 expectedTime.clear();
667 expectedRsrp.clear();
668
669 // === Event A3 (neighbour becomes offset better than PCell) ===
670
672 config.a3Offset = 0;
673 AddTestCase(new NrUeMeasurementsPiecewiseTestCase1("Piecewise test case 1 - Event A3",
674 config,
675 expectedTime,
676 expectedRsrp),
677 TestCase::Duration::EXTENSIVE);
678
679 // === Event A4 (neighbour becomes better than threshold) ===
680
682 config.threshold1.range = 54;
683 AddTestCase(new NrUeMeasurementsPiecewiseTestCase1("Piecewise test case 1 - Event A4",
684 config,
685 expectedTime,
686 expectedRsrp),
687 TestCase::Duration::EXTENSIVE);
688
689 // === Event A5 (PCell becomes worse than absolute threshold1 AND neighbour becomes better than
690 // another absolute threshold2) ===
691
693 config.threshold2.range = 58;
694 AddTestCase(new NrUeMeasurementsPiecewiseTestCase1("Piecewise test case 1 - Event A5",
695 config,
696 expectedTime,
697 expectedRsrp),
698 TestCase::Duration::EXTENSIVE);
699
700} // end of NrUeMeasurementsPiecewiseTestSuite1::NrUeMeasurementsPiecewiseTestSuite1
701
707
708/*
709 * Test Case
710 */
711
713 std::string name,
715 std::vector<Time> expectedTime,
716 std::vector<uint8_t> expectedRsrp)
717 : TestCase(name),
718 m_config(config),
719 m_expectedTime(expectedTime),
720 m_expectedRsrp(expectedRsrp)
721{
722 // input sanity check
723 uint16_t size = m_expectedTime.size();
724
725 if (size != m_expectedRsrp.size())
726 {
727 NS_FATAL_ERROR("Vectors of expected results are not of the same size");
728 }
729
730 m_itExpectedTime = m_expectedTime.begin();
731 m_itExpectedRsrp = m_expectedRsrp.begin();
732
733 NS_LOG_INFO(this << " name=" << name);
734}
735
736NrUeMeasurementsPiecewiseTestCase1::~NrUeMeasurementsPiecewiseTestCase1()
737{
738 NS_LOG_FUNCTION(this);
739}
740
741void
742NrUeMeasurementsPiecewiseTestCase1::DoRun()
743{
744 NS_LOG_INFO(this << " " << GetName());
745
746 Ptr<NrHelper> nrHelper = CreateObject<NrHelper>();
747 nrHelper->SetAttribute("UseIdealRrc", BooleanValue(true));
748 Config::SetDefault("ns3::NrGnbPhy::TxPower", DoubleValue(30));
749 Config::SetDefault("ns3::NrUePhy::TxPower", DoubleValue(23));
750
751 // Disable Uplink Power Control
752 Config::SetDefault("ns3::NrUePhy::EnableUplinkPowerControl", BooleanValue(false));
753
754 // Create Nodes: eNodeB and UE
755 NodeContainer nrNodes;
756 NodeContainer ueNodes;
757 nrNodes.Create(1);
758 ueNodes.Create(1);
759
760 /*
761 * The topology is the following:
762 *
763 * eNodeB UE
764 * | |
765 * x ----- x --------- x --------------- x ------------------- x
766 * 100 m | 200 m | 300 m | 400 m |
767 * | | | |
768 * VeryNear Near Far VeryFar
769 */
770
771 Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
772 positionAlloc->Add(Vector(0.0, 0.0, 0.0)); // eNodeB
773 positionAlloc->Add(Vector(100.0, 0.0, 0.0)); // UE
774 MobilityHelper mobility;
775 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
776 mobility.SetPositionAllocator(positionAlloc);
777 mobility.Install(nrNodes);
778 mobility.Install(ueNodes);
779 m_ueMobility = ueNodes.Get(0)->GetObject<MobilityModel>();
780
781 // Disable layer-3 filtering
782 Config::SetDefault("ns3::NrGnbRrc::RsrpFilterCoefficient", UintegerValue(0));
783
784 auto bandwidthAndBWPPair = nrHelper->CreateBandwidthParts({{2.8e9, 5e6, 1}}, "UMa");
785 // Create Devices and install them in the Nodes (gNB and UE)
786 NetDeviceContainer nrDevs;
787 NetDeviceContainer ueDevs;
788 nrHelper->SetSchedulerTypeId(TypeId::LookupByName("ns3::NrMacSchedulerTdmaRR"));
789 nrDevs = nrHelper->InstallGnbDevice(nrNodes, bandwidthAndBWPPair.second);
790 ueDevs = nrHelper->InstallUeDevice(ueNodes, bandwidthAndBWPPair.second);
791
792 // Setup UE measurement configuration
793 Ptr<NrGnbRrc> nrRrc = nrDevs.Get(0)->GetObject<NrGnbNetDevice>()->GetRrc();
794 m_expectedMeasId = nrRrc->AddUeMeasReportConfig(m_config).at(0);
795
796 // Attach UE to eNodeB
797 nrHelper->AttachToGnb(ueDevs.Get(0), nrDevs.Get(0));
798
799 // Activate an EPS bearer
801 NrEpsBearer bearer(q);
802 nrHelper->ActivateDataRadioBearer(ueDevs, bearer);
803
804 // Connect to trace sources
805 Config::Connect(
806 "/NodeList/0/DeviceList/0/NrGnbRrc/RecvMeasurementReport",
808
809 /*
810 * Schedule "teleports"
811 * 0 1 2
812 * +-------------------+-------------------+---------> time
813 * VeryNear |------ ---- ---- --------
814 * Near | ---- ----
815 * Far | ---- ----
816 * VeryFar | -- ---- ----
817 */
818 Simulator::Schedule(MilliSeconds(301),
819 &NrUeMeasurementsPiecewiseTestCase1::TeleportVeryFar,
820 this);
821 Simulator::Schedule(MilliSeconds(401),
822 &NrUeMeasurementsPiecewiseTestCase1::TeleportVeryNear,
823 this);
824 Simulator::Schedule(MilliSeconds(601),
825 &NrUeMeasurementsPiecewiseTestCase1::TeleportVeryFar,
826 this);
827 Simulator::Schedule(MilliSeconds(801),
828 &NrUeMeasurementsPiecewiseTestCase1::TeleportVeryNear,
829 this);
830 Simulator::Schedule(MilliSeconds(1001),
831 &NrUeMeasurementsPiecewiseTestCase1::TeleportNear,
832 this);
833 Simulator::Schedule(MilliSeconds(1201), &NrUeMeasurementsPiecewiseTestCase1::TeleportFar, this);
834 Simulator::Schedule(MilliSeconds(1401),
835 &NrUeMeasurementsPiecewiseTestCase1::TeleportVeryFar,
836 this);
837 Simulator::Schedule(MilliSeconds(1601), &NrUeMeasurementsPiecewiseTestCase1::TeleportFar, this);
838 Simulator::Schedule(MilliSeconds(1801),
839 &NrUeMeasurementsPiecewiseTestCase1::TeleportNear,
840 this);
841 Simulator::Schedule(MilliSeconds(2001),
842 &NrUeMeasurementsPiecewiseTestCase1::TeleportVeryNear,
843 this);
844
845 // Run simulation
846 Simulator::Stop(Seconds(2.201));
847 Simulator::Run();
848 Simulator::Destroy();
849
850} // end of void NrUeMeasurementsPiecewiseTestCase1::DoRun ()
851
852void
853NrUeMeasurementsPiecewiseTestCase1::DoTeardown()
854{
855 NS_LOG_FUNCTION(this);
856 bool hasEnded = m_itExpectedTime == m_expectedTime.end();
857 NS_TEST_ASSERT_MSG_EQ(hasEnded,
858 true,
859 "Reporting should have occurred at " << m_itExpectedTime->As(Time::S));
860 hasEnded = m_itExpectedRsrp == m_expectedRsrp.end();
861 NS_ASSERT(hasEnded);
862}
863
864void
866 std::string context,
867 uint64_t imsi,
868 uint16_t cellId,
869 uint16_t rnti,
871{
872 NS_LOG_FUNCTION(this << context);
873 NS_ASSERT(rnti == 1);
874 NS_ASSERT(cellId == 1);
875
876 if (report.measResults.measId == m_expectedMeasId)
877 {
878 // verifying the report completeness
879 NrRrcSap::MeasResults measResults = report.measResults;
880 NS_LOG_DEBUG(this << " rsrp=" << (uint16_t)measResults.measResultPCell.rsrpResult << " ("
882 measResults.measResultPCell.rsrpResult)
883 << " dBm)"
884 << " rsrq=" << (uint16_t)measResults.measResultPCell.rsrqResult << " ("
886 measResults.measResultPCell.rsrqResult)
887 << " dB)");
888 NS_TEST_ASSERT_MSG_EQ(measResults.haveMeasResultNeighCells,
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();
906 m_itExpectedTime++;
907
908 uint16_t observedRsrp = measResults.measResultPCell.rsrpResult;
909 uint16_t referenceRsrp = *m_itExpectedRsrp;
910 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 NrUeMeasurementsPiecewiseTestCase1::RecvMeasurementReportCallback
923
924void
925NrUeMeasurementsPiecewiseTestCase1::TeleportVeryNear()
926{
927 NS_LOG_FUNCTION(this);
928 m_ueMobility->SetPosition(Vector(100.0, 0.0, 0.0));
929}
930
931void
932NrUeMeasurementsPiecewiseTestCase1::TeleportNear()
933{
934 NS_LOG_FUNCTION(this);
935 m_ueMobility->SetPosition(Vector(300.0, 0.0, 0.0));
936}
937
938void
939NrUeMeasurementsPiecewiseTestCase1::TeleportFar()
940{
941 NS_LOG_FUNCTION(this);
942 m_ueMobility->SetPosition(Vector(600.0, 0.0, 0.0));
943}
944
945void
946NrUeMeasurementsPiecewiseTestCase1::TeleportVeryFar()
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
958NrUeMeasurementsPiecewiseTestSuite2::NrUeMeasurementsPiecewiseTestSuite2()
959 : TestSuite("nr-ue-measurements-piecewise-2", Type::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
976 config.threshold1.range = 0;
978 config.reportInterval = NrRrcSap::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::Duration::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::Duration::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 NrUeMeasurementsPiecewiseTestCase2("Piecewise test case 2 - Event A1 with hysteresis",
1011 config,
1012 expectedTime,
1013 expectedRsrp),
1014 TestCase::Duration::EXTENSIVE);
1015
1016 // With very high threshold
1017 config.threshold1.range = 97;
1018 config.hysteresis = 0;
1019 expectedTime.clear();
1020 expectedRsrp.clear();
1021 AddTestCase(new NrUeMeasurementsPiecewiseTestCase2(
1022 "Piecewise test case 2 - Event A1 with very high threshold",
1023 config,
1024 expectedTime,
1025 expectedRsrp),
1026 TestCase::Duration::TAKES_FOREVER);
1027
1028 // === Event A2 (serving cell becomes worse than threshold) ===
1029
1030 // With very low threshold
1032 config.threshold1.range = 0;
1033 expectedTime.clear();
1034 expectedRsrp.clear();
1035 AddTestCase(new NrUeMeasurementsPiecewiseTestCase2(
1036 "Piecewise test case 2 - Event A2 with very low threshold",
1037 config,
1038 expectedTime,
1039 expectedRsrp),
1040 TestCase::Duration::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;
1048 AddTestCase(new NrUeMeasurementsPiecewiseTestCase2(
1049 "Piecewise test case 2 - Event A2 with normal threshold",
1050 config,
1051 expectedTime,
1052 expectedRsrp),
1053 TestCase::Duration::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 NrUeMeasurementsPiecewiseTestCase2("Piecewise test case 2 - Event A2 with hysteresis",
1063 config,
1064 expectedTime,
1065 expectedRsrp),
1066 TestCase::Duration::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;
1075 AddTestCase(new NrUeMeasurementsPiecewiseTestCase2(
1076 "Piecewise test case 2 - Event A2 with very high threshold",
1077 config,
1078 expectedTime,
1079 expectedRsrp),
1080 TestCase::Duration::TAKES_FOREVER);
1081
1082 // === Event A3 (neighbour becomes offset better than PCell) ===
1083
1084 // With positive offset
1086 config.threshold1.range = 0;
1087 config.a3Offset = 7;
1088 expectedTime.clear();
1089 expectedTime << 800 << 1600;
1090 expectedRsrp.clear();
1091 expectedRsrp << 52 << 52;
1092 AddTestCase(new NrUeMeasurementsPiecewiseTestCase2(
1093 "Piecewise test case 2 - Event A3 with positive offset",
1094 config,
1095 expectedTime,
1096 expectedRsrp),
1097 TestCase::Duration::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 NrUeMeasurementsPiecewiseTestCase2("Piecewise test case 2 - Event A3 with zero offset",
1107 config,
1108 expectedTime,
1109 expectedRsrp),
1110 TestCase::Duration::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;
1118 AddTestCase(new NrUeMeasurementsPiecewiseTestCase2(
1119 "Piecewise test case 2 - Event A3 with short time-to-trigger",
1120 config,
1121 expectedTime,
1122 expectedRsrp),
1123 TestCase::Duration::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;
1131 AddTestCase(new NrUeMeasurementsPiecewiseTestCase2(
1132 "Piecewise test case 2 - Event A3 with super time-to-trigger",
1133 config,
1134 expectedTime,
1135 expectedRsrp),
1136 TestCase::Duration::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 NrUeMeasurementsPiecewiseTestCase2("Piecewise test case 2 - Event A3 with hysteresis",
1148 config,
1149 expectedTime,
1150 expectedRsrp),
1151 TestCase::Duration::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;
1161 AddTestCase(new NrUeMeasurementsPiecewiseTestCase2(
1162 "Piecewise test case 2 - Event A3 with negative offset",
1163 config,
1164 expectedTime,
1165 expectedRsrp),
1166 TestCase::Duration::EXTENSIVE);
1167
1168 // === Event A4 (neighbour becomes better than threshold) ===
1169
1170 // With very low threshold
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;
1178 AddTestCase(new NrUeMeasurementsPiecewiseTestCase2(
1179 "Piecewise test case 2 - Event A4 with very low threshold",
1180 config,
1181 expectedTime,
1182 expectedRsrp),
1183 TestCase::Duration::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;
1191 AddTestCase(new NrUeMeasurementsPiecewiseTestCase2(
1192 "Piecewise test case 2 - Event A4 with normal threshold",
1193 config,
1194 expectedTime,
1195 expectedRsrp),
1196 TestCase::Duration::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;
1204 AddTestCase(new NrUeMeasurementsPiecewiseTestCase2(
1205 "Piecewise test case 2 - Event A4 with short time-to-trigger",
1206 config,
1207 expectedTime,
1208 expectedRsrp),
1209 TestCase::Duration::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;
1217 AddTestCase(new NrUeMeasurementsPiecewiseTestCase2(
1218 "Piecewise test case 2 - Event A4 with super time-to-trigger",
1219 config,
1220 expectedTime,
1221 expectedRsrp),
1222 TestCase::Duration::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 NrUeMeasurementsPiecewiseTestCase2("Piecewise test case 2 - Event A4 with hysteresis",
1233 config,
1234 expectedTime,
1235 expectedRsrp),
1236 TestCase::Duration::QUICK);
1237
1238 // With very high threshold
1239 config.threshold1.range = 97;
1240 config.hysteresis = 0;
1241 expectedTime.clear();
1242 expectedRsrp.clear();
1243 AddTestCase(new NrUeMeasurementsPiecewiseTestCase2(
1244 "Piecewise test case 2 - Event A4 with very high threshold",
1245 config,
1246 expectedTime,
1247 expectedRsrp),
1248 TestCase::Duration::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
1255 config.threshold1.range = 0;
1256 config.threshold2.range = 0;
1257 expectedTime.clear();
1258 expectedRsrp.clear();
1259 AddTestCase(new NrUeMeasurementsPiecewiseTestCase2(
1260 "Piecewise test case 2 - Event A5 with low-low threshold",
1261 config,
1262 expectedTime,
1263 expectedRsrp),
1264 TestCase::Duration::EXTENSIVE);
1265
1266 // With low-normal threshold
1267 config.threshold2.range = 58;
1268 AddTestCase(new NrUeMeasurementsPiecewiseTestCase2(
1269 "Piecewise test case 2 - Event A5 with low-normal threshold",
1270 config,
1271 expectedTime,
1272 expectedRsrp),
1273 TestCase::Duration::TAKES_FOREVER);
1274
1275 // With low-high threshold
1276 config.threshold2.range = 97;
1277 AddTestCase(new NrUeMeasurementsPiecewiseTestCase2(
1278 "Piecewise test case 2 - Event A5 with low-high threshold",
1279 config,
1280 expectedTime,
1281 expectedRsrp),
1282 TestCase::Duration::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;
1291 AddTestCase(new NrUeMeasurementsPiecewiseTestCase2(
1292 "Piecewise test case 2 - Event A5 with normal-low threshold",
1293 config,
1294 expectedTime,
1295 expectedRsrp),
1296 TestCase::Duration::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;
1304 AddTestCase(new NrUeMeasurementsPiecewiseTestCase2(
1305 "Piecewise test case 2 - Event A5 with normal-normal threshold",
1306 config,
1307 expectedTime,
1308 expectedRsrp),
1309 TestCase::Duration::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;
1317 AddTestCase(new NrUeMeasurementsPiecewiseTestCase2(
1318 "Piecewise test case 2 - Event A5 with short time-to-trigger",
1319 config,
1320 expectedTime,
1321 expectedRsrp),
1322 TestCase::Duration::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;
1330 AddTestCase(new NrUeMeasurementsPiecewiseTestCase2(
1331 "Piecewise test case 2 - Event A5 with super time-to-trigger",
1332 config,
1333 expectedTime,
1334 expectedRsrp),
1335 TestCase::Duration::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 NrUeMeasurementsPiecewiseTestCase2("Piecewise test case 2 - Event A5 with hysteresis",
1346 config,
1347 expectedTime,
1348 expectedRsrp),
1349 TestCase::Duration::QUICK);
1350
1351 // With normal-high threshold
1352 config.threshold2.range = 97;
1353 config.hysteresis = 0;
1354 expectedTime.clear();
1355 expectedRsrp.clear();
1356 AddTestCase(new NrUeMeasurementsPiecewiseTestCase2(
1357 "Piecewise test case 2 - Event A5 with normal-high threshold",
1358 config,
1359 expectedTime,
1360 expectedRsrp),
1361 TestCase::Duration::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;
1370 AddTestCase(new NrUeMeasurementsPiecewiseTestCase2(
1371 "Piecewise test case 2 - Event A5 with high-low threshold",
1372 config,
1373 expectedTime,
1374 expectedRsrp),
1375 TestCase::Duration::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;
1383 AddTestCase(new NrUeMeasurementsPiecewiseTestCase2(
1384 "Piecewise test case 2 - Event A5 with high-normal threshold",
1385 config,
1386 expectedTime,
1387 expectedRsrp),
1388 TestCase::Duration::TAKES_FOREVER);
1389
1390 // With high-high threshold
1391 config.threshold2.range = 97;
1392 expectedTime.clear();
1393 expectedRsrp.clear();
1394 AddTestCase(new NrUeMeasurementsPiecewiseTestCase2(
1395 "Piecewise test case 2 - Event A5 with high-high threshold",
1396 config,
1397 expectedTime,
1398 expectedRsrp),
1399 TestCase::Duration::EXTENSIVE);
1400
1401} // end of NrUeMeasurementsPiecewiseTestSuite2::NrUeMeasurementsPiecewiseTestSuite2
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
1437NrUeMeasurementsPiecewiseTestCase2::~NrUeMeasurementsPiecewiseTestCase2()
1438{
1439 NS_LOG_FUNCTION(this);
1440}
1441
1442void
1443NrUeMeasurementsPiecewiseTestCase2::DoRun()
1444{
1445 NS_LOG_INFO(this << " " << GetName());
1446
1447 Ptr<NrHelper> nrHelper = CreateObject<NrHelper>();
1448 nrHelper->SetAttribute("UseIdealRrc", BooleanValue(true));
1449
1450 Config::SetDefault("ns3::NrGnbPhy::TxPower", DoubleValue(30));
1451 Config::SetDefault("ns3::NrUePhy::TxPower", DoubleValue(23));
1452 // Disable Uplink Power Control
1453 Config::SetDefault("ns3::NrUePhy::EnableUplinkPowerControl", BooleanValue(false));
1454
1455 // Create Nodes: eNodeB and UE
1456 NodeContainer nrNodes;
1457 NodeContainer ueNodes;
1458 nrNodes.Create(2);
1459 ueNodes.Create(1);
1460
1461 /*
1462 * The topology is the following:
1463 *
1464 * eNodeB UE eNodeB
1465 * | | |
1466 * x ---- x --------------- x ------- x --------------- x ---- x
1467 * 50 m | 200 m | 100 m | 200 m | 50 m
1468 * | | | |
1469 * VeryNear Near Far VeryFar
1470 */
1471
1472 Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
1473 positionAlloc->Add(Vector(0.0, 0.0, 0.0)); // Serving eNodeB
1474 positionAlloc->Add(Vector(600.0, 0.0, 0.0)); // Neighbour eNodeB
1475 positionAlloc->Add(Vector(50.0, 0.0, 0.0)); // UE
1476 MobilityHelper mobility;
1477 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
1478 mobility.SetPositionAllocator(positionAlloc);
1479 mobility.Install(nrNodes);
1480 mobility.Install(ueNodes);
1481 m_ueMobility = ueNodes.Get(0)->GetObject<MobilityModel>();
1482
1483 // Disable layer-3 filtering
1484 Config::SetDefault("ns3::NrGnbRrc::RsrpFilterCoefficient", UintegerValue(0));
1485 auto bandwidthAndBWPPair = nrHelper->CreateBandwidthParts({{2.8e9, 5e6, 1}}, "UMa");
1486 // Create Devices and install them in the Nodes (gNB and UE)
1487 NetDeviceContainer nrDevs;
1488 NetDeviceContainer ueDevs;
1489 nrHelper->SetSchedulerTypeId(TypeId::LookupByName("ns3::NrMacSchedulerTdmaRR"));
1490 nrDevs = nrHelper->InstallGnbDevice(nrNodes, bandwidthAndBWPPair.second);
1491 ueDevs = nrHelper->InstallUeDevice(ueNodes, bandwidthAndBWPPair.second);
1492
1493 // Setup UE measurement configuration in serving cell
1494 Ptr<NrGnbRrc> nrRrc1 = nrDevs.Get(0)->GetObject<NrGnbNetDevice>()->GetRrc();
1495 m_expectedMeasId = nrRrc1->AddUeMeasReportConfig(m_config).at(0);
1496
1497 // Disable handover in neighbour cell
1498 Ptr<NrGnbRrc> nrRrc2 = nrDevs.Get(1)->GetObject<NrGnbNetDevice>()->GetRrc();
1499 nrRrc2->SetAttribute("AdmitHandoverRequest", BooleanValue(false));
1500
1501 // Attach UE to serving eNodeB
1502 nrHelper->AttachToGnb(ueDevs.Get(0), nrDevs.Get(0));
1503
1504 // Activate an EPS bearer
1506 NrEpsBearer bearer(q);
1507 nrHelper->ActivateDataRadioBearer(ueDevs, bearer);
1508
1509 // Connect to trace sources in serving eNodeB
1510 Config::Connect(
1511 "/NodeList/0/DeviceList/0/NrGnbRrc/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),
1524 &NrUeMeasurementsPiecewiseTestCase2::TeleportVeryFar,
1525 this);
1526 Simulator::Schedule(MilliSeconds(401),
1527 &NrUeMeasurementsPiecewiseTestCase2::TeleportVeryNear,
1528 this);
1529 Simulator::Schedule(MilliSeconds(601),
1530 &NrUeMeasurementsPiecewiseTestCase2::TeleportVeryFar,
1531 this);
1532 Simulator::Schedule(MilliSeconds(801),
1533 &NrUeMeasurementsPiecewiseTestCase2::TeleportVeryNear,
1534 this);
1535 Simulator::Schedule(MilliSeconds(1001),
1536 &NrUeMeasurementsPiecewiseTestCase2::TeleportNear,
1537 this);
1538 Simulator::Schedule(MilliSeconds(1201), &NrUeMeasurementsPiecewiseTestCase2::TeleportFar, this);
1539 Simulator::Schedule(MilliSeconds(1401),
1540 &NrUeMeasurementsPiecewiseTestCase2::TeleportVeryFar,
1541 this);
1542 Simulator::Schedule(MilliSeconds(1601), &NrUeMeasurementsPiecewiseTestCase2::TeleportFar, this);
1543 Simulator::Schedule(MilliSeconds(1801),
1544 &NrUeMeasurementsPiecewiseTestCase2::TeleportNear,
1545 this);
1546 Simulator::Schedule(MilliSeconds(2001),
1547 &NrUeMeasurementsPiecewiseTestCase2::TeleportVeryNear,
1548 this);
1549
1550 // Run simulation
1551 Simulator::Stop(Seconds(2.201));
1552 Simulator::Run();
1553 Simulator::Destroy();
1554
1555} // end of void NrUeMeasurementsPiecewiseTestCase2::DoRun ()
1556
1557void
1558NrUeMeasurementsPiecewiseTestCase2::DoTeardown()
1559{
1560 NS_LOG_FUNCTION(this);
1561 bool hasEnded = m_itExpectedTime == m_expectedTime.end();
1562 NS_TEST_ASSERT_MSG_EQ(hasEnded,
1563 true,
1564 "Reporting should have occurred at " << m_itExpectedTime->As(Time::S));
1565 hasEnded = m_itExpectedRsrp == m_expectedRsrp.end();
1566 NS_ASSERT(hasEnded);
1567}
1568
1569void
1571 std::string context,
1572 uint64_t imsi,
1573 uint16_t cellId,
1574 uint16_t rnti,
1576{
1577 NS_LOG_FUNCTION(this << context);
1578 NS_ASSERT(rnti == 1);
1579 NS_ASSERT(cellId == 1);
1580
1581 if (report.measResults.measId == m_expectedMeasId)
1582 {
1583 // verifying the report completeness
1584 NrRrcSap::MeasResults measResults = report.measResults;
1585 NS_LOG_DEBUG(this << " Serving cellId=" << cellId
1586 << " rsrp=" << (uint16_t)measResults.measResultPCell.rsrpResult << " ("
1588 measResults.measResultPCell.rsrpResult)
1589 << " dBm)"
1590 << " rsrq=" << (uint16_t)measResults.measResultPCell.rsrqResult << " ("
1592 measResults.measResultPCell.rsrqResult)
1593 << " dB)");
1594
1595 // verifying reported best cells
1596 if (measResults.measResultListEutra.empty())
1597 {
1598 NS_TEST_ASSERT_MSG_EQ(measResults.haveMeasResultNeighCells,
1599 false,
1600 "Unexpected report content");
1601 }
1602 else
1603 {
1604 NS_TEST_ASSERT_MSG_EQ(measResults.haveMeasResultNeighCells,
1605 true,
1606 "Unexpected report content");
1607 auto it = measResults.measResultListEutra.begin();
1608 NS_ASSERT(it != measResults.measResultListEutra.end());
1609 NS_ASSERT(it->physCellId == 2);
1610 NS_TEST_ASSERT_MSG_EQ(it->haveCgiInfo,
1611 false,
1612 "Report contains cgi-info, which is not supported");
1613 NS_TEST_ASSERT_MSG_EQ(it->haveRsrpResult,
1614 true,
1615 "Report does not contain measured RSRP result");
1616 NS_TEST_ASSERT_MSG_EQ(it->haveRsrqResult,
1617 true,
1618 "Report does not contain measured RSRQ result");
1619 NS_LOG_DEBUG(
1620 this << " Neighbour cellId=" << it->physCellId
1621 << " rsrp=" << (uint16_t)it->rsrpResult << " ("
1622 << nr::EutranMeasurementMapping::RsrpRange2Dbm(it->rsrpResult) << " dBm)"
1623 << " rsrq=" << (uint16_t)it->rsrqResult << " ("
1624 << nr::EutranMeasurementMapping::RsrqRange2Db(it->rsrqResult) << " dB)");
1625
1626 } // end of else of if (measResults.measResultListEutra.size () == 0)
1627
1628 // verifying the report timing
1629 bool hasEnded = m_itExpectedTime == m_expectedTime.end();
1630 NS_TEST_ASSERT_MSG_EQ(hasEnded,
1631 false,
1632 "Reporting should not have occurred at "
1633 << Simulator::Now().As(Time::S));
1634 if (!hasEnded)
1635 {
1636 hasEnded = m_itExpectedRsrp == m_expectedRsrp.end();
1637 NS_ASSERT(!hasEnded);
1638
1639 // using milliseconds to avoid floating-point comparison
1640 uint64_t timeNowMs = Simulator::Now().GetMilliSeconds();
1641 uint64_t timeExpectedMs = m_itExpectedTime->GetMilliSeconds();
1642 m_itExpectedTime++;
1643
1644 uint16_t observedRsrp = measResults.measResultPCell.rsrpResult;
1645 uint16_t referenceRsrp = *m_itExpectedRsrp;
1646 m_itExpectedRsrp++;
1647
1648 NS_TEST_ASSERT_MSG_EQ(timeNowMs,
1649 timeExpectedMs,
1650 "Reporting should not have occurred at this time");
1651 NS_TEST_ASSERT_MSG_EQ(observedRsrp,
1652 referenceRsrp,
1653 "The RSRP observed differs with the reference RSRP");
1654
1655 } // end of if (!hasEnded)
1656
1657 } // end of if (report.measResults.measId == m_expectedMeasId)
1658
1659} // end of void NrUeMeasurementsPiecewiseTestCase2::RecvMeasurementReportCallback
1660
1661void
1662NrUeMeasurementsPiecewiseTestCase2::TeleportVeryNear()
1663{
1664 NS_LOG_FUNCTION(this);
1665 m_ueMobility->SetPosition(Vector(50.0, 0.0, 0.0));
1666}
1667
1668void
1669NrUeMeasurementsPiecewiseTestCase2::TeleportNear()
1670{
1671 NS_LOG_FUNCTION(this);
1672 m_ueMobility->SetPosition(Vector(250.0, 0.0, 0.0));
1673}
1674
1675void
1676NrUeMeasurementsPiecewiseTestCase2::TeleportFar()
1677{
1678 NS_LOG_FUNCTION(this);
1679 m_ueMobility->SetPosition(Vector(350.0, 0.0, 0.0));
1680}
1681
1682void
1683NrUeMeasurementsPiecewiseTestCase2::TeleportVeryFar()
1684{
1685 NS_LOG_FUNCTION(this);
1686 m_ueMobility->SetPosition(Vector(550.0, 0.0, 0.0));
1687}
1688
1689// ===== LTE-UE-MEASUREMENTS-PIECEWISE-3 TEST SUITE ======================== //
1690
1691/*
1692 * Test Suite
1693 */
1694
1695NrUeMeasurementsPiecewiseTestSuite3::NrUeMeasurementsPiecewiseTestSuite3()
1696 : TestSuite("nr-ue-measurements-piecewise-3", Type::SYSTEM)
1697{
1698 std::vector<Time> expectedTime;
1699
1700 // === Event A4 (neighbor becomes better than threshold) ===
1701
1702 // The threshold value was chosen to achieve the following:
1703 // 1. Neighbor 1 (gNB2) RSRP would be above the chosen threshold, hence,
1704 // the UE will include it in its reports to its gNB (gNB1) from the beginning
1705 // of the simulation.
1706 // 2. When neighbor 2 (gNB3) is placed at a very far position, its RSRP would
1707 // be less than the chosen threshold, hence, UE will not include it in its
1708 // initial report(s) to its eNB.
1709 // 3. When neighbor 2 (gNB3) is placed at a near position, its RSRP would
1710 // always be above the chosen threshold, hence, the UE will include it in its
1711 // reports to its gNB (gNB1).
1716 config.threshold1.range = 6;
1718 config.reportInterval = NrRrcSap::ReportConfigEutra::MS240;
1719 expectedTime.clear();
1720 expectedTime << 200 << 440 << 680 << 920 << 1160 << 1400 << 1640 << 1880 << 2120;
1721
1722 AddTestCase(new NrUeMeasurementsPiecewiseTestCase3("Piecewise test case 3 - Event A4",
1723 config,
1724 expectedTime),
1725 TestCase::Duration::QUICK);
1726} // end of NrUeMeasurementsPiecewiseTestSuite3::NrUeMeasurementsPiecewiseTestSuite3
1727
1733
1734/*
1735 * Test Case
1736 */
1737
1739 std::string name,
1741 std::vector<Time> expectedTime)
1742 : TestCase(name),
1743 m_config(config),
1744 m_expectedTime(expectedTime)
1745{
1746 m_expectedMeasId = std::numeric_limits<uint8_t>::max();
1747
1748 m_itExpectedTime = m_expectedTime.begin();
1749
1750 NS_LOG_INFO(this << " name=" << name);
1751}
1752
1753NrUeMeasurementsPiecewiseTestCase3::~NrUeMeasurementsPiecewiseTestCase3()
1754{
1755 NS_LOG_FUNCTION(this);
1756}
1757
1758void
1759NrUeMeasurementsPiecewiseTestCase3::DoRun()
1760{
1761 NS_LOG_INFO(this << " " << GetName());
1762
1763 Ptr<NrHelper> nrHelper = CreateObject<NrHelper>();
1764 nrHelper->SetAttribute("UseIdealRrc", BooleanValue(true));
1765
1766 Config::SetDefault("ns3::NrGnbPhy::TxPower", DoubleValue(30));
1767 Config::SetDefault("ns3::NrUePhy::TxPower", DoubleValue(23));
1768 // Disable Uplink Power Control
1769 Config::SetDefault("ns3::NrUePhy::EnableUplinkPowerControl", BooleanValue(false));
1770
1771 // Create Nodes: eNodeB and UE
1772 NodeContainer nrNodes;
1773 NodeContainer ueNodes;
1774 nrNodes.Create(3);
1775 ueNodes.Create(1);
1776
1777 /*
1778 * The topology is the following:
1779 *
1780 * We place the 3rd gNB initially very far so it does not fulfills
1781 * the entry condition to be reported.
1782 *
1783 * eNodeB UE eNodeB eNodeB
1784 * | | | |
1785 * x ---- x --------------- x -------------- x ---------------------x
1786 * 50 m 100 m 500 | 1000000
1787 * Near
1788 */
1789
1790 Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
1791 positionAlloc->Add(Vector(0.0, 0.0, 0.0)); // Serving eNodeB
1792 positionAlloc->Add(Vector(200.0, 0.0, 0.0)); // Neighbour eNodeB1
1793 positionAlloc->Add(Vector(1000700.0, 0.0, 0.0)); // Neighbour eNodeB2
1794 positionAlloc->Add(Vector(50.0, 0.0, 0.0)); // UE
1795 MobilityHelper mobility;
1796 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
1797 mobility.SetPositionAllocator(positionAlloc);
1798 mobility.Install(nrNodes);
1799 mobility.Install(ueNodes);
1800 m_gnbMobility = nrNodes.Get(2)->GetObject<MobilityModel>();
1801
1802 // Disable layer-3 filtering
1803 Config::SetDefault("ns3::NrGnbRrc::RsrpFilterCoefficient", UintegerValue(0));
1804 auto bandwidthAndBWPPair = nrHelper->CreateBandwidthParts({{2.8e9, 5e6, 1}}, "UMa");
1805 // Create Devices and install them in the Nodes (eNB and UE)
1806 NetDeviceContainer nrDevs;
1807 NetDeviceContainer ueDevs;
1808 nrHelper->SetSchedulerTypeId(TypeId::LookupByName("ns3::NrMacSchedulerTdmaRR"));
1809 nrDevs = nrHelper->InstallGnbDevice(nrNodes, bandwidthAndBWPPair.second);
1810 ueDevs = nrHelper->InstallUeDevice(ueNodes, bandwidthAndBWPPair.second);
1811
1812 // Setup UE measurement configuration in serving cell
1813 Ptr<NrGnbRrc> nrRrc1 = nrDevs.Get(0)->GetObject<NrGnbNetDevice>()->GetRrc();
1814 m_expectedMeasId = nrRrc1->AddUeMeasReportConfig(m_config).at(0);
1815
1816 // Disable handover in neighbour cells
1817 Ptr<NrGnbRrc> nrRrc2 = nrDevs.Get(1)->GetObject<NrGnbNetDevice>()->GetRrc();
1818 nrRrc2->SetAttribute("AdmitHandoverRequest", BooleanValue(false));
1819 Ptr<NrGnbRrc> nrRrc3 = nrDevs.Get(2)->GetObject<NrGnbNetDevice>()->GetRrc();
1820 nrRrc3->SetAttribute("AdmitHandoverRequest", BooleanValue(false));
1821
1822 // Attach UE to serving eNodeB
1823 nrHelper->AttachToGnb(ueDevs.Get(0), nrDevs.Get(0));
1824
1825 // Activate an EPS bearer
1827 NrEpsBearer bearer(q);
1828 nrHelper->ActivateDataRadioBearer(ueDevs, bearer);
1829
1830 // Connect to trace sources in serving eNodeB
1831 Config::Connect(
1832 "/NodeList/0/DeviceList/0/NrGnbRrc/RecvMeasurementReport",
1834 /*
1835 * Schedule "teleport" for the 2nd neighbour
1836 *
1837 * We bring the 2nd neighbour near once the UE has already scheduled the periodic
1838 * reporting after detecting the 1st neighbour, which ideally should be at
1839 * 200 ms.
1840 */
1841 Simulator::Schedule(MilliSeconds(301),
1842 &NrUeMeasurementsPiecewiseTestCase3::TeleportGnbNear,
1843 this);
1844
1845 // Run simulation
1846 Simulator::Stop(Seconds(2.201));
1847 Simulator::Run();
1848 Simulator::Destroy();
1849
1850} // end of void NrUeMeasurementsPiecewiseTestCase3::DoRun ()
1851
1852void
1853NrUeMeasurementsPiecewiseTestCase3::DoTeardown()
1854{
1855 NS_LOG_FUNCTION(this);
1856 bool hasEnded = m_itExpectedTime == m_expectedTime.end();
1857 NS_TEST_ASSERT_MSG_EQ(hasEnded,
1858 true,
1859 "Reporting should have occurred at " << m_itExpectedTime->GetSeconds()
1860 << "s");
1861}
1862
1863void
1865 std::string context,
1866 uint64_t imsi,
1867 uint16_t cellId,
1868 uint16_t rnti,
1870{
1871 NS_LOG_FUNCTION(this << context);
1872 NS_ASSERT(rnti == 1);
1873 NS_ASSERT(cellId == 1);
1874
1875 if (report.measResults.measId == m_expectedMeasId)
1876 {
1877 // verifying the report completeness
1878 NrRrcSap::MeasResults measResults = report.measResults;
1879 NS_LOG_DEBUG(this << " Serving cellId=" << cellId
1880 << " rsrp=" << (uint16_t)measResults.measResultPCell.rsrpResult << " ("
1882 measResults.measResultPCell.rsrpResult)
1883 << " dBm)"
1884 << " rsrq=" << (uint16_t)measResults.measResultPCell.rsrqResult << " ("
1886 measResults.measResultPCell.rsrqResult)
1887 << " dB)");
1888
1889 // verifying reported best cells
1890 if (measResults.measResultListEutra.empty())
1891 {
1892 NS_TEST_ASSERT_MSG_EQ(measResults.haveMeasResultNeighCells,
1893 false,
1894 "Unexpected report content");
1895 }
1896 else
1897 {
1898 NS_TEST_ASSERT_MSG_EQ(measResults.haveMeasResultNeighCells,
1899 true,
1900 "Unexpected report content");
1901 auto it = measResults.measResultListEutra.begin();
1902 NS_ASSERT(it != measResults.measResultListEutra.end());
1903 for (const auto& it : measResults.measResultListEutra)
1904 {
1905 NS_ASSERT(it.physCellId == 2 || it.physCellId == 3);
1906 NS_TEST_ASSERT_MSG_EQ(it.haveCgiInfo,
1907 false,
1908 "Report contains cgi-info, which is not supported");
1909 NS_TEST_ASSERT_MSG_EQ(it.haveRsrpResult,
1910 true,
1911 "Report does not contain measured RSRP result");
1912 NS_TEST_ASSERT_MSG_EQ(it.haveRsrqResult,
1913 true,
1914 "Report does not contain measured RSRQ result");
1915 NS_LOG_DEBUG(
1916 this << " Neighbour cellId=" << it.physCellId
1917 << " rsrp=" << (uint16_t)it.rsrpResult << " ("
1918 << nr::EutranMeasurementMapping::RsrpRange2Dbm(it.rsrpResult) << " dBm)"
1919 << " rsrq=" << (uint16_t)it.rsrqResult << " ("
1920 << nr::EutranMeasurementMapping::RsrqRange2Db(it.rsrqResult) << " dB)");
1921 }
1922
1923 } // end of else of if (measResults.measResultListEutra.size () == 0)
1924
1925 // verifying the report timing
1926 bool hasEnded = m_itExpectedTime == m_expectedTime.end();
1927 NS_TEST_ASSERT_MSG_EQ(hasEnded,
1928 false,
1929 "Reporting should not have occurred at "
1930 << Simulator::Now().GetSeconds() << "s");
1931 if (!hasEnded)
1932 {
1933 // using milliseconds to avoid floating-point comparison
1934 uint64_t timeNowMs = Simulator::Now().GetMilliSeconds();
1935 uint64_t timeExpectedMs = m_itExpectedTime->GetMilliSeconds();
1936 m_itExpectedTime++;
1937
1938 NS_TEST_ASSERT_MSG_EQ(timeNowMs,
1939 timeExpectedMs,
1940 "Reporting should not have occurred at this time");
1941
1942 } // end of if (!hasEnded)
1943
1944 } // end of if (report.measResults.measId == m_expectedMeasId)
1945
1946} // end of void NrUeMeasurementsPiecewiseTestCase3::RecvMeasurementReportCallback
1947
1948void
1949NrUeMeasurementsPiecewiseTestCase3::TeleportGnbNear()
1950{
1951 NS_LOG_FUNCTION(this);
1952 m_gnbMobility->SetPosition(Vector(700.0, 0.0, 0.0));
1953}
1954
1955// ===== LTE-UE-MEASUREMENTS-HANDOVER TEST SUITE =========================== //
1956
1957/*
1958 * Test Suite
1959 */
1960
1961NrUeMeasurementsHandoverTestSuite::NrUeMeasurementsHandoverTestSuite()
1962 : TestSuite("nr-ue-measurements-handover", Type::SYSTEM)
1963{
1964 std::list<NrRrcSap::ReportConfigEutra> sourceConfigList;
1965 std::list<NrRrcSap::ReportConfigEutra> targetConfigList;
1966 std::vector<Time> expectedTime;
1967 std::vector<uint8_t> expectedRsrp;
1968
1969 NrRrcSap::ReportConfigEutra sourceConfig;
1973 sourceConfig.threshold1.range = 0;
1975 sourceConfig.reportInterval = NrRrcSap::ReportConfigEutra::MS240;
1976 sourceConfigList.push_back(sourceConfig);
1977
1978 NrRrcSap::ReportConfigEutra targetConfig;
1982 targetConfig.threshold1.range = 0;
1984 targetConfig.reportInterval = NrRrcSap::ReportConfigEutra::MS240;
1985 targetConfigList.push_back(targetConfig);
1986
1987 // === Report interval difference ===
1988
1989 // decreasing report interval
1990 sourceConfigList.front().reportInterval = NrRrcSap::ReportConfigEutra::MS480;
1991 targetConfigList.front().reportInterval = NrRrcSap::ReportConfigEutra::MS240;
1992 expectedTime.clear();
1993 expectedTime << 200 << 680 << 1200 << 1440 << 1680 << 1920;
1994 expectedRsrp.clear();
1995 expectedRsrp << 55 << 55 << 53 << 53 << 53 << 53;
1996 AddTestCase(
1997 new NrUeMeasurementsHandoverTestCase("Handover test case - decreasing report interval",
1998 sourceConfigList,
1999 targetConfigList,
2000 expectedTime,
2001 expectedRsrp,
2002 Seconds(2)),
2003 TestCase::Duration::TAKES_FOREVER);
2004
2005 // increasing report interval
2006 sourceConfigList.front().reportInterval = NrRrcSap::ReportConfigEutra::MS120;
2007 targetConfigList.front().reportInterval = NrRrcSap::ReportConfigEutra::MS640;
2008 expectedTime.clear();
2009 expectedTime << 200 << 320 << 440 << 560 << 680 << 800 << 920 << 1200 << 1840;
2010 expectedRsrp.clear();
2011 expectedRsrp << 55 << 55 << 55 << 55 << 55 << 55 << 55 << 53 << 53;
2012 AddTestCase(
2013 new NrUeMeasurementsHandoverTestCase("Handover test case - increasing report interval",
2014 sourceConfigList,
2015 targetConfigList,
2016 expectedTime,
2017 expectedRsrp,
2018 Seconds(2)),
2019 TestCase::Duration::QUICK);
2020
2021 // === Event difference ===
2022
2023 sourceConfigList.front().reportInterval = NrRrcSap::ReportConfigEutra::MS240;
2024 targetConfigList.front().reportInterval = NrRrcSap::ReportConfigEutra::MS240;
2025 sourceConfigList.front().threshold1.range = 54;
2026 sourceConfigList.front().threshold2.range = 54;
2027 sourceConfigList.front().a3Offset = 1;
2028 targetConfigList.front().threshold1.range = 54;
2029 targetConfigList.front().threshold2.range = 54;
2030 targetConfigList.front().a3Offset = 1;
2031
2032 // Event A1 to Event A2
2033 sourceConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A1;
2034 targetConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A2;
2035 expectedTime.clear();
2036 expectedTime << 200 << 440 << 680 << 920 << 1200 << 1440 << 1680 << 1920;
2037 expectedRsrp.clear();
2038 expectedRsrp << 55 << 55 << 55 << 55 << 53 << 53 << 53 << 53;
2039 AddTestCase(new NrUeMeasurementsHandoverTestCase("Handover test case - Event A1 to Event A2",
2040 sourceConfigList,
2041 targetConfigList,
2042 expectedTime,
2043 expectedRsrp,
2044 Seconds(2)),
2045 TestCase::Duration::EXTENSIVE);
2046
2047 // Event A2 to Event A1
2048 sourceConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A2;
2049 targetConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A1;
2050 expectedTime.clear();
2051 expectedRsrp.clear();
2052 AddTestCase(new NrUeMeasurementsHandoverTestCase("Handover test case - Event A2 to Event A1",
2053 sourceConfigList,
2054 targetConfigList,
2055 expectedTime,
2056 expectedRsrp,
2057 Seconds(2)),
2058 TestCase::Duration::TAKES_FOREVER);
2059
2060 // Event A3 to Event A4
2061 sourceConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A3;
2062 targetConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A4;
2063 expectedTime.clear();
2064 expectedTime << 1200 << 1440 << 1680 << 1920;
2065 expectedRsrp.clear();
2066 expectedRsrp << 53 << 53 << 53 << 53;
2067 AddTestCase(new NrUeMeasurementsHandoverTestCase("Handover test case - Event A3 to Event A4",
2068 sourceConfigList,
2069 targetConfigList,
2070 expectedTime,
2071 expectedRsrp,
2072 Seconds(2)),
2073 TestCase::Duration::TAKES_FOREVER);
2074
2075 // Event A4 to Event A3
2076 sourceConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A4;
2077 targetConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A3;
2078 expectedTime.clear();
2079 expectedTime << 1200 << 1440 << 1680 << 1920;
2080 expectedRsrp.clear();
2081 expectedRsrp << 53 << 53 << 53 << 53;
2082 AddTestCase(new NrUeMeasurementsHandoverTestCase("Handover test case - Event A4 to Event A3",
2083 sourceConfigList,
2084 targetConfigList,
2085 expectedTime,
2086 expectedRsrp,
2087 Seconds(2)),
2088 TestCase::Duration::QUICK);
2089
2090 // Event A2 to Event A3
2091 sourceConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A2;
2092 targetConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A3;
2093 expectedTime.clear();
2094 expectedTime << 1200 << 1440 << 1680 << 1920;
2095 expectedRsrp.clear();
2096 expectedRsrp << 53 << 53 << 53 << 53;
2097 AddTestCase(new NrUeMeasurementsHandoverTestCase("Handover test case - Event A2 to Event A3",
2098 sourceConfigList,
2099 targetConfigList,
2100 expectedTime,
2101 expectedRsrp,
2102 Seconds(2)),
2103 TestCase::Duration::EXTENSIVE);
2104
2105 // Event A3 to Event A2
2106 sourceConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A3;
2107 targetConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A2;
2108 expectedTime.clear();
2109 expectedTime << 1200 << 1440 << 1680 << 1920;
2110 expectedRsrp.clear();
2111 expectedRsrp << 53 << 53 << 53 << 53;
2112 AddTestCase(new NrUeMeasurementsHandoverTestCase("Handover test case - Event A3 to Event A2",
2113 sourceConfigList,
2114 targetConfigList,
2115 expectedTime,
2116 expectedRsrp,
2117 Seconds(2)),
2118 TestCase::Duration::TAKES_FOREVER);
2119
2120 // Event A4 to Event A5
2121 sourceConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A4;
2122 targetConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A5;
2123 expectedTime.clear();
2124 expectedTime << 1200 << 1440 << 1680 << 1920;
2125 expectedRsrp.clear();
2126 expectedRsrp << 53 << 53 << 53 << 53;
2127 AddTestCase(new NrUeMeasurementsHandoverTestCase("Handover test case - Event A4 to Event A5",
2128 sourceConfigList,
2129 targetConfigList,
2130 expectedTime,
2131 expectedRsrp,
2132 Seconds(2)),
2133 TestCase::Duration::TAKES_FOREVER);
2134
2135 // Event A5 to Event A4
2136 sourceConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A5;
2137 targetConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A4;
2138 expectedTime.clear();
2139 expectedTime << 1200 << 1440 << 1680 << 1920;
2140 expectedRsrp.clear();
2141 expectedRsrp << 53 << 53 << 53 << 53;
2142 AddTestCase(new NrUeMeasurementsHandoverTestCase("Handover test case - Event A5 to Event A4",
2143 sourceConfigList,
2144 targetConfigList,
2145 expectedTime,
2146 expectedRsrp,
2147 Seconds(2)),
2148 TestCase::Duration::EXTENSIVE);
2149
2150 // === Threshold/offset difference ===
2151
2152 sourceConfigList.front().threshold1.range = 52;
2153 targetConfigList.front().threshold1.range = 56;
2154
2155 // Event A1
2156 sourceConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A1;
2157 targetConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A1;
2158 expectedTime.clear();
2159 expectedTime << 200 << 440 << 680 << 920;
2160 expectedRsrp.clear();
2161 expectedRsrp << 55 << 55 << 55 << 55;
2162 AddTestCase(
2163 new NrUeMeasurementsHandoverTestCase("Handover test case - Event A1 threshold difference",
2164 sourceConfigList,
2165 targetConfigList,
2166 expectedTime,
2167 expectedRsrp,
2168 Seconds(2)),
2169 TestCase::Duration::EXTENSIVE);
2170
2171 // Event A2
2172 sourceConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A2;
2173 targetConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A2;
2174 expectedTime.clear();
2175 expectedTime << 1200 << 1440 << 1680 << 1920;
2176 expectedRsrp.clear();
2177 expectedRsrp << 53 << 53 << 53 << 53;
2178 AddTestCase(
2179 new NrUeMeasurementsHandoverTestCase("Handover test case - Event A2 threshold difference",
2180 sourceConfigList,
2181 targetConfigList,
2182 expectedTime,
2183 expectedRsrp,
2184 Seconds(2)),
2185 TestCase::Duration::QUICK);
2186
2187 // Event A3
2188 sourceConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A3;
2189 sourceConfigList.front().a3Offset = -30;
2190 targetConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A3;
2191 targetConfigList.front().a3Offset = 30;
2192 expectedTime.clear();
2193 expectedTime << 200 << 440 << 680 << 920;
2194 expectedRsrp.clear();
2195 expectedRsrp << 55 << 55 << 55 << 55;
2196 AddTestCase(
2197 new NrUeMeasurementsHandoverTestCase("Handover test case - Event A3 offset difference",
2198 sourceConfigList,
2199 targetConfigList,
2200 expectedTime,
2201 expectedRsrp,
2202 Seconds(2)),
2203 TestCase::Duration::QUICK);
2204
2205 // Event A4
2206 sourceConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A4;
2207 targetConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A4;
2208 expectedTime.clear();
2209 expectedTime << 200 << 440 << 680 << 920;
2210 expectedRsrp.clear();
2211 expectedRsrp << 55 << 55 << 55 << 55;
2212 AddTestCase(
2213 new NrUeMeasurementsHandoverTestCase("Handover test case - Event A4 threshold difference",
2214 sourceConfigList,
2215 targetConfigList,
2216 expectedTime,
2217 expectedRsrp,
2218 Seconds(2)),
2219 TestCase::Duration::EXTENSIVE);
2220
2221 // Event A5
2222 sourceConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A5;
2223 sourceConfigList.front().threshold2.range = 52;
2224 targetConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A5;
2225 targetConfigList.front().threshold2.range = 56;
2226 expectedTime.clear();
2227 expectedRsrp.clear();
2228 AddTestCase(
2229 new NrUeMeasurementsHandoverTestCase("Handover test case - Event A5 threshold difference",
2230 sourceConfigList,
2231 targetConfigList,
2232 expectedTime,
2233 expectedRsrp,
2234 Seconds(2)),
2235 TestCase::Duration::EXTENSIVE);
2236
2237 // === Time-to-trigger (TTT) difference ===
2238
2239 sourceConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A1;
2240 sourceConfigList.front().a3Offset = 1;
2241 sourceConfigList.front().threshold1.range = 0;
2242 sourceConfigList.front().threshold2.range = 0;
2243 targetConfigList.front().eventId = NrRrcSap::ReportConfigEutra::EVENT_A1;
2244 targetConfigList.front().a3Offset = 1;
2245 targetConfigList.front().threshold1.range = 0;
2246 targetConfigList.front().threshold2.range = 0;
2247
2248 // decreasing time-to-trigger (short duration)
2249 sourceConfigList.front().timeToTrigger = 1024;
2250 targetConfigList.front().timeToTrigger = 100;
2251 expectedTime.clear();
2252 expectedTime << 1300 << 1540 << 1780;
2253 expectedRsrp.clear();
2254 expectedRsrp << 53 << 53 << 53;
2255 AddTestCase(new NrUeMeasurementsHandoverTestCase("Handover test case - decreasing TTT (short)",
2256 sourceConfigList,
2257 targetConfigList,
2258 expectedTime,
2259 expectedRsrp,
2260 Seconds(2)),
2261 TestCase::Duration::QUICK);
2262
2263 // decreasing time-to-trigger (longer duration)
2264 sourceConfigList.front().timeToTrigger = 1024;
2265 targetConfigList.front().timeToTrigger = 640;
2266 expectedTime.clear();
2267 expectedTime << 1224 << 1464 << 1704 << 1944 << 2840 << 3080 << 3320 << 3560 << 3800 << 4040;
2268 expectedRsrp.clear();
2269 expectedRsrp << 55 << 55 << 55 << 55 << 53 << 53 << 53 << 53 << 53 << 53;
2270 AddTestCase(new NrUeMeasurementsHandoverTestCase("Handover test case - decreasing TTT (long)",
2271 sourceConfigList,
2272 targetConfigList,
2273 expectedTime,
2274 expectedRsrp,
2275 Seconds(4.2)),
2276 TestCase::Duration::EXTENSIVE);
2277
2278} // end of NrUeMeasurementsHandoverTestSuite::NrUeMeasurementsHandoverTestSuite
2279
2285
2286/*
2287 * Test Case
2288 */
2289
2291 std::string name,
2292 std::list<NrRrcSap::ReportConfigEutra> sourceConfigList,
2293 std::list<NrRrcSap::ReportConfigEutra> targetConfigList,
2294 std::vector<Time> expectedTime,
2295 std::vector<uint8_t> expectedRsrp,
2296 Time duration)
2297 : TestCase(name),
2298 m_sourceConfigList(sourceConfigList),
2299 m_targetConfigList(targetConfigList),
2300 m_expectedTime(expectedTime),
2301 m_expectedRsrp(expectedRsrp),
2302 m_duration(duration)
2303{
2304 // input sanity check
2305 uint16_t size = m_expectedTime.size();
2306
2307 if (size != m_expectedRsrp.size())
2308 {
2309 NS_FATAL_ERROR("Vectors of expected results are not of the same size");
2310 }
2311
2312 m_itExpectedTime = m_expectedTime.begin();
2313 m_itExpectedRsrp = m_expectedRsrp.begin();
2314
2315 NS_LOG_INFO(this << " name=" << name);
2316}
2317
2318NrUeMeasurementsHandoverTestCase::~NrUeMeasurementsHandoverTestCase()
2319{
2320 NS_LOG_FUNCTION(this);
2321}
2322
2323void
2324NrUeMeasurementsHandoverTestCase::DoRun()
2325{
2326 NS_LOG_INFO(this << " " << GetName());
2327
2328 Ptr<NrHelper> nrHelper = CreateObject<NrHelper>();
2329 Ptr<NrPointToPointEpcHelper> nrEpcHelper = CreateObject<NrPointToPointEpcHelper>();
2330 nrHelper->SetEpcHelper(nrEpcHelper);
2331 nrHelper->SetAttribute("UseIdealRrc", BooleanValue(true));
2332 Config::SetDefault("ns3::NrGnbPhy::TxPower", DoubleValue(30));
2333 Config::SetDefault("ns3::NrUePhy::TxPower", DoubleValue(23));
2334
2335 // Disable Uplink Power Control
2336 Config::SetDefault("ns3::NrUePhy::EnableUplinkPowerControl", BooleanValue(false));
2337
2338 // Create Nodes: eNodeB and UE
2339 NodeContainer nrNodes;
2340 NodeContainer ueNodes;
2341 nrNodes.Create(2);
2342 ueNodes.Create(1);
2343
2344 /*
2345 * The topology is the following:
2346 *
2347 * eNodeB UE eNodeB
2348 * | | |
2349 * x ------------------- x ----------------------- x
2350 * 400 m 500 m
2351 */
2352
2353 Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
2354 positionAlloc->Add(Vector(0.0, 0.0, 0.0)); // Source eNodeB
2355 positionAlloc->Add(Vector(900.0, 0.0, 0.0)); // Target eNodeB
2356 positionAlloc->Add(Vector(400.0, 0.0, 0.0)); // UE
2357 MobilityHelper mobility;
2358 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
2359 mobility.SetPositionAllocator(positionAlloc);
2360 mobility.Install(nrNodes);
2361 mobility.Install(ueNodes);
2362
2363 // Create P-GW node
2364 Ptr<Node> pgw = nrEpcHelper->GetPgwNode();
2365
2366 // Create a single RemoteHost
2367 NodeContainer remoteHostContainer;
2368 remoteHostContainer.Create(1);
2369 Ptr<Node> remoteHost = remoteHostContainer.Get(0);
2370 InternetStackHelper internet;
2371 internet.Install(remoteHostContainer);
2372
2373 // Create the Internet
2374 PointToPointHelper p2ph;
2375 p2ph.SetDeviceAttribute("DataRate", DataRateValue(DataRate("100Gb/s")));
2376 p2ph.SetDeviceAttribute("Mtu", UintegerValue(1500));
2377 p2ph.SetChannelAttribute("Delay", TimeValue(Seconds(0.010)));
2378 NetDeviceContainer internetDevices = p2ph.Install(pgw, remoteHost);
2379 Ipv4AddressHelper ipv4h;
2380 ipv4h.SetBase("1.0.0.0", "255.0.0.0");
2381 Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign(internetDevices);
2382
2383 // Routing of the Internet Host (towards the NR network)
2384 Ipv4StaticRoutingHelper ipv4RoutingHelper;
2385 Ptr<Ipv4StaticRouting> remoteHostStaticRouting =
2386 ipv4RoutingHelper.GetStaticRouting(remoteHost->GetObject<Ipv4>());
2387 remoteHostStaticRouting->AddNetworkRouteTo(Ipv4Address("7.0.0.0"), Ipv4Mask("255.0.0.0"), 1);
2388
2389 // Enable layer-3 filtering
2390 Config::SetDefault("ns3::NrGnbRrc::RsrpFilterCoefficient", UintegerValue(4));
2391
2392 // Disable control channel error model
2393 auto bandwidthAndBWPPair = nrHelper->CreateBandwidthParts({{2.8e9, 5e6, 1}}, "UMa");
2394 // Create Devices and install them in the Nodes (eNB and UE)
2395 NetDeviceContainer nrDevs;
2396 NetDeviceContainer ueDevs;
2397 nrDevs = nrHelper->InstallGnbDevice(nrNodes, bandwidthAndBWPPair.second);
2398 ueDevs = nrHelper->InstallUeDevice(ueNodes, bandwidthAndBWPPair.second);
2399
2400 // Setup UE measurement configuration in eNodeBs
2401 uint8_t measId;
2402 Ptr<NrGnbRrc> nrRrc1 = nrDevs.Get(0)->GetObject<NrGnbNetDevice>()->GetRrc();
2403 Ptr<NrGnbRrc> nrRrc2 = nrDevs.Get(1)->GetObject<NrGnbNetDevice>()->GetRrc();
2404
2405 for (auto itReportConfig = m_sourceConfigList.begin();
2406 itReportConfig != m_sourceConfigList.end();
2407 itReportConfig++)
2408 {
2409 measId = nrRrc1->AddUeMeasReportConfig(*itReportConfig).at(0);
2410 m_expectedSourceCellMeasId.insert(measId);
2411 }
2412
2413 for (auto itReportConfig = m_targetConfigList.begin();
2414 itReportConfig != m_targetConfigList.end();
2415 itReportConfig++)
2416 {
2417 measId = nrRrc2->AddUeMeasReportConfig(*itReportConfig).at(0);
2418 m_expectedTargetCellMeasId.insert(measId);
2419 }
2420
2421 // Install the IP stack on the UEs
2422 internet.Install(ueNodes);
2423 Ipv4InterfaceContainer ueIpIfaces;
2424 ueIpIfaces = nrEpcHelper->AssignUeIpv4Address(NetDeviceContainer(ueDevs));
2425
2426 // Attach UE to serving eNodeB
2427 nrHelper->AttachToGnb(ueDevs.Get(0), nrDevs.Get(0));
2428
2429 // Add X2 interface
2430 nrHelper->AddX2Interface(nrNodes);
2431
2432 // Connect to trace sources in source eNodeB
2433 Config::Connect(
2434 "/NodeList/3/DeviceList/0/NrGnbRrc/RecvMeasurementReport",
2436
2437 // Connect to trace sources in target eNodeB
2438 Config::Connect(
2439 "/NodeList/4/DeviceList/0/NrGnbRrc/RecvMeasurementReport",
2441
2442 // Schedule handover
2443 nrHelper->HandoverRequest(MilliSeconds(m_duration.GetMilliSeconds() / 2),
2444 ueDevs.Get(0),
2445 nrDevs.Get(0),
2446 nrDevs.Get(1));
2447
2448 // Run simulation
2449 Simulator::Stop(m_duration);
2450 Simulator::Run();
2451 Simulator::Destroy();
2452
2453} // end of void NrUeMeasurementsHandoverTestCase::DoRun ()
2454
2455void
2456NrUeMeasurementsHandoverTestCase::DoTeardown()
2457{
2458 NS_LOG_FUNCTION(this);
2459 bool hasEnded = m_itExpectedTime == m_expectedTime.end();
2460 NS_TEST_ASSERT_MSG_EQ(hasEnded,
2461 true,
2462 "Reporting should have occurred at " << m_itExpectedTime->As(Time::S));
2463 hasEnded = m_itExpectedRsrp == m_expectedRsrp.end();
2464 NS_ASSERT(hasEnded);
2465}
2466
2467void
2469 uint64_t imsi,
2470 uint16_t cellId,
2471 uint16_t rnti,
2473{
2474 uint8_t measId = report.measResults.measId;
2475 NS_LOG_FUNCTION(this << context << (uint16_t)measId);
2476
2477 bool isCorrectMeasId;
2478 if (cellId == 1)
2479 {
2480 auto itMeasId = m_expectedSourceCellMeasId.find(measId);
2481 isCorrectMeasId = (itMeasId != m_expectedSourceCellMeasId.end());
2482 }
2483 else if (cellId == 2)
2484 {
2485 auto itMeasId = m_expectedTargetCellMeasId.find(measId);
2486 isCorrectMeasId = (itMeasId != m_expectedTargetCellMeasId.end());
2487 }
2488 else
2489 {
2490 NS_FATAL_ERROR("Invalid cell ID " << cellId);
2491 }
2492
2493 if (isCorrectMeasId)
2494 {
2495 // verifying the report completeness
2496 NrRrcSap::MeasResults measResults = report.measResults;
2497 NS_LOG_DEBUG(this << " Serving cellId=" << cellId
2498 << " rsrp=" << (uint16_t)measResults.measResultPCell.rsrpResult << " ("
2500 measResults.measResultPCell.rsrpResult)
2501 << " dBm)"
2502 << " rsrq=" << (uint16_t)measResults.measResultPCell.rsrqResult << " ("
2504 measResults.measResultPCell.rsrqResult)
2505 << " dB)");
2506
2507 // verifying reported best cells
2508 if (measResults.measResultListEutra.empty())
2509 {
2510 NS_TEST_ASSERT_MSG_EQ(measResults.haveMeasResultNeighCells,
2511 false,
2512 "Unexpected report content");
2513 }
2514 else
2515 {
2516 NS_TEST_ASSERT_MSG_EQ(measResults.haveMeasResultNeighCells,
2517 true,
2518 "Unexpected report content");
2519 auto it = measResults.measResultListEutra.begin();
2520 NS_ASSERT(it != measResults.measResultListEutra.end());
2521 NS_ASSERT(it->physCellId != cellId);
2522 NS_ASSERT(it->physCellId <= 2);
2523 NS_TEST_ASSERT_MSG_EQ(it->haveCgiInfo,
2524 false,
2525 "Report contains cgi-info, which is not supported");
2526 NS_TEST_ASSERT_MSG_EQ(it->haveRsrpResult,
2527 true,
2528 "Report does not contain measured RSRP result");
2529 NS_TEST_ASSERT_MSG_EQ(it->haveRsrqResult,
2530 true,
2531 "Report does not contain measured RSRQ result");
2532 NS_LOG_DEBUG(
2533 this << " Neighbour cellId=" << it->physCellId
2534 << " rsrp=" << (uint16_t)it->rsrpResult << " ("
2535 << nr::EutranMeasurementMapping::RsrpRange2Dbm(it->rsrpResult) << " dBm)"
2536 << " rsrq=" << (uint16_t)it->rsrqResult << " ("
2537 << nr::EutranMeasurementMapping::RsrqRange2Db(it->rsrqResult) << " dB)");
2538
2539 } // end of else of if (measResults.measResultListEutra.size () == 0)
2540
2541 // verifying the report timing
2542 bool hasEnded = m_itExpectedTime == m_expectedTime.end();
2543 NS_TEST_ASSERT_MSG_EQ(hasEnded,
2544 false,
2545 "Reporting should not have occurred at "
2546 << Simulator::Now().As(Time::S));
2547 if (!hasEnded)
2548 {
2549 hasEnded = m_itExpectedRsrp == m_expectedRsrp.end();
2550 NS_ASSERT(!hasEnded);
2551
2552 // using milliseconds to avoid floating-point comparison
2553 uint64_t timeNowMs = Simulator::Now().GetMilliSeconds();
2554 uint64_t timeExpectedMs = m_itExpectedTime->GetMilliSeconds();
2555 m_itExpectedTime++;
2556
2557 uint16_t observedRsrp = measResults.measResultPCell.rsrpResult;
2558 uint16_t referenceRsrp = *m_itExpectedRsrp;
2559 m_itExpectedRsrp++;
2560
2561 NS_TEST_ASSERT_MSG_EQ(timeNowMs,
2562 timeExpectedMs,
2563 "Reporting should not have occurred at this time");
2564 NS_TEST_ASSERT_MSG_EQ(observedRsrp,
2565 referenceRsrp,
2566 "The RSRP observed differs with the reference RSRP");
2567
2568 } // end of if (!hasEnded)
2569
2570 } // end of if (report.measResults.measId == correctMeasId)
2571
2572} // end of void NrUeMeasurementsHandoverTestCase::RecvMeasurementReportCallback
Testing UE measurements in NR with simulation of 2 eNodeB and 1 UE in a handover configuration.
NrUeMeasurementsHandoverTestCase(std::string name, std::list< NrRrcSap::ReportConfigEutra > sourceConfigList, std::list< NrRrcSap::ReportConfigEutra > targetConfigList, std::vector< Time > expectedTime, std::vector< uint8_t > expectedRsrp, Time duration)
void RecvMeasurementReportCallback(std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti, NrRrcSap::MeasurementReport report)
Triggers when either one of the eNodeBs receives measurement report from UE, then perform verificatio...
Test suite for generating calls to UE measurements test case ns3::NrUeMeasurementsHandoverTestCase.
Testing UE measurements in NR with simulation of 1 eNodeB and 1 UE in piecewise configuration and 120...
NrUeMeasurementsPiecewiseTestCase1(std::string name, NrRrcSap::ReportConfigEutra config, std::vector< Time > expectedTime, std::vector< uint8_t > expectedRsrp)
void RecvMeasurementReportCallback(std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti, NrRrcSap::MeasurementReport report)
Triggers when eNodeB receives measurement report from UE, then perform verification on it.
Testing UE measurements in NR with simulation of 2 eNodeB and 1 UE in piecewise configuration and 240...
NrUeMeasurementsPiecewiseTestCase2(std::string name, NrRrcSap::ReportConfigEutra config, std::vector< Time > expectedTime, std::vector< uint8_t > expectedRsrp)
void RecvMeasurementReportCallback(std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti, NrRrcSap::MeasurementReport report)
Triggers when eNodeB receives measurement report from UE, then perform verification on it.
Testing UE measurements in NR with simulation of 3 eNodeB and 1 UE in piecewise configuration and 240...
NrUeMeasurementsPiecewiseTestCase3(std::string name, NrRrcSap::ReportConfigEutra config, std::vector< Time > expectedTime)
void RecvMeasurementReportCallback(std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti, NrRrcSap::MeasurementReport report)
Triggers when eNodeB receives measurement report from UE, then perform verification on it.
Test suite for generating calls to UE measurements test case ns3::NrUeMeasurementsPiecewiseTestCase1.
Test suite for generating calls to UE measurements test case ns3::NrUeMeasurementsPiecewiseTestCase2.
Test suite for generating calls to UE measurements test case ns3::NrUeMeasurementsPiecewiseTestCase3.
Test that UE measurements calculation works properly in a scenario with 2 eNodeBs and 2UEs....
NrUeMeasurementsTestCase(std::string name, double d1, double d2, double rsrpDbmUe1, double rsrpDbmUe2, double rsrqDbUe1, double rsrqDbUe2)
void RecvMeasurementReport(uint64_t imsi, uint16_t cellId, uint16_t rnti, NrRrcSap::MeasurementReport meas)
void ReportUeMeasurements(uint16_t rnti, uint16_t cellId, double rsrp, double rsrq, bool servingCell)
Test that UE Measurements (see 36.214) calculation works fine in a multi-cell interference scenario.
@ ShannonModel
Shannon based model (very conservative)
Definition nr-amc.h:80
This class contains the specification of EPS Bearers.
@ GBR_CONV_VOICE
GBR Conversational Voice.
The NrGnbNetDevice class.
static double RsrqRange2Db(uint8_t range)
Definition nr-common.cc:231
static double RsrpRange2Dbm(uint8_t range)
Definition nr-common.cc:215
static uint8_t Dbm2RsrpRange(double dbm)
Definition nr-common.cc:223
static uint8_t Db2RsrqRange(double db)
Definition nr-common.cc:239
static NrUeMeasurementsPiecewiseTestSuite3 nrUeMeasurementsPiecewiseTestSuite3
static NrUeMeasurementsTestSuite nrUeMeasurementsTestSuite
static NrUeMeasurementsPiecewiseTestSuite1 nrUeMeasurementsPiecewiseTestSuite1
static NrUeMeasurementsHandoverTestSuite nrUeMeasurementsHandoverTestSuite
static NrUeMeasurementsPiecewiseTestSuite2 nrUeMeasurementsPiecewiseTestSuite2
uint8_t rsrpResult
the RSRP result
Definition nr-rrc-sap.h:680
uint8_t rsrqResult
the RSRQ result
Definition nr-rrc-sap.h:681
MeasResults structure.
Definition nr-rrc-sap.h:723
uint8_t measId
measure ID
Definition nr-rrc-sap.h:724
bool haveMeasResultNeighCells
have measure result neighbor cells
Definition nr-rrc-sap.h:726
MeasResultPCell measResultPCell
measurement result primary cell
Definition nr-rrc-sap.h:725
std::list< MeasResultEutra > measResultListEutra
measure result list eutra
Definition nr-rrc-sap.h:727
MeasurementReport structure.
Definition nr-rrc-sap.h:954
MeasResults measResults
measure results
Definition nr-rrc-sap.h:955
Specifies criteria for triggering of an E-UTRA measurement reporting event.
Definition nr-rrc-sap.h:360
enum ns3::NrRrcSap::ReportConfigEutra::@5 triggerQuantity
Trigger type enumeration.
@ RSRP
Reference Signal Received Power.
Definition nr-rrc-sap.h:412
enum ns3::NrRrcSap::ReportConfigEutra::@7 reportInterval
Report interval enumeration.
@ EVENT_A2
Event A2: Serving becomes worse than absolute threshold.
Definition nr-rrc-sap.h:372
@ EVENT_A1
Event A1: Serving becomes better than absolute threshold.
Definition nr-rrc-sap.h:371
@ EVENT_A4
Event A4: Neighbour becomes better than absolute threshold.
Definition nr-rrc-sap.h:374
@ EVENT_A3
Event A3: Neighbour becomes amount of offset better than PCell.
Definition nr-rrc-sap.h:373
ThresholdEutra threshold2
Threshold for event A5.
Definition nr-rrc-sap.h:381
enum ns3::NrRrcSap::ReportConfigEutra::@4 eventId
Event enumeration.
ThresholdEutra threshold1
Threshold for event A1, A2, A4, and A5.
Definition nr-rrc-sap.h:380
enum ns3::NrRrcSap::ReportConfigEutra::@3 triggerType
Trigger enumeration.
enum ns3::NrRrcSap::ThresholdEutra::@2 choice
Threshold enumeration.
uint8_t range
Value range used in RSRP/RSRQ threshold.
Definition nr-rrc-sap.h:355
@ THRESHOLD_RSRP
RSRP is used for the threshold.
Definition nr-rrc-sap.h:351