A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
test-lte-x2-handover.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Nicola Baldo <nbaldo@cttc.es>
7 */
8
9#include "ns3/core-module.h"
10#include "ns3/internet-module.h"
11#include "ns3/lte-module.h"
12#include "ns3/mobility-module.h"
13#include "ns3/network-module.h"
14#include "ns3/packet-sink-helper.h"
15#include "ns3/packet-sink.h"
16#include "ns3/point-to-point-module.h"
17#include "ns3/udp-client-server-helper.h"
18
19using namespace ns3;
20
21NS_LOG_COMPONENT_DEFINE("LteX2HandoverTest");
22
23/**
24 * @ingroup lte-test
25 *
26 * @brief HandoverEvent structure
27 */
29{
30 Time startTime; ///< start time
31 uint32_t ueDeviceIndex; ///< UE device index
32 uint32_t sourceEnbDeviceIndex; ///< source ENB device index
33 uint32_t targetEnbDeviceIndex; ///< target ENB device index
34};
35
36/**
37 * @ingroup lte-test
38 *
39 * @brief Test X2 Handover. In this test is used NoOpHandoverAlgorithm and
40 * the request for handover is generated manually, and it is not based on measurements.
41 */
43{
44 public:
45 /**
46 *
47 *
48 * @param nUes number of UEs in the test
49 * @param nDedicatedBearers number of bearers to be activated per UE
50 * @param handoverEventList
51 * @param handoverEventListName
52 * @param schedulerType the scheduler type
53 * @param admitHo
54 * @param useIdealRrc true if the ideal RRC should be used
55 */
57 uint32_t nDedicatedBearers,
58 std::list<HandoverEvent> handoverEventList,
59 std::string handoverEventListName,
60 std::string schedulerType,
61 bool admitHo,
62 bool useIdealRrc);
63
64 private:
65 /**
66 * Build name string
67 * @param nUes number of UEs in the test
68 * @param nDedicatedBearers number of bearers to be activated per UE
69 * @param handoverEventListName
70 * @param schedulerType the scheduler type
71 * @param admitHo
72 * @param useIdealRrc true if the ideal RRC should be used
73 * @returns the name string
74 */
75 static std::string BuildNameString(uint32_t nUes,
76 uint32_t nDedicatedBearers,
77 std::string handoverEventListName,
78 std::string schedulerType,
79 bool admitHo,
80 bool useIdealRrc);
81 void DoRun() override;
82 /**
83 * Check connected function
84 * @param ueDevice the UE device
85 * @param enbDevice the ENB device
86 */
87 void CheckConnected(Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice);
88
89 /**
90 * Teleport UE between both eNBs of the test
91 * @param ueNode the UE node
92 */
93 void TeleportUeToMiddle(Ptr<Node> ueNode);
94
95 /**
96 * Teleport UE near the target eNB of the handover
97 * @param ueNode the UE node
98 * @param enbNode the target eNB node
99 */
100 void TeleportUeNearTargetEnb(Ptr<Node> ueNode, Ptr<Node> enbNode);
101
102 uint32_t m_nUes; ///< number of UEs in the test
103 uint32_t m_nDedicatedBearers; ///< number of UEs in the test
104 std::list<HandoverEvent> m_handoverEventList; ///< handover event list
105 std::string m_handoverEventListName; ///< handover event list name
106 bool m_epc; ///< whether to use EPC
107 std::string m_schedulerType; ///< scheduler type
108 bool m_admitHo; ///< whether to admit the handover request
109 bool m_useIdealRrc; ///< whether to use the ideal RRC
112
113 /**
114 * @ingroup lte-test
115 *
116 * @brief BearerData structure
117 */
119 {
120 uint32_t bid; ///< BID
123 uint32_t dlOldTotalRx; ///< DL old total receive
124 uint32_t ulOldTotalRx; ///< UL old total receive
125 };
126
127 /**
128 * @ingroup lte-test
129 *
130 * @brief UeData structure
131 */
132 struct UeData
133 {
134 uint32_t id; ///< ID
135 std::list<BearerData> bearerDataList; ///< bearer ID list
136 };
137
138 /**
139 * @brief Save stats after handover function
140 * @param ueIndex the index of the UE
141 */
142 void SaveStatsAfterHandover(uint32_t ueIndex);
143 /**
144 * @brief Check stats a while after handover function
145 * @param ueIndex the index of the UE
146 */
148
149 std::vector<UeData> m_ueDataVector; ///< UE data vector
150
151 const Time m_maxHoDuration; ///< maximum HO duration
152 const Time m_statsDuration; ///< stats duration
153 const Time m_udpClientInterval; ///< UDP client interval
154 const uint32_t m_udpClientPktSize; ///< UDP client packet size
155};
156
157std::string
159 uint32_t nDedicatedBearers,
160 std::string handoverEventListName,
161 std::string schedulerType,
162 bool admitHo,
163 bool useIdealRrc)
164{
165 std::ostringstream oss;
166 oss << " nUes=" << nUes << " nDedicatedBearers=" << nDedicatedBearers << " " << schedulerType
167 << " admitHo=" << admitHo << " hoList: " << handoverEventListName;
168 if (useIdealRrc)
169 {
170 oss << ", ideal RRC";
171 }
172 else
173 {
174 oss << ", real RRC";
175 }
176 return oss.str();
177}
178
180 uint32_t nDedicatedBearers,
181 std::list<HandoverEvent> handoverEventList,
182 std::string handoverEventListName,
183 std::string schedulerType,
184 bool admitHo,
185 bool useIdealRrc)
187 nDedicatedBearers,
188 handoverEventListName,
189 schedulerType,
190 admitHo,
191 useIdealRrc)),
192 m_nUes(nUes),
193 m_nDedicatedBearers(nDedicatedBearers),
194 m_handoverEventList(handoverEventList),
195 m_handoverEventListName(handoverEventListName),
196 m_epc(true),
197 m_schedulerType(schedulerType),
198 m_admitHo(admitHo),
199 m_useIdealRrc(useIdealRrc),
204
205{
206}
207
208void
210{
215 m_admitHo,
217
218 uint32_t previousSeed = RngSeedManager::GetSeed();
219 uint64_t previousRun = RngSeedManager::GetRun();
221 // This test is sensitive to random variable stream assignments
224 Config::SetDefault("ns3::UdpClient::Interval", TimeValue(m_udpClientInterval));
225 Config::SetDefault("ns3::UdpClient::MaxPackets", UintegerValue(1000000));
226 Config::SetDefault("ns3::UdpClient::PacketSize", UintegerValue(m_udpClientPktSize));
227
228 // Disable Uplink Power Control
229 Config::SetDefault("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue(false));
230
231 int64_t stream = 1;
232
234 m_lteHelper->SetAttribute("PathlossModel",
235 StringValue("ns3::FriisSpectrumPropagationLossModel"));
236 m_lteHelper->SetSchedulerType(m_schedulerType);
237 m_lteHelper->SetHandoverAlgorithmType(
238 "ns3::NoOpHandoverAlgorithm"); // disable automatic handover
239 m_lteHelper->SetAttribute("UseIdealRrc", BooleanValue(m_useIdealRrc));
240
241 NodeContainer enbNodes;
242 enbNodes.Create(2);
243 NodeContainer ueNodes;
244 ueNodes.Create(m_nUes);
245
246 if (m_epc)
247 {
249 m_lteHelper->SetEpcHelper(m_epcHelper);
250 }
251
253 positionAlloc->Add(Vector(-3000, 0, 0)); // enb0
254 positionAlloc->Add(Vector(3000, 0, 0)); // enb1
255 for (uint32_t i = 0; i < m_nUes; i++)
256 {
257 positionAlloc->Add(Vector(-3000, 100, 0));
258 }
259 MobilityHelper mobility;
260 mobility.SetPositionAllocator(positionAlloc);
261 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
262 mobility.Install(enbNodes);
263 mobility.Install(ueNodes);
264
265 NetDeviceContainer enbDevices;
266 enbDevices = m_lteHelper->InstallEnbDevice(enbNodes);
267 // Call AssignStreams in the EpcHelper only once by setting 'assignEpcStreams' only once
268 // Then, increment the stream value by 1000 (a magic number that should ensure that there
269 // are no overlapping stream assignments) each time that AssignStreams is called,
270 // to lessen the possibility that random variable stream assignment changes propagate
271 // to other objects.
272 m_lteHelper->AssignStreams(enbDevices, stream, false);
273 stream += 1000;
274 for (auto it = enbDevices.Begin(); it != enbDevices.End(); ++it)
275 {
276 Ptr<LteEnbRrc> enbRrc = (*it)->GetObject<LteEnbNetDevice>()->GetRrc();
277 enbRrc->SetAttribute("AdmitHandoverRequest", BooleanValue(m_admitHo));
278 }
279
280 NetDeviceContainer ueDevices;
281 ueDevices = m_lteHelper->InstallUeDevice(ueNodes);
282 m_lteHelper->AssignStreams(ueDevices, stream, true);
283 stream += 1000;
284
285 Ipv4Address remoteHostAddr;
286 Ipv4StaticRoutingHelper ipv4RoutingHelper;
287 Ipv4InterfaceContainer ueIpIfaces;
288 Ptr<Node> remoteHost;
289 if (m_epc)
290 {
291 // Create a single RemoteHost
292 NodeContainer remoteHostContainer;
293 remoteHostContainer.Create(1);
294 remoteHost = remoteHostContainer.Get(0);
295 InternetStackHelper internet;
296 internet.Install(remoteHostContainer);
297
298 // Create the Internet
300 p2ph.SetDeviceAttribute("DataRate", DataRateValue(DataRate("100Gb/s")));
301 p2ph.SetDeviceAttribute("Mtu", UintegerValue(1500));
302 p2ph.SetChannelAttribute("Delay", TimeValue(Seconds(0.010)));
303 Ptr<Node> pgw = m_epcHelper->GetPgwNode();
304 NetDeviceContainer internetDevices = p2ph.Install(pgw, remoteHost);
305 Ipv4AddressHelper ipv4h;
306 ipv4h.SetBase("1.0.0.0", "255.0.0.0");
307 Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign(internetDevices);
308 // in this container, interface 0 is the pgw, 1 is the remoteHost
309 remoteHostAddr = internetIpIfaces.GetAddress(1);
310
311 Ipv4StaticRoutingHelper ipv4RoutingHelper;
312 Ptr<Ipv4StaticRouting> remoteHostStaticRouting =
313 ipv4RoutingHelper.GetStaticRouting(remoteHost->GetObject<Ipv4>());
314 remoteHostStaticRouting->AddNetworkRouteTo(Ipv4Address("7.0.0.0"),
315 Ipv4Mask("255.0.0.0"),
316 1);
317
318 // Install the IP stack on the UEs
319 internet.Install(ueNodes);
320 ueIpIfaces = m_epcHelper->AssignUeIpv4Address(NetDeviceContainer(ueDevices));
321 }
322
323 // attachment (needs to be done after IP stack configuration)
324 // all UEs attached to eNB 0 at the beginning
325 m_lteHelper->Attach(ueDevices, enbDevices.Get(0));
326
327 if (m_epc)
328 {
329 // always true: bool epcDl = true;
330 // always true: bool epcUl = true;
331 // the rest of this block is copied from lena-dual-stripe
332
333 // Install and start applications on UEs and remote host
334 uint16_t dlPort = 10000;
335 uint16_t ulPort = 20000;
336
337 // randomize a bit start times to avoid simulation artifacts
338 // (e.g., buffer overflows due to packet transmissions happening
339 // exactly at the same time)
341 startTimeSeconds->SetAttribute("Min", DoubleValue(0));
342 startTimeSeconds->SetAttribute("Max", DoubleValue(0.010));
343 startTimeSeconds->SetStream(stream++);
344
345 for (uint32_t u = 0; u < ueNodes.GetN(); ++u)
346 {
347 Ptr<Node> ue = ueNodes.Get(u);
348 // Set the default gateway for the UE
349 Ptr<Ipv4StaticRouting> ueStaticRouting =
350 ipv4RoutingHelper.GetStaticRouting(ue->GetObject<Ipv4>());
351 ueStaticRouting->SetDefaultRoute(m_epcHelper->GetUeDefaultGatewayAddress(), 1);
352
353 UeData ueData;
354
355 for (uint32_t b = 0; b < m_nDedicatedBearers; ++b)
356 {
357 ++dlPort;
358 ++ulPort;
359
360 ApplicationContainer clientApps;
361 ApplicationContainer serverApps;
362 BearerData bearerData = BearerData();
363
364 // always true: if (epcDl)
365 {
366 UdpClientHelper dlClientHelper(ueIpIfaces.GetAddress(u), dlPort);
367 clientApps.Add(dlClientHelper.Install(remoteHost));
368 PacketSinkHelper dlPacketSinkHelper(
369 "ns3::UdpSocketFactory",
371 ApplicationContainer sinkContainer = dlPacketSinkHelper.Install(ue);
372 bearerData.dlSink = sinkContainer.Get(0)->GetObject<PacketSink>();
373 serverApps.Add(sinkContainer);
374 }
375 // always true: if (epcUl)
376 {
377 UdpClientHelper ulClientHelper(remoteHostAddr, ulPort);
378 clientApps.Add(ulClientHelper.Install(ue));
379 PacketSinkHelper ulPacketSinkHelper(
380 "ns3::UdpSocketFactory",
382 ApplicationContainer sinkContainer = ulPacketSinkHelper.Install(remoteHost);
383 bearerData.ulSink = sinkContainer.Get(0)->GetObject<PacketSink>();
384 serverApps.Add(sinkContainer);
385 }
386
388 // always true: if (epcDl)
389 {
391 dlpf.localPortStart = dlPort;
392 dlpf.localPortEnd = dlPort;
393 tft->Add(dlpf);
394 }
395 // always true: if (epcUl)
396 {
398 ulpf.remotePortStart = ulPort;
399 ulpf.remotePortEnd = ulPort;
400 tft->Add(ulpf);
401 }
402
403 // always true: if (epcDl || epcUl)
404 {
406 m_lteHelper->ActivateDedicatedEpsBearer(ueDevices.Get(u), bearer, tft);
407 }
408 double d = startTimeSeconds->GetValue();
409 Time startTime = Seconds(d);
410 serverApps.Start(startTime);
411 clientApps.Start(startTime);
412
413 ueData.bearerDataList.push_back(bearerData);
414 }
415
416 m_ueDataVector.push_back(ueData);
417 }
418 }
419 else // (epc == false)
420 {
421 // for radio bearer activation purposes, consider together home UEs and macro UEs
422 for (uint32_t u = 0; u < ueDevices.GetN(); ++u)
423 {
424 Ptr<NetDevice> ueDev = ueDevices.Get(u);
425 for (uint32_t b = 0; b < m_nDedicatedBearers; ++b)
426 {
428 EpsBearer bearer(q);
429 m_lteHelper->ActivateDataRadioBearer(ueDev, bearer);
430 }
431 }
432 }
433
434 m_lteHelper->AddX2Interface(enbNodes);
435
436 // check initial RRC connection
437 const Time maxRrcConnectionEstablishmentDuration = Seconds(0.080);
438 for (auto it = ueDevices.Begin(); it != ueDevices.End(); ++it)
439 {
440 Simulator::Schedule(maxRrcConnectionEstablishmentDuration,
442 this,
443 *it,
444 enbDevices.Get(0));
445 }
446
447 // schedule handover events and corresponding checks
448
450 for (auto hoEventIt = m_handoverEventList.begin(); hoEventIt != m_handoverEventList.end();
451 ++hoEventIt)
452 {
453 // Teleport the UE between both eNBs just before the handover starts
454 Simulator::Schedule(hoEventIt->startTime - MilliSeconds(10),
456 this,
457 ueNodes.Get(hoEventIt->ueDeviceIndex));
458
459 Simulator::Schedule(hoEventIt->startTime,
461 this,
462 ueDevices.Get(hoEventIt->ueDeviceIndex),
463 enbDevices.Get(hoEventIt->sourceEnbDeviceIndex));
464
465 m_lteHelper->HandoverRequest(hoEventIt->startTime,
466 ueDevices.Get(hoEventIt->ueDeviceIndex),
467 enbDevices.Get(hoEventIt->sourceEnbDeviceIndex),
468 enbDevices.Get(hoEventIt->targetEnbDeviceIndex));
469
470 // Once the handover is finished, teleport the UE near the target eNB
471 Simulator::Schedule(hoEventIt->startTime + MilliSeconds(40),
473 this,
474 ueNodes.Get(hoEventIt->ueDeviceIndex),
475 enbNodes.Get(m_admitHo ? hoEventIt->targetEnbDeviceIndex
476 : hoEventIt->sourceEnbDeviceIndex));
477
478 Time hoEndTime = hoEventIt->startTime + m_maxHoDuration;
479 Simulator::Schedule(hoEndTime,
481 this,
482 ueDevices.Get(hoEventIt->ueDeviceIndex),
483 enbDevices.Get(m_admitHo ? hoEventIt->targetEnbDeviceIndex
484 : hoEventIt->sourceEnbDeviceIndex));
485 Simulator::Schedule(hoEndTime,
487 this,
488 hoEventIt->ueDeviceIndex);
489
490 Time checkStatsAfterHoTime = hoEndTime + m_statsDuration;
491 Simulator::Schedule(checkStatsAfterHoTime,
493 this,
494 hoEventIt->ueDeviceIndex);
495 if (stopTime <= checkStatsAfterHoTime)
496 {
497 stopTime = checkStatsAfterHoTime + MilliSeconds(1);
498 }
499 }
500
501 // m_lteHelper->EnableRlcTraces ();
502 // m_lteHelper->EnablePdcpTraces();
503
505
507
509
510 // Undo changes to default settings
512 // Restore the previous settings of RngSeed and RngRun
513 RngSeedManager::SetSeed(previousSeed);
514 RngSeedManager::SetRun(previousRun);
515}
516
517void
519{
520 Ptr<LteUeNetDevice> ueLteDevice = ueDevice->GetObject<LteUeNetDevice>();
521 Ptr<LteUeRrc> ueRrc = ueLteDevice->GetRrc();
522 NS_TEST_ASSERT_MSG_EQ(ueRrc->GetState(), LteUeRrc::CONNECTED_NORMALLY, "Wrong LteUeRrc state!");
523
524 Ptr<LteEnbNetDevice> enbLteDevice = enbDevice->GetObject<LteEnbNetDevice>();
525 Ptr<LteEnbRrc> enbRrc = enbLteDevice->GetRrc();
526 uint16_t rnti = ueRrc->GetRnti();
527 Ptr<UeManager> ueManager = enbRrc->GetUeManager(rnti);
528 NS_TEST_ASSERT_MSG_NE(ueManager, nullptr, "RNTI " << rnti << " not found in eNB");
529
530 UeManager::State ueManagerState = ueManager->GetState();
531 NS_TEST_ASSERT_MSG_EQ(ueManagerState, UeManager::CONNECTED_NORMALLY, "Wrong UeManager state!");
532
533 uint16_t ueCellId = ueRrc->GetCellId();
534 uint16_t enbCellId = enbLteDevice->GetCellId();
535 uint8_t ueDlBandwidth = ueRrc->GetDlBandwidth();
536 uint8_t enbDlBandwidth = enbLteDevice->GetDlBandwidth();
537 uint8_t ueUlBandwidth = ueRrc->GetUlBandwidth();
538 uint8_t enbUlBandwidth = enbLteDevice->GetUlBandwidth();
539 uint8_t ueDlEarfcn = ueRrc->GetDlEarfcn();
540 uint8_t enbDlEarfcn = enbLteDevice->GetDlEarfcn();
541 uint8_t ueUlEarfcn = ueRrc->GetUlEarfcn();
542 uint8_t enbUlEarfcn = enbLteDevice->GetUlEarfcn();
543 uint64_t ueImsi = ueLteDevice->GetImsi();
544 uint64_t enbImsi = ueManager->GetImsi();
545
546 NS_TEST_ASSERT_MSG_EQ(ueImsi, enbImsi, "inconsistent IMSI");
547 NS_TEST_ASSERT_MSG_EQ(ueCellId, enbCellId, "inconsistent CellId");
548 NS_TEST_ASSERT_MSG_EQ(ueDlBandwidth, enbDlBandwidth, "inconsistent DlBandwidth");
549 NS_TEST_ASSERT_MSG_EQ(ueUlBandwidth, enbUlBandwidth, "inconsistent UlBandwidth");
550 NS_TEST_ASSERT_MSG_EQ(ueDlEarfcn, enbDlEarfcn, "inconsistent DlEarfcn");
551 NS_TEST_ASSERT_MSG_EQ(ueUlEarfcn, enbUlEarfcn, "inconsistent UlEarfcn");
552
553 ObjectMapValue enbDataRadioBearerMapValue;
554 ueManager->GetAttribute("DataRadioBearerMap", enbDataRadioBearerMapValue);
555 NS_TEST_ASSERT_MSG_EQ(enbDataRadioBearerMapValue.GetN(),
557 "wrong num bearers at eNB");
558
559 ObjectMapValue ueDataRadioBearerMapValue;
560 ueRrc->GetAttribute("DataRadioBearerMap", ueDataRadioBearerMapValue);
561 NS_TEST_ASSERT_MSG_EQ(ueDataRadioBearerMapValue.GetN(),
563 "wrong num bearers at UE");
564
565 auto enbBearerIt = enbDataRadioBearerMapValue.Begin();
566 auto ueBearerIt = ueDataRadioBearerMapValue.Begin();
567 while (enbBearerIt != enbDataRadioBearerMapValue.End() &&
568 ueBearerIt != ueDataRadioBearerMapValue.End())
569 {
570 Ptr<LteDataRadioBearerInfo> enbDrbInfo =
571 enbBearerIt->second->GetObject<LteDataRadioBearerInfo>();
573 ueBearerIt->second->GetObject<LteDataRadioBearerInfo>();
574 // NS_TEST_ASSERT_MSG_EQ (enbDrbInfo->m_epsBearer, ueDrbInfo->m_epsBearer, "epsBearer
575 // differs");
576 NS_TEST_ASSERT_MSG_EQ((uint32_t)enbDrbInfo->m_epsBearerIdentity,
577 (uint32_t)ueDrbInfo->m_epsBearerIdentity,
578 "epsBearerIdentity differs");
579 NS_TEST_ASSERT_MSG_EQ((uint32_t)enbDrbInfo->m_drbIdentity,
580 (uint32_t)ueDrbInfo->m_drbIdentity,
581 "drbIdentity differs");
582 // NS_TEST_ASSERT_MSG_EQ (enbDrbInfo->m_rlcConfig, ueDrbInfo->m_rlcConfig, "rlcConfig
583 // differs");
584 NS_TEST_ASSERT_MSG_EQ((uint32_t)enbDrbInfo->m_logicalChannelIdentity,
585 (uint32_t)ueDrbInfo->m_logicalChannelIdentity,
586 "logicalChannelIdentity differs");
587 // NS_TEST_ASSERT_MSG_EQ (enbDrbInfo->m_logicalChannelConfig,
588 // ueDrbInfo->m_logicalChannelConfig, "logicalChannelConfig differs");
589
590 ++enbBearerIt;
591 ++ueBearerIt;
592 }
593 NS_ASSERT_MSG(enbBearerIt == enbDataRadioBearerMapValue.End(), "too many bearers at eNB");
594 NS_ASSERT_MSG(ueBearerIt == ueDataRadioBearerMapValue.End(), "too many bearers at UE");
595}
596
597void
599{
600 Ptr<MobilityModel> ueMobility = ueNode->GetObject<MobilityModel>();
601 ueMobility->SetPosition(Vector(0.0, 0.0, 0.0));
602}
603
604void
606{
607 Ptr<MobilityModel> enbMobility = enbNode->GetObject<MobilityModel>();
608 Vector pos = enbMobility->GetPosition();
609
610 Ptr<MobilityModel> ueMobility = ueNode->GetObject<MobilityModel>();
611 ueMobility->SetPosition(pos + Vector(0.0, 100.0, 0.0));
612}
613
614void
616{
617 for (auto it = m_ueDataVector.at(ueIndex).bearerDataList.begin();
618 it != m_ueDataVector.at(ueIndex).bearerDataList.end();
619 ++it)
620 {
621 it->dlOldTotalRx = it->dlSink->GetTotalRx();
622 it->ulOldTotalRx = it->ulSink->GetTotalRx();
623 }
624}
625
626void
628{
629 uint32_t b = 1;
630 for (auto it = m_ueDataVector.at(ueIndex).bearerDataList.begin();
631 it != m_ueDataVector.at(ueIndex).bearerDataList.end();
632 ++it)
633 {
634 uint32_t dlRx = it->dlSink->GetTotalRx() - it->dlOldTotalRx;
635 uint32_t ulRx = it->ulSink->GetTotalRx() - it->ulOldTotalRx;
636 uint32_t expectedBytes =
638
640 expectedBytes,
641 "too few RX bytes in DL, ue=" << ueIndex << ", b=" << b);
643 expectedBytes,
644 "too few RX bytes in UL, ue=" << ueIndex << ", b=" << b);
645 ++b;
646 }
647}
648
649/**
650 * @ingroup lte-test
651 *
652 * @brief LTE X2 Handover Test Suite.
653 *
654 * In this test suite, we use NoOpHandoverAlgorithm, i.e. "handover algorithm which does nothing"
655 * is used and handover is triggered manually. The automatic handover algorithms (A2A4, A3Rsrp)
656 * are not tested.
657 *
658 * The tests are designed to check that eNB-buffered data received while a handover is in progress
659 * is not lost but successfully forwarded. But the test suite doesn't test for possible loss of
660 * RLC-buffered data because "lossless" handover is not implemented, and there are other application
661 * send patterns (outside of the range tested here) that may incur losses.
662 */
664{
665 public:
667};
668
670 : TestSuite("lte-x2-handover", Type::SYSTEM)
671{
672 // in the following:
673 // fwd means handover from enb 0 to enb 1
674 // bwd means handover from enb 1 to enb 0
675
676 HandoverEvent ue1fwd;
677 ue1fwd.startTime = MilliSeconds(100);
678 ue1fwd.ueDeviceIndex = 0;
679 ue1fwd.sourceEnbDeviceIndex = 0;
680 ue1fwd.targetEnbDeviceIndex = 1;
681
682 HandoverEvent ue1bwd;
683 ue1bwd.startTime = MilliSeconds(400);
684 ue1bwd.ueDeviceIndex = 0;
685 ue1bwd.sourceEnbDeviceIndex = 1;
686 ue1bwd.targetEnbDeviceIndex = 0;
687
688 HandoverEvent ue1fwdagain;
689 ue1fwdagain.startTime = MilliSeconds(700);
690 ue1fwdagain.ueDeviceIndex = 0;
691 ue1fwdagain.sourceEnbDeviceIndex = 0;
692 ue1fwdagain.targetEnbDeviceIndex = 1;
693
694 HandoverEvent ue2fwd;
695 ue2fwd.startTime = MilliSeconds(110);
696 ue2fwd.ueDeviceIndex = 1;
697 ue2fwd.sourceEnbDeviceIndex = 0;
698 ue2fwd.targetEnbDeviceIndex = 1;
699
700 HandoverEvent ue2bwd;
701 ue2bwd.startTime = MilliSeconds(350);
702 ue2bwd.ueDeviceIndex = 1;
703 ue2bwd.sourceEnbDeviceIndex = 1;
704 ue2bwd.targetEnbDeviceIndex = 0;
705
706 std::string handoverEventList0name("none");
707 std::list<HandoverEvent> handoverEventList0;
708
709 std::string handoverEventList1name("1 fwd");
710 const std::list<HandoverEvent> handoverEventList1{
711 ue1fwd,
712 };
713
714 std::string handoverEventList2name("1 fwd & bwd");
715 const std::list<HandoverEvent> handoverEventList2{
716 ue1fwd,
717 ue1bwd,
718 };
719
720 std::string handoverEventList3name("1 fwd & bwd & fwd");
721 const std::list<HandoverEvent> handoverEventList3{
722 ue1fwd,
723 ue1bwd,
724 ue1fwdagain,
725 };
726
727 std::string handoverEventList4name("1+2 fwd");
728 const std::list<HandoverEvent> handoverEventList4{
729 ue1fwd,
730 ue2fwd,
731 };
732
733 std::string handoverEventList5name("1+2 fwd & bwd");
734 const std::list<HandoverEvent> handoverEventList5{
735 ue1fwd,
736 ue1bwd,
737 ue2fwd,
738 ue2bwd,
739 };
740
741 // std::string handoverEventList6name("2 fwd");
742 // const std::list<HandoverEvent> handoverEventList6{
743 // ue2fwd,
744 // };
745
746 // std::string handoverEventList7name("2 fwd & bwd");
747 // const std::list<HandoverEvent> handoverEventList7{
748 // ue2fwd,
749 // ue2bwd,
750 // };
751
752 std::vector<std::string> schedulers{
753 "ns3::RrFfMacScheduler",
754 "ns3::PfFfMacScheduler",
755 };
756
757 for (auto schedIt = schedulers.begin(); schedIt != schedulers.end(); ++schedIt)
758 {
759 for (auto useIdealRrc : {true, false})
760 {
761 // nUes, nDBearers, helist, name, sched, admitHo, idealRrc
763 0,
764 handoverEventList0,
765 handoverEventList0name,
766 *schedIt,
767 true,
768 useIdealRrc),
771 0,
772 handoverEventList0,
773 handoverEventList0name,
774 *schedIt,
775 true,
776 useIdealRrc),
779 5,
780 handoverEventList0,
781 handoverEventList0name,
782 *schedIt,
783 true,
784 useIdealRrc),
787 5,
788 handoverEventList0,
789 handoverEventList0name,
790 *schedIt,
791 true,
792 useIdealRrc),
795 0,
796 handoverEventList1,
797 handoverEventList1name,
798 *schedIt,
799 true,
800 useIdealRrc),
803 1,
804 handoverEventList1,
805 handoverEventList1name,
806 *schedIt,
807 true,
808 useIdealRrc),
811 2,
812 handoverEventList1,
813 handoverEventList1name,
814 *schedIt,
815 true,
816 useIdealRrc),
819 0,
820 handoverEventList1,
821 handoverEventList1name,
822 *schedIt,
823 false,
824 useIdealRrc),
827 1,
828 handoverEventList1,
829 handoverEventList1name,
830 *schedIt,
831 false,
832 useIdealRrc),
835 2,
836 handoverEventList1,
837 handoverEventList1name,
838 *schedIt,
839 false,
840 useIdealRrc),
843 0,
844 handoverEventList1,
845 handoverEventList1name,
846 *schedIt,
847 true,
848 useIdealRrc),
851 1,
852 handoverEventList1,
853 handoverEventList1name,
854 *schedIt,
855 true,
856 useIdealRrc),
859 2,
860 handoverEventList1,
861 handoverEventList1name,
862 *schedIt,
863 true,
864 useIdealRrc),
867 0,
868 handoverEventList1,
869 handoverEventList1name,
870 *schedIt,
871 false,
872 useIdealRrc),
875 1,
876 handoverEventList1,
877 handoverEventList1name,
878 *schedIt,
879 false,
880 useIdealRrc),
883 2,
884 handoverEventList1,
885 handoverEventList1name,
886 *schedIt,
887 false,
888 useIdealRrc),
891 0,
892 handoverEventList2,
893 handoverEventList2name,
894 *schedIt,
895 true,
896 useIdealRrc),
899 1,
900 handoverEventList2,
901 handoverEventList2name,
902 *schedIt,
903 true,
904 useIdealRrc),
907 2,
908 handoverEventList2,
909 handoverEventList2name,
910 *schedIt,
911 true,
912 useIdealRrc),
915 0,
916 handoverEventList3,
917 handoverEventList3name,
918 *schedIt,
919 true,
920 useIdealRrc),
923 1,
924 handoverEventList3,
925 handoverEventList3name,
926 *schedIt,
927 true,
928 useIdealRrc),
931 2,
932 handoverEventList3,
933 handoverEventList3name,
934 *schedIt,
935 true,
936 useIdealRrc),
939 0,
940 handoverEventList3,
941 handoverEventList3name,
942 *schedIt,
943 true,
944 useIdealRrc),
947 1,
948 handoverEventList3,
949 handoverEventList3name,
950 *schedIt,
951 true,
952 useIdealRrc),
955 2,
956 handoverEventList3,
957 handoverEventList3name,
958 *schedIt,
959 true,
960 useIdealRrc),
963 0,
964 handoverEventList4,
965 handoverEventList4name,
966 *schedIt,
967 true,
968 useIdealRrc),
971 1,
972 handoverEventList4,
973 handoverEventList4name,
974 *schedIt,
975 true,
976 useIdealRrc),
979 2,
980 handoverEventList4,
981 handoverEventList4name,
982 *schedIt,
983 true,
984 useIdealRrc),
987 0,
988 handoverEventList5,
989 handoverEventList5name,
990 *schedIt,
991 true,
992 useIdealRrc),
995 1,
996 handoverEventList5,
997 handoverEventList5name,
998 *schedIt,
999 true,
1000 useIdealRrc),
1003 2,
1004 handoverEventList5,
1005 handoverEventList5name,
1006 *schedIt,
1007 true,
1008 useIdealRrc),
1011 0,
1012 handoverEventList3,
1013 handoverEventList3name,
1014 *schedIt,
1015 true,
1016 useIdealRrc),
1019 1,
1020 handoverEventList3,
1021 handoverEventList3name,
1022 *schedIt,
1023 true,
1024 useIdealRrc),
1027 2,
1028 handoverEventList3,
1029 handoverEventList3name,
1030 *schedIt,
1031 true,
1032 useIdealRrc),
1035 0,
1036 handoverEventList4,
1037 handoverEventList4name,
1038 *schedIt,
1039 true,
1040 useIdealRrc),
1043 1,
1044 handoverEventList4,
1045 handoverEventList4name,
1046 *schedIt,
1047 true,
1048 useIdealRrc),
1051 2,
1052 handoverEventList4,
1053 handoverEventList4name,
1054 *schedIt,
1055 true,
1056 useIdealRrc),
1059 0,
1060 handoverEventList5,
1061 handoverEventList5name,
1062 *schedIt,
1063 true,
1064 useIdealRrc),
1067 1,
1068 handoverEventList5,
1069 handoverEventList5name,
1070 *schedIt,
1071 true,
1072 useIdealRrc),
1075 2,
1076 handoverEventList5,
1077 handoverEventList5name,
1078 *schedIt,
1079 true,
1080 useIdealRrc),
1082 }
1083 }
1084}
1085
1086/**
1087 * @ingroup lte-test
1088 * Static variable for test initialization
1089 */
uint32_t q
uint32_t u
static std::string BuildNameString(uint32_t nUes, uint32_t nDedicatedBearers, std::string handoverEventListName, std::string schedulerType, bool admitHo, bool useIdealRrc)
Build name string.
void DoRun() override
Implementation to actually run this TestCase.
Ptr< PointToPointEpcHelper > m_epcHelper
EPC helper.
uint32_t m_nUes
number of UEs in the test
std::string m_handoverEventListName
handover event list name
std::string m_schedulerType
scheduler type
const uint32_t m_udpClientPktSize
UDP client packet size.
bool m_useIdealRrc
whether to use the ideal RRC
const Time m_statsDuration
stats duration
std::vector< UeData > m_ueDataVector
UE data vector.
void CheckConnected(Ptr< NetDevice > ueDevice, Ptr< NetDevice > enbDevice)
Check connected function.
LteX2HandoverTestCase(uint32_t nUes, uint32_t nDedicatedBearers, std::list< HandoverEvent > handoverEventList, std::string handoverEventListName, std::string schedulerType, bool admitHo, bool useIdealRrc)
void TeleportUeNearTargetEnb(Ptr< Node > ueNode, Ptr< Node > enbNode)
Teleport UE near the target eNB of the handover.
bool m_admitHo
whether to admit the handover request
bool m_epc
whether to use EPC
void SaveStatsAfterHandover(uint32_t ueIndex)
Save stats after handover function.
const Time m_maxHoDuration
maximum HO duration
std::list< HandoverEvent > m_handoverEventList
handover event list
void CheckStatsAWhileAfterHandover(uint32_t ueIndex)
Check stats a while after handover function.
uint32_t m_nDedicatedBearers
number of UEs in the test
const Time m_udpClientInterval
UDP client interval.
void TeleportUeToMiddle(Ptr< Node > ueNode)
Teleport UE between both eNBs of the test.
Ptr< LteHelper > m_lteHelper
LTE helper.
LTE X2 Handover Test Suite.
holds a vector of ns3::Application pointers.
Ptr< Application > Get(uint32_t i) const
Get the Ptr<Application> stored in this container at a given index.
ApplicationContainer Install(NodeContainer c)
Install an application on each node of the input container configured with all the attributes set wit...
AttributeValue implementation for Boolean.
Definition boolean.h:26
Class for representing data rates.
Definition data-rate.h:78
AttributeValue implementation for DataRate.
Definition data-rate.h:252
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
This class contains the specification of EPS Bearers.
Definition eps-bearer.h:80
Qci
QoS Class Indicator.
Definition eps-bearer.h:95
@ NGBR_VIDEO_TCP_DEFAULT
Non-GBR TCP-based Video (Buffered Streaming, e.g., www, e-mail...).
Definition eps-bearer.h:115
an Inet address class
aggregate IP/TCP/UDP functionality to existing Nodes.
A helper class to make life easier while doing simple IPv4 address assignment in scripts.
void SetBase(Ipv4Address network, Ipv4Mask mask, Ipv4Address base="0.0.0.1")
Set the base network number, network mask and base address.
Ipv4InterfaceContainer Assign(const NetDeviceContainer &c)
Assign IP addresses to the net devices specified in the container based on the current network prefix...
Ipv4 addresses are stored in host order in this class.
static Ipv4Address GetAny()
Access to the IPv4 forwarding table, interfaces, and configuration.
Definition ipv4.h:69
holds a vector of std::pair of Ptr<Ipv4> and interface index.
Ipv4Address GetAddress(uint32_t i, uint32_t j=0) const
a class to represent an Ipv4 address mask
Helper class that adds ns3::Ipv4StaticRouting objects.
Ptr< Ipv4StaticRouting > GetStaticRouting(Ptr< Ipv4 > ipv4) const
Try and find the static routing protocol as either the main routing protocol or in the list of routin...
store information on active data radio bearer instance
The eNodeB device implementation.
The LteUeNetDevice class implements the UE net device.
Helper class used to assign positions and mobility models to nodes.
Keep track of the current position and velocity of an object.
holds a vector of ns3::NetDevice pointers
uint32_t GetN() const
Get the number of Ptr<NetDevice> stored in this container.
Iterator Begin() const
Get an iterator which refers to the first NetDevice in the container.
Iterator End() const
Get an iterator which indicates past-the-last NetDevice in the container.
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
keep track of a set of node pointers.
uint32_t GetN() const
Get the number of Ptr<Node> stored in this container.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
std::size_t GetN() const
Get the number of Objects.
Iterator End() const
Get an iterator to the past-the-end Object.
Iterator Begin() const
Get an iterator to the first Object.
A helper to make it easier to instantiate an ns3::PacketSinkApplication on a set of nodes.
Receive and consume traffic generated to an IP address and port.
Definition packet-sink.h:61
Build a set of PointToPointNetDevice objects.
void SetDeviceAttribute(std::string name, const AttributeValue &value)
Set an attribute value to be propagated to each NetDevice created by the helper.
void SetChannelAttribute(std::string name, const AttributeValue &value)
Set an attribute value to be propagated to each Channel created by the helper.
NetDeviceContainer Install(NodeContainer c)
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:70
static void SetRun(uint64_t run)
Set the run number of simulation.
static void SetSeed(uint32_t seed)
Set the seed.
static uint64_t GetRun()
Get the current run number.
static uint32_t GetSeed()
Get the current seed value which will be used by all subsequently instantiated RandomVariableStream o...
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:580
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:125
static void Run()
Run the simulation.
Definition simulator.cc:161
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition simulator.cc:169
Hold variables of type string.
Definition string.h:45
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:296
@ EXTENSIVE
Medium length test.
Definition test.h:1058
@ QUICK
Fast test.
Definition test.h:1057
TestCase(const TestCase &)=delete
Caller graph was not generated because of its size.
Type
Type of test.
Definition test.h:1271
TestSuite(std::string name, Type type=Type::UNIT)
Construct a new test suite.
Definition test.cc:494
Simulation virtual time values and global simulation resolution.
Definition nstime.h:95
AttributeValue implementation for Time.
Definition nstime.h:1375
Create a client application which sends UDP packets carrying a 32bit sequence number and a 64 bit tim...
State
The state of the UeManager at the eNB RRC.
Definition lte-enb-rrc.h:67
Hold an unsigned integer type.
Definition uinteger.h:34
Time stopTime
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
ObjectPtrContainerValue ObjectMapValue
ObjectMapValue is an alias for ObjectPtrContainerValue.
Definition object-map.h:29
void Reset()
Reset the initial value of every attribute as well as the value of every global to what they were bef...
Definition config.cc:851
void SetDefault(std::string name, const AttributeValue &value)
Definition config.cc:886
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:194
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
static LteX2HandoverTestSuite g_lteX2HandoverTestSuiteInstance
Static variable for test initialization.
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:627
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:454
#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:133
#define NS_TEST_ASSERT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report and abort if not.
Definition test.h:553
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1273
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1290
Every class exported by the ns3 library is enclosed in the ns3 namespace.
HandoverEvent structure.
uint32_t ueDeviceIndex
UE device index.
Time startTime
start time
uint32_t targetEnbDeviceIndex
target ENB device index
uint32_t sourceEnbDeviceIndex
source ENB device index
uint32_t dlOldTotalRx
DL old total receive.
uint32_t ulOldTotalRx
UL old total receive.
std::list< BearerData > bearerDataList
bearer ID list
Implement the data structure representing a TrafficFlowTemplate Packet Filter.
Definition epc-tft.h:60
uint16_t localPortEnd
end of the port number range of the UE
Definition epc-tft.h:121
uint16_t remotePortEnd
end of the port number range of the remote host
Definition epc-tft.h:119
uint16_t remotePortStart
start of the port number range of the remote host
Definition epc-tft.h:118
uint16_t localPortStart
start of the port number range of the UE
Definition epc-tft.h:120