A Discrete-Event Network Simulator
API
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 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Nicola Baldo <nbaldo@cttc.es>
18 */
19
20#include <ns3/applications-module.h>
21#include <ns3/core-module.h>
22#include <ns3/internet-module.h>
23#include <ns3/lte-module.h>
24#include <ns3/mobility-module.h>
25#include <ns3/network-module.h>
26#include <ns3/point-to-point-module.h>
27
28using namespace ns3;
29
30NS_LOG_COMPONENT_DEFINE("LteX2HandoverTest");
31
38{
43};
44
52{
53 public:
66 uint32_t nDedicatedBearers,
67 std::list<HandoverEvent> handoverEventList,
68 std::string handoverEventListName,
69 std::string schedulerType,
70 bool admitHo,
71 bool useIdealRrc);
72
73 private:
84 static std::string BuildNameString(uint32_t nUes,
85 uint32_t nDedicatedBearers,
86 std::string handoverEventListName,
87 std::string schedulerType,
88 bool admitHo,
89 bool useIdealRrc);
90 void DoRun() override;
96 void CheckConnected(Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice);
97
102 void TeleportUeToMiddle(Ptr<Node> ueNode);
103
109 void TeleportUeNearTargetEnb(Ptr<Node> ueNode, Ptr<Node> enbNode);
110
113 std::list<HandoverEvent> m_handoverEventList;
115 bool m_epc;
116 std::string m_schedulerType;
121
128 {
134 };
135
141 struct UeData
142 {
144 std::list<BearerData> bearerDataList;
145 };
146
151 void SaveStatsAfterHandover(uint32_t ueIndex);
157
158 std::vector<UeData> m_ueDataVector;
159
164};
165
166std::string
168 uint32_t nDedicatedBearers,
169 std::string handoverEventListName,
170 std::string schedulerType,
171 bool admitHo,
172 bool useIdealRrc)
173{
174 std::ostringstream oss;
175 oss << " nUes=" << nUes << " nDedicatedBearers=" << nDedicatedBearers << " " << schedulerType
176 << " admitHo=" << admitHo << " hoList: " << handoverEventListName;
177 if (useIdealRrc)
178 {
179 oss << ", ideal RRC";
180 }
181 else
182 {
183 oss << ", real RRC";
184 }
185 return oss.str();
186}
187
189 uint32_t nDedicatedBearers,
190 std::list<HandoverEvent> handoverEventList,
191 std::string handoverEventListName,
192 std::string schedulerType,
193 bool admitHo,
194 bool useIdealRrc)
195 : TestCase(BuildNameString(nUes,
196 nDedicatedBearers,
197 handoverEventListName,
198 schedulerType,
199 admitHo,
200 useIdealRrc)),
201 m_nUes(nUes),
202 m_nDedicatedBearers(nDedicatedBearers),
203 m_handoverEventList(handoverEventList),
204 m_handoverEventListName(handoverEventListName),
205 m_epc(true),
206 m_schedulerType(schedulerType),
207 m_admitHo(admitHo),
208 m_useIdealRrc(useIdealRrc),
209 m_maxHoDuration(Seconds(0.1)),
210 m_statsDuration(Seconds(0.1)),
211 m_udpClientInterval(Seconds(0.01)),
212 m_udpClientPktSize(100)
213
214{
215}
216
217void
219{
224 m_admitHo,
226
227 uint32_t previousSeed = RngSeedManager::GetSeed();
228 uint64_t previousRun = RngSeedManager::GetRun();
230 // This test is sensitive to random variable stream assigments
231 RngSeedManager::SetSeed(1);
232 RngSeedManager::SetRun(3);
233 Config::SetDefault("ns3::UdpClient::Interval", TimeValue(m_udpClientInterval));
234 Config::SetDefault("ns3::UdpClient::MaxPackets", UintegerValue(1000000));
235 Config::SetDefault("ns3::UdpClient::PacketSize", UintegerValue(m_udpClientPktSize));
236
237 // Disable Uplink Power Control
238 Config::SetDefault("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue(false));
239
240 int64_t stream = 1;
241
242 m_lteHelper = CreateObject<LteHelper>();
243 m_lteHelper->SetAttribute("PathlossModel",
244 StringValue("ns3::FriisSpectrumPropagationLossModel"));
247 "ns3::NoOpHandoverAlgorithm"); // disable automatic handover
249
250 NodeContainer enbNodes;
251 enbNodes.Create(2);
252 NodeContainer ueNodes;
253 ueNodes.Create(m_nUes);
254
255 if (m_epc)
256 {
257 m_epcHelper = CreateObject<PointToPointEpcHelper>();
259 }
260
261 Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
262 positionAlloc->Add(Vector(-3000, 0, 0)); // enb0
263 positionAlloc->Add(Vector(3000, 0, 0)); // enb1
264 for (uint32_t i = 0; i < m_nUes; i++)
265 {
266 positionAlloc->Add(Vector(-3000, 100, 0));
267 }
269 mobility.SetPositionAllocator(positionAlloc);
270 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
271 mobility.Install(enbNodes);
272 mobility.Install(ueNodes);
273
274 NetDeviceContainer enbDevices;
275 enbDevices = m_lteHelper->InstallEnbDevice(enbNodes);
276 stream += m_lteHelper->AssignStreams(enbDevices, stream);
277 for (NetDeviceContainer::Iterator it = enbDevices.Begin(); it != enbDevices.End(); ++it)
278 {
279 Ptr<LteEnbRrc> enbRrc = (*it)->GetObject<LteEnbNetDevice>()->GetRrc();
280 enbRrc->SetAttribute("AdmitHandoverRequest", BooleanValue(m_admitHo));
281 }
282
283 NetDeviceContainer ueDevices;
284 ueDevices = m_lteHelper->InstallUeDevice(ueNodes);
285 stream += m_lteHelper->AssignStreams(ueDevices, stream);
286
287 Ipv4Address remoteHostAddr;
288 Ipv4StaticRoutingHelper ipv4RoutingHelper;
289 Ipv4InterfaceContainer ueIpIfaces;
290 Ptr<Node> remoteHost;
291 if (m_epc)
292 {
293 // Create a single RemoteHost
294 NodeContainer remoteHostContainer;
295 remoteHostContainer.Create(1);
296 remoteHost = remoteHostContainer.Get(0);
297 InternetStackHelper internet;
298 internet.Install(remoteHostContainer);
299
300 // Create the Internet
302 p2ph.SetDeviceAttribute("DataRate", DataRateValue(DataRate("100Gb/s")));
303 p2ph.SetDeviceAttribute("Mtu", UintegerValue(1500));
304 p2ph.SetChannelAttribute("Delay", TimeValue(Seconds(0.010)));
306 NetDeviceContainer internetDevices = p2ph.Install(pgw, remoteHost);
307 Ipv4AddressHelper ipv4h;
308 ipv4h.SetBase("1.0.0.0", "255.0.0.0");
309 Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign(internetDevices);
310 // in this container, interface 0 is the pgw, 1 is the remoteHost
311 remoteHostAddr = internetIpIfaces.GetAddress(1);
312
313 Ipv4StaticRoutingHelper ipv4RoutingHelper;
314 Ptr<Ipv4StaticRouting> remoteHostStaticRouting =
315 ipv4RoutingHelper.GetStaticRouting(remoteHost->GetObject<Ipv4>());
316 remoteHostStaticRouting->AddNetworkRouteTo(Ipv4Address("7.0.0.0"),
317 Ipv4Mask("255.0.0.0"),
318 1);
319
320 // Install the IP stack on the UEs
321 internet.Install(ueNodes);
322 ueIpIfaces = m_epcHelper->AssignUeIpv4Address(NetDeviceContainer(ueDevices));
323 }
324
325 // attachment (needs to be done after IP stack configuration)
326 // all UEs attached to eNB 0 at the beginning
327 m_lteHelper->Attach(ueDevices, enbDevices.Get(0));
328
329 if (m_epc)
330 {
331 // always true: bool epcDl = true;
332 // always true: bool epcUl = true;
333 // the rest of this block is copied from lena-dual-stripe
334
335 // Install and start applications on UEs and remote host
336 uint16_t dlPort = 10000;
337 uint16_t ulPort = 20000;
338
339 // randomize a bit start times to avoid simulation artifacts
340 // (e.g., buffer overflows due to packet transmissions happening
341 // exactly at the same time)
342 Ptr<UniformRandomVariable> startTimeSeconds = CreateObject<UniformRandomVariable>();
343 startTimeSeconds->SetAttribute("Min", DoubleValue(0));
344 startTimeSeconds->SetAttribute("Max", DoubleValue(0.010));
345 startTimeSeconds->SetStream(stream++);
346
347 for (uint32_t u = 0; u < ueNodes.GetN(); ++u)
348 {
349 Ptr<Node> ue = ueNodes.Get(u);
350 // Set the default gateway for the UE
351 Ptr<Ipv4StaticRouting> ueStaticRouting =
352 ipv4RoutingHelper.GetStaticRouting(ue->GetObject<Ipv4>());
353 ueStaticRouting->SetDefaultRoute(m_epcHelper->GetUeDefaultGatewayAddress(), 1);
354
355 UeData ueData;
356
357 for (uint32_t b = 0; b < m_nDedicatedBearers; ++b)
358 {
359 ++dlPort;
360 ++ulPort;
361
364 BearerData bearerData = BearerData();
365
366 // always true: if (epcDl)
367 {
368 UdpClientHelper dlClientHelper(ueIpIfaces.GetAddress(u), dlPort);
369 clientApps.Add(dlClientHelper.Install(remoteHost));
370 PacketSinkHelper dlPacketSinkHelper(
371 "ns3::UdpSocketFactory",
372 InetSocketAddress(Ipv4Address::GetAny(), dlPort));
373 ApplicationContainer sinkContainer = dlPacketSinkHelper.Install(ue);
374 bearerData.dlSink = sinkContainer.Get(0)->GetObject<PacketSink>();
375 serverApps.Add(sinkContainer);
376 }
377 // always true: if (epcUl)
378 {
379 UdpClientHelper ulClientHelper(remoteHostAddr, ulPort);
380 clientApps.Add(ulClientHelper.Install(ue));
381 PacketSinkHelper ulPacketSinkHelper(
382 "ns3::UdpSocketFactory",
383 InetSocketAddress(Ipv4Address::GetAny(), ulPort));
384 ApplicationContainer sinkContainer = ulPacketSinkHelper.Install(remoteHost);
385 bearerData.ulSink = sinkContainer.Get(0)->GetObject<PacketSink>();
386 serverApps.Add(sinkContainer);
387 }
388
389 Ptr<EpcTft> tft = Create<EpcTft>();
390 // always true: if (epcDl)
391 {
393 dlpf.localPortStart = dlPort;
394 dlpf.localPortEnd = dlPort;
395 tft->Add(dlpf);
396 }
397 // always true: if (epcUl)
398 {
400 ulpf.remotePortStart = ulPort;
401 ulpf.remotePortEnd = ulPort;
402 tft->Add(ulpf);
403 }
404
405 // always true: if (epcDl || epcUl)
406 {
407 EpsBearer bearer(EpsBearer::NGBR_VIDEO_TCP_DEFAULT);
408 m_lteHelper->ActivateDedicatedEpsBearer(ueDevices.Get(u), bearer, tft);
409 }
410 double d = startTimeSeconds->GetValue();
411 Time startTime = Seconds(d);
412 serverApps.Start(startTime);
413 clientApps.Start(startTime);
414
415 ueData.bearerDataList.push_back(bearerData);
416
417 } // end for b
418
419 m_ueDataVector.push_back(ueData);
420 }
421 }
422 else // (epc == false)
423 {
424 // for radio bearer activation purposes, consider together home UEs and macro UEs
425 for (uint32_t u = 0; u < ueDevices.GetN(); ++u)
426 {
427 Ptr<NetDevice> ueDev = ueDevices.Get(u);
428 for (uint32_t b = 0; b < m_nDedicatedBearers; ++b)
429 {
430 enum EpsBearer::Qci q = EpsBearer::NGBR_VIDEO_TCP_DEFAULT;
431 EpsBearer bearer(q);
432 m_lteHelper->ActivateDataRadioBearer(ueDev, bearer);
433 }
434 }
435 }
436
437 m_lteHelper->AddX2Interface(enbNodes);
438
439 // check initial RRC connection
440 const Time maxRrcConnectionEstablishmentDuration = Seconds(0.080);
441 for (NetDeviceContainer::Iterator it = ueDevices.Begin(); it != ueDevices.End(); ++it)
442 {
443 Simulator::Schedule(maxRrcConnectionEstablishmentDuration,
445 this,
446 *it,
447 enbDevices.Get(0));
448 }
449
450 // schedule handover events and corresponding checks
451
452 Time stopTime = Seconds(0);
453 for (std::list<HandoverEvent>::iterator hoEventIt = m_handoverEventList.begin();
454 hoEventIt != m_handoverEventList.end();
455 ++hoEventIt)
456 {
457 // Teleport the UE between both eNBs just before the handover starts
458 Simulator::Schedule(hoEventIt->startTime - MilliSeconds(10),
460 this,
461 ueNodes.Get(hoEventIt->ueDeviceIndex));
462
463 Simulator::Schedule(hoEventIt->startTime,
465 this,
466 ueDevices.Get(hoEventIt->ueDeviceIndex),
467 enbDevices.Get(hoEventIt->sourceEnbDeviceIndex));
468
469 m_lteHelper->HandoverRequest(hoEventIt->startTime,
470 ueDevices.Get(hoEventIt->ueDeviceIndex),
471 enbDevices.Get(hoEventIt->sourceEnbDeviceIndex),
472 enbDevices.Get(hoEventIt->targetEnbDeviceIndex));
473
474 // Once the handover is finished, teleport the UE near the target eNB
475 Simulator::Schedule(hoEventIt->startTime + MilliSeconds(40),
477 this,
478 ueNodes.Get(hoEventIt->ueDeviceIndex),
479 enbNodes.Get(m_admitHo ? hoEventIt->targetEnbDeviceIndex
480 : hoEventIt->sourceEnbDeviceIndex));
481
482 Time hoEndTime = hoEventIt->startTime + m_maxHoDuration;
483 Simulator::Schedule(hoEndTime,
485 this,
486 ueDevices.Get(hoEventIt->ueDeviceIndex),
487 enbDevices.Get(m_admitHo ? hoEventIt->targetEnbDeviceIndex
488 : hoEventIt->sourceEnbDeviceIndex));
489 Simulator::Schedule(hoEndTime,
491 this,
492 hoEventIt->ueDeviceIndex);
493
494 Time checkStatsAfterHoTime = hoEndTime + m_statsDuration;
495 Simulator::Schedule(checkStatsAfterHoTime,
497 this,
498 hoEventIt->ueDeviceIndex);
499 if (stopTime <= checkStatsAfterHoTime)
500 {
501 stopTime = checkStatsAfterHoTime + MilliSeconds(1);
502 }
503 }
504
505 // m_lteHelper->EnableRlcTraces ();
506 // m_lteHelper->EnablePdcpTraces();
507
508 Simulator::Stop(stopTime);
509
510 Simulator::Run();
511
512 Simulator::Destroy();
513
514 // Undo changes to default settings
516 // Restore the previous settings of RngSeed and RngRun
517 RngSeedManager::SetSeed(previousSeed);
518 RngSeedManager::SetRun(previousRun);
519}
520
521void
523{
524 Ptr<LteUeNetDevice> ueLteDevice = ueDevice->GetObject<LteUeNetDevice>();
525 Ptr<LteUeRrc> ueRrc = ueLteDevice->GetRrc();
526 NS_TEST_ASSERT_MSG_EQ(ueRrc->GetState(), LteUeRrc::CONNECTED_NORMALLY, "Wrong LteUeRrc state!");
527
528 Ptr<LteEnbNetDevice> enbLteDevice = enbDevice->GetObject<LteEnbNetDevice>();
529 Ptr<LteEnbRrc> enbRrc = enbLteDevice->GetRrc();
530 uint16_t rnti = ueRrc->GetRnti();
531 Ptr<UeManager> ueManager = enbRrc->GetUeManager(rnti);
532 NS_TEST_ASSERT_MSG_NE(ueManager, nullptr, "RNTI " << rnti << " not found in eNB");
533
534 UeManager::State ueManagerState = ueManager->GetState();
535 NS_TEST_ASSERT_MSG_EQ(ueManagerState, UeManager::CONNECTED_NORMALLY, "Wrong UeManager state!");
536 NS_ASSERT_MSG(ueManagerState == UeManager::CONNECTED_NORMALLY, "Wrong UeManager state!");
537
538 uint16_t ueCellId = ueRrc->GetCellId();
539 uint16_t enbCellId = enbLteDevice->GetCellId();
540 uint8_t ueDlBandwidth = ueRrc->GetDlBandwidth();
541 uint8_t enbDlBandwidth = enbLteDevice->GetDlBandwidth();
542 uint8_t ueUlBandwidth = ueRrc->GetUlBandwidth();
543 uint8_t enbUlBandwidth = enbLteDevice->GetUlBandwidth();
544 uint8_t ueDlEarfcn = ueRrc->GetDlEarfcn();
545 uint8_t enbDlEarfcn = enbLteDevice->GetDlEarfcn();
546 uint8_t ueUlEarfcn = ueRrc->GetUlEarfcn();
547 uint8_t enbUlEarfcn = enbLteDevice->GetUlEarfcn();
548 uint64_t ueImsi = ueLteDevice->GetImsi();
549 uint64_t enbImsi = ueManager->GetImsi();
550
551 NS_TEST_ASSERT_MSG_EQ(ueImsi, enbImsi, "inconsistent IMSI");
552 NS_TEST_ASSERT_MSG_EQ(ueCellId, enbCellId, "inconsistent CellId");
553 NS_TEST_ASSERT_MSG_EQ(ueDlBandwidth, enbDlBandwidth, "inconsistent DlBandwidth");
554 NS_TEST_ASSERT_MSG_EQ(ueUlBandwidth, enbUlBandwidth, "inconsistent UlBandwidth");
555 NS_TEST_ASSERT_MSG_EQ(ueDlEarfcn, enbDlEarfcn, "inconsistent DlEarfcn");
556 NS_TEST_ASSERT_MSG_EQ(ueUlEarfcn, enbUlEarfcn, "inconsistent UlEarfcn");
557
558 ObjectMapValue enbDataRadioBearerMapValue;
559 ueManager->GetAttribute("DataRadioBearerMap", enbDataRadioBearerMapValue);
560 NS_TEST_ASSERT_MSG_EQ(enbDataRadioBearerMapValue.GetN(),
562 "wrong num bearers at eNB");
563
564 ObjectMapValue ueDataRadioBearerMapValue;
565 ueRrc->GetAttribute("DataRadioBearerMap", ueDataRadioBearerMapValue);
566 NS_TEST_ASSERT_MSG_EQ(ueDataRadioBearerMapValue.GetN(),
568 "wrong num bearers at UE");
569
570 ObjectMapValue::Iterator enbBearerIt = enbDataRadioBearerMapValue.Begin();
571 ObjectMapValue::Iterator ueBearerIt = ueDataRadioBearerMapValue.Begin();
572 while (enbBearerIt != enbDataRadioBearerMapValue.End() &&
573 ueBearerIt != ueDataRadioBearerMapValue.End())
574 {
575 Ptr<LteDataRadioBearerInfo> enbDrbInfo =
576 enbBearerIt->second->GetObject<LteDataRadioBearerInfo>();
578 ueBearerIt->second->GetObject<LteDataRadioBearerInfo>();
579 // NS_TEST_ASSERT_MSG_EQ (enbDrbInfo->m_epsBearer, ueDrbInfo->m_epsBearer, "epsBearer
580 // differs");
581 NS_TEST_ASSERT_MSG_EQ((uint32_t)enbDrbInfo->m_epsBearerIdentity,
582 (uint32_t)ueDrbInfo->m_epsBearerIdentity,
583 "epsBearerIdentity differs");
584 NS_TEST_ASSERT_MSG_EQ((uint32_t)enbDrbInfo->m_drbIdentity,
585 (uint32_t)ueDrbInfo->m_drbIdentity,
586 "drbIdentity differs");
587 // NS_TEST_ASSERT_MSG_EQ (enbDrbInfo->m_rlcConfig, ueDrbInfo->m_rlcConfig, "rlcConfig
588 // differs");
589 NS_TEST_ASSERT_MSG_EQ((uint32_t)enbDrbInfo->m_logicalChannelIdentity,
590 (uint32_t)ueDrbInfo->m_logicalChannelIdentity,
591 "logicalChannelIdentity differs");
592 // NS_TEST_ASSERT_MSG_EQ (enbDrbInfo->m_logicalChannelConfig,
593 // ueDrbInfo->m_logicalChannelConfig, "logicalChannelConfig differs");
594
595 ++enbBearerIt;
596 ++ueBearerIt;
597 }
598 NS_ASSERT_MSG(enbBearerIt == enbDataRadioBearerMapValue.End(), "too many bearers at eNB");
599 NS_ASSERT_MSG(ueBearerIt == ueDataRadioBearerMapValue.End(), "too many bearers at UE");
600}
601
602void
604{
605 Ptr<MobilityModel> ueMobility = ueNode->GetObject<MobilityModel>();
606 ueMobility->SetPosition(Vector(0.0, 0.0, 0.0));
607}
608
609void
611{
612 Ptr<MobilityModel> enbMobility = enbNode->GetObject<MobilityModel>();
613 Vector pos = enbMobility->GetPosition();
614
615 Ptr<MobilityModel> ueMobility = ueNode->GetObject<MobilityModel>();
616 ueMobility->SetPosition(pos + Vector(0.0, 100.0, 0.0));
617}
618
619void
621{
622 for (std::list<BearerData>::iterator it = m_ueDataVector.at(ueIndex).bearerDataList.begin();
623 it != m_ueDataVector.at(ueIndex).bearerDataList.end();
624 ++it)
625 {
626 it->dlOldTotalRx = it->dlSink->GetTotalRx();
627 it->ulOldTotalRx = it->ulSink->GetTotalRx();
628 }
629}
630
631void
633{
634 uint32_t b = 1;
635 for (std::list<BearerData>::iterator it = m_ueDataVector.at(ueIndex).bearerDataList.begin();
636 it != m_ueDataVector.at(ueIndex).bearerDataList.end();
637 ++it)
638 {
639 uint32_t dlRx = it->dlSink->GetTotalRx() - it->dlOldTotalRx;
640 uint32_t ulRx = it->ulSink->GetTotalRx() - it->ulOldTotalRx;
641 uint32_t expectedBytes =
643
645 expectedBytes,
646 "too few RX bytes in DL, ue=" << ueIndex << ", b=" << b);
648 expectedBytes,
649 "too few RX bytes in UL, ue=" << ueIndex << ", b=" << b);
650 ++b;
651 }
652}
653
669{
670 public:
672};
673
675 : TestSuite("lte-x2-handover", SYSTEM)
676{
677 // in the following:
678 // fwd means handover from enb 0 to enb 1
679 // bwd means handover from enb 1 to enb 0
680
681 HandoverEvent ue1fwd;
682 ue1fwd.startTime = MilliSeconds(100);
683 ue1fwd.ueDeviceIndex = 0;
684 ue1fwd.sourceEnbDeviceIndex = 0;
685 ue1fwd.targetEnbDeviceIndex = 1;
686
687 HandoverEvent ue1bwd;
688 ue1bwd.startTime = MilliSeconds(400);
689 ue1bwd.ueDeviceIndex = 0;
690 ue1bwd.sourceEnbDeviceIndex = 1;
691 ue1bwd.targetEnbDeviceIndex = 0;
692
693 HandoverEvent ue1fwdagain;
694 ue1fwdagain.startTime = MilliSeconds(700);
695 ue1fwdagain.ueDeviceIndex = 0;
696 ue1fwdagain.sourceEnbDeviceIndex = 0;
697 ue1fwdagain.targetEnbDeviceIndex = 1;
698
699 HandoverEvent ue2fwd;
700 ue2fwd.startTime = MilliSeconds(110);
701 ue2fwd.ueDeviceIndex = 1;
702 ue2fwd.sourceEnbDeviceIndex = 0;
703 ue2fwd.targetEnbDeviceIndex = 1;
704
705 HandoverEvent ue2bwd;
706 ue2bwd.startTime = MilliSeconds(350);
707 ue2bwd.ueDeviceIndex = 1;
708 ue2bwd.sourceEnbDeviceIndex = 1;
709 ue2bwd.targetEnbDeviceIndex = 0;
710
711 std::string hel0name("none");
712 std::list<HandoverEvent> hel0;
713
714 std::string hel1name("1 fwd");
715 const std::list<HandoverEvent> hel1{
716 ue1fwd,
717 };
718
719 std::string hel2name("1 fwd & bwd");
720 const std::list<HandoverEvent> hel2{
721 ue1fwd,
722 ue1bwd,
723 };
724
725 std::string hel3name("1 fwd & bwd & fwd");
726 const std::list<HandoverEvent> hel3{
727 ue1fwd,
728 ue1bwd,
729 ue1fwdagain,
730 };
731
732 std::string hel4name("1+2 fwd");
733 const std::list<HandoverEvent> hel4{
734 ue1fwd,
735 ue2fwd,
736 };
737
738 std::string hel5name("1+2 fwd & bwd");
739 const std::list<HandoverEvent> hel5{
740 ue1fwd,
741 ue1bwd,
742 ue2fwd,
743 ue2bwd,
744 };
745
746 // std::string hel6name("2 fwd");
747 // const std::list<HandoverEvent> hel6{
748 // ue2fwd,
749 // };
750
751 // std::string hel7name("2 fwd & bwd");
752 // const std::list<HandoverEvent> hel7{
753 // ue2fwd,
754 // ue2bwd,
755 // };
756
757 std::vector<std::string> schedulers{
758 "ns3::RrFfMacScheduler",
759 "ns3::PfFfMacScheduler",
760 };
761
762 for (std::vector<std::string>::iterator schedIt = schedulers.begin();
763 schedIt != schedulers.end();
764 ++schedIt)
765 {
766 for (int32_t useIdealRrc = 1; useIdealRrc >= 0; --useIdealRrc)
767 {
768 // nUes, nDBearers, helist, name, sched, admitHo,
769 // idealRrc
771 new LteX2HandoverTestCase(1, 0, hel0, hel0name, *schedIt, true, useIdealRrc),
772 TestCase::EXTENSIVE);
774 new LteX2HandoverTestCase(2, 0, hel0, hel0name, *schedIt, true, useIdealRrc),
775 TestCase::EXTENSIVE);
777 new LteX2HandoverTestCase(1, 5, hel0, hel0name, *schedIt, true, useIdealRrc),
778 TestCase::EXTENSIVE);
780 new LteX2HandoverTestCase(2, 5, hel0, hel0name, *schedIt, true, useIdealRrc),
781 TestCase::EXTENSIVE);
783 new LteX2HandoverTestCase(1, 0, hel1, hel1name, *schedIt, true, useIdealRrc),
784 TestCase::EXTENSIVE);
786 new LteX2HandoverTestCase(1, 1, hel1, hel1name, *schedIt, true, useIdealRrc),
787 TestCase::EXTENSIVE);
789 new LteX2HandoverTestCase(1, 2, hel1, hel1name, *schedIt, true, useIdealRrc),
790 TestCase::EXTENSIVE);
792 new LteX2HandoverTestCase(1, 0, hel1, hel1name, *schedIt, false, useIdealRrc),
793 TestCase::EXTENSIVE);
795 new LteX2HandoverTestCase(1, 1, hel1, hel1name, *schedIt, false, useIdealRrc),
796 TestCase::EXTENSIVE);
798 new LteX2HandoverTestCase(1, 2, hel1, hel1name, *schedIt, false, useIdealRrc),
799 TestCase::EXTENSIVE);
801 new LteX2HandoverTestCase(2, 0, hel1, hel1name, *schedIt, true, useIdealRrc),
802 TestCase::EXTENSIVE);
804 new LteX2HandoverTestCase(2, 1, hel1, hel1name, *schedIt, true, useIdealRrc),
805 TestCase::EXTENSIVE);
807 new LteX2HandoverTestCase(2, 2, hel1, hel1name, *schedIt, true, useIdealRrc),
808 TestCase::EXTENSIVE);
810 new LteX2HandoverTestCase(2, 0, hel1, hel1name, *schedIt, false, useIdealRrc),
811 TestCase::EXTENSIVE);
813 new LteX2HandoverTestCase(2, 1, hel1, hel1name, *schedIt, false, useIdealRrc),
814 TestCase::EXTENSIVE);
816 new LteX2HandoverTestCase(2, 2, hel1, hel1name, *schedIt, false, useIdealRrc),
817 TestCase::EXTENSIVE);
819 new LteX2HandoverTestCase(1, 0, hel2, hel2name, *schedIt, true, useIdealRrc),
820 TestCase::EXTENSIVE);
822 new LteX2HandoverTestCase(1, 1, hel2, hel2name, *schedIt, true, useIdealRrc),
823 TestCase::EXTENSIVE);
825 new LteX2HandoverTestCase(1, 2, hel2, hel2name, *schedIt, true, useIdealRrc),
826 TestCase::EXTENSIVE);
828 new LteX2HandoverTestCase(1, 0, hel3, hel3name, *schedIt, true, useIdealRrc),
829 TestCase::EXTENSIVE);
831 new LteX2HandoverTestCase(1, 1, hel3, hel3name, *schedIt, true, useIdealRrc),
832 TestCase::EXTENSIVE);
834 new LteX2HandoverTestCase(1, 2, hel3, hel3name, *schedIt, true, useIdealRrc),
835 TestCase::EXTENSIVE);
837 new LteX2HandoverTestCase(2, 0, hel3, hel3name, *schedIt, true, useIdealRrc),
838 TestCase::EXTENSIVE);
840 new LteX2HandoverTestCase(2, 1, hel3, hel3name, *schedIt, true, useIdealRrc),
841 TestCase::EXTENSIVE);
843 new LteX2HandoverTestCase(2, 2, hel3, hel3name, *schedIt, true, useIdealRrc),
844 TestCase::QUICK);
846 new LteX2HandoverTestCase(2, 0, hel4, hel4name, *schedIt, true, useIdealRrc),
847 TestCase::EXTENSIVE);
849 new LteX2HandoverTestCase(2, 1, hel4, hel4name, *schedIt, true, useIdealRrc),
850 TestCase::EXTENSIVE);
852 new LteX2HandoverTestCase(2, 2, hel4, hel4name, *schedIt, true, useIdealRrc),
853 TestCase::EXTENSIVE);
855 new LteX2HandoverTestCase(2, 0, hel5, hel5name, *schedIt, true, useIdealRrc),
856 TestCase::EXTENSIVE);
858 new LteX2HandoverTestCase(2, 1, hel5, hel5name, *schedIt, true, useIdealRrc),
859 TestCase::EXTENSIVE);
861 new LteX2HandoverTestCase(2, 2, hel5, hel5name, *schedIt, true, useIdealRrc),
862 TestCase::EXTENSIVE);
864 new LteX2HandoverTestCase(3, 0, hel3, hel3name, *schedIt, true, useIdealRrc),
865 TestCase::EXTENSIVE);
867 new LteX2HandoverTestCase(3, 1, hel3, hel3name, *schedIt, true, useIdealRrc),
868 TestCase::EXTENSIVE);
870 new LteX2HandoverTestCase(3, 2, hel3, hel3name, *schedIt, true, useIdealRrc),
871 TestCase::EXTENSIVE);
873 new LteX2HandoverTestCase(3, 0, hel4, hel4name, *schedIt, true, useIdealRrc),
874 TestCase::EXTENSIVE);
876 new LteX2HandoverTestCase(3, 1, hel4, hel4name, *schedIt, true, useIdealRrc),
877 TestCase::EXTENSIVE);
879 new LteX2HandoverTestCase(3, 2, hel4, hel4name, *schedIt, true, useIdealRrc),
880 TestCase::EXTENSIVE);
882 new LteX2HandoverTestCase(3, 0, hel5, hel5name, *schedIt, true, useIdealRrc),
883 TestCase::EXTENSIVE);
885 new LteX2HandoverTestCase(3, 1, hel5, hel5name, *schedIt, true, useIdealRrc),
886 TestCase::EXTENSIVE);
888 new LteX2HandoverTestCase(3, 2, hel5, hel5name, *schedIt, true, useIdealRrc),
889 TestCase::QUICK);
890 }
891 }
892}
893
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.
AttributeValue implementation for Boolean.
Definition: boolean.h:37
AttributeValue implementation for DataRate.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
This class contains the specification of EPS Bearers.
Definition: eps-bearer.h:91
Qci
QoS Class Indicator.
Definition: eps-bearer.h:106
an Inet address class
aggregate IP/TCP/UDP functionality to existing Nodes.
void Install(std::string nodeName) const
Aggregate implementations of the ns3::Ipv4, ns3::Ipv6, ns3::Udp, and ns3::Tcp classes onto the provid...
A helper class to make life easier while doing simple IPv4 address assignment in scripts.
void SetBase(Ipv4Address network, Ipv4Mask mask, Ipv4Address base="0.0.0.1")
Set the base network number, network mask and base address.
Ipv4InterfaceContainer Assign(const NetDeviceContainer &c)
Assign IP addresses to the net devices specified in the container based on the current network prefix...
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:43
Access to the IPv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:79
holds a vector of std::pair of Ptr<Ipv4> and interface index.
Ipv4Address GetAddress(uint32_t i, uint32_t j=0) const
a class to represent an Ipv4 address mask
Definition: ipv4-address.h:258
Helper class that adds ns3::Ipv4StaticRouting objects.
Ptr< Ipv4StaticRouting > GetStaticRouting(Ptr< Ipv4 > ipv4) const
Try and find the static routing protocol as either the main routing protocol or in the list of routin...
store information on active data radio bearer instance
The eNodeB device implementation.
uint16_t GetDlBandwidth() const
uint32_t GetUlEarfcn() const
uint32_t GetDlEarfcn() const
Ptr< LteEnbRrc > GetRrc() const
uint16_t GetUlBandwidth() const
uint16_t GetCellId() const
void SetEpcHelper(Ptr< EpcHelper > h)
Set the EpcHelper to be used to setup the EPC network in conjunction with the setup of the LTE radio ...
Definition: lte-helper.cc:282
void HandoverRequest(Time hoTime, Ptr< NetDevice > ueDev, Ptr< NetDevice > sourceEnbDev, Ptr< NetDevice > targetEnbDev)
Manually trigger an X2-based handover.
Definition: lte-helper.cc:1343
NetDeviceContainer InstallEnbDevice(NodeContainer c)
Create a set of eNodeB devices.
Definition: lte-helper.cc:482
void SetHandoverAlgorithmType(std::string type)
Set the type of handover algorithm to be used by eNodeB devices.
Definition: lte-helper.cc:337
void SetSchedulerType(std::string type)
Set the type of scheduler to be used by eNodeB devices.
Definition: lte-helper.cc:289
void Attach(NetDeviceContainer ueDevices)
Enables automatic attachment of a set of UE devices to a suitable cell using Idle mode initial cell s...
Definition: lte-helper.cc:1044
void ActivateDataRadioBearer(NetDeviceContainer ueDevices, EpsBearer bearer)
Activate a Data Radio Bearer on a given UE devices (for LTE-only simulation).
Definition: lte-helper.cc:1441
NetDeviceContainer InstallUeDevice(NodeContainer c)
Create a set of UE devices.
Definition: lte-helper.cc:497
void AddX2Interface(NodeContainer enbNodes)
Create an X2 interface between all the eNBs in a given set.
Definition: lte-helper.cc:1318
int64_t AssignStreams(NetDeviceContainer c, int64_t stream)
Assign a fixed random variable stream number to the random variables used.
Definition: lte-helper.cc:1572
uint8_t ActivateDedicatedEpsBearer(NetDeviceContainer ueDevices, EpsBearer bearer, Ptr< EpcTft > tft)
Activate a dedicated EPS bearer on a given set of UE devices.
Definition: lte-helper.cc:1159
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.
Vector GetPosition() const
void SetPosition(const Vector &position)
holds a vector of ns3::NetDevice pointers
uint32_t GetN() const
Get the number of Ptr<NetDevice> stored in this container.
std::vector< Ptr< NetDevice > >::const_iterator Iterator
NetDevice container iterator.
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.
Ptr< Node > GetPgwNode() const override
Get the PGW node.
Ipv4Address GetUeDefaultGatewayAddress() override
Ipv4InterfaceContainer AssignUeIpv4Address(NetDeviceContainer ueDevices) override
Assign IPv4 addresses to UE devices.
keep track of a set of node pointers.
uint32_t GetN() const
Get the number of Ptr<Node> stored in this container.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:200
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
Container for a set of ns3::Object pointers.
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.
std::map< std::size_t, Ptr< Object > >::const_iterator Iterator
Iterator type for traversing this container.
A helper to make it easier to instantiate an ns3::PacketSinkApplication on a set of nodes.
ApplicationContainer Install(NodeContainer c) const
Install an ns3::PacketSinkApplication on each node of the input container configured with all the att...
Receive and consume traffic generated to an IP address and port.
Definition: packet-sink.h:74
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:78
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
Hold variables of type string.
Definition: string.h:56
encapsulates test code
Definition: test.h:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:305
A suite of tests to run.
Definition: test.h:1256
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
AttributeValue implementation for Time.
Definition: nstime.h:1423
Create a client application which sends UDP packets carrying a 32bit sequence number and a 64 bit tim...
ApplicationContainer Install(NodeContainer c)
State
The state of the UeManager at the eNB RRC.
Definition: lte-enb-rrc.h:82
Hold an unsigned integer type.
Definition: uinteger.h:45
double GetValue(double min, double max)
Get the next random value, as a double in the specified range .
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:86
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:856
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:891
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
static LteX2HandoverTestSuite g_lteX2HandoverTestSuiteInstance
Static variable for test initialization.
void(* DataRate)(DataRate oldValue, DataRate newValue)
TracedValue callback signature for DataRate.
Definition: data-rate.h:328
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition: test.h:144
#define NS_TEST_ASSERT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report and abort if not.
Definition: test.h:564
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1348
serverApps
Definition: first.py:48
clientApps
Definition: first.py:58
Every class exported by the ns3 library is enclosed in the ns3 namespace.
mobility
Definition: third.py:96
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:71
uint16_t localPortEnd
end of the port number range of the UE
Definition: epc-tft.h:132
uint16_t remotePortEnd
end of the port number range of the remote host
Definition: epc-tft.h:130
uint16_t remotePortStart
start of the port number range of the remote host
Definition: epc-tft.h:129
uint16_t localPortStart
start of the port number range of the UE
Definition: epc-tft.h:131