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/core-module.h>
21 #include <ns3/internet-module.h>
22 #include <ns3/lte-module.h>
23 #include <ns3/mobility-module.h>
24 #include <ns3/network-module.h>
25 #include <ns3/packet-sink-helper.h>
26 #include <ns3/packet-sink.h>
27 #include <ns3/point-to-point-module.h>
28 #include <ns3/udp-client-server-helper.h>
29 
30 using namespace ns3;
31 
32 NS_LOG_COMPONENT_DEFINE("LteX2HandoverTest");
33 
40 {
42  uint32_t ueDeviceIndex;
45 };
46 
54 {
55  public:
67  LteX2HandoverTestCase(uint32_t nUes,
68  uint32_t nDedicatedBearers,
69  std::list<HandoverEvent> handoverEventList,
70  std::string handoverEventListName,
71  std::string schedulerType,
72  bool admitHo,
73  bool useIdealRrc);
74 
75  private:
86  static std::string BuildNameString(uint32_t nUes,
87  uint32_t nDedicatedBearers,
88  std::string handoverEventListName,
89  std::string schedulerType,
90  bool admitHo,
91  bool useIdealRrc);
92  void DoRun() override;
98  void CheckConnected(Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice);
99 
104  void TeleportUeToMiddle(Ptr<Node> ueNode);
105 
111  void TeleportUeNearTargetEnb(Ptr<Node> ueNode, Ptr<Node> enbNode);
112 
113  uint32_t m_nUes;
115  std::list<HandoverEvent> m_handoverEventList;
117  bool m_epc;
118  std::string m_schedulerType;
119  bool m_admitHo;
123 
129  struct BearerData
130  {
131  uint32_t bid;
134  uint32_t dlOldTotalRx;
135  uint32_t ulOldTotalRx;
136  };
137 
143  struct UeData
144  {
145  uint32_t id;
146  std::list<BearerData> bearerDataList;
147  };
148 
153  void SaveStatsAfterHandover(uint32_t ueIndex);
158  void CheckStatsAWhileAfterHandover(uint32_t ueIndex);
159 
160  std::vector<UeData> m_ueDataVector;
161 
165  const uint32_t m_udpClientPktSize;
166 };
167 
168 std::string
170  uint32_t nDedicatedBearers,
171  std::string handoverEventListName,
172  std::string schedulerType,
173  bool admitHo,
174  bool useIdealRrc)
175 {
176  std::ostringstream oss;
177  oss << " nUes=" << nUes << " nDedicatedBearers=" << nDedicatedBearers << " " << schedulerType
178  << " admitHo=" << admitHo << " hoList: " << handoverEventListName;
179  if (useIdealRrc)
180  {
181  oss << ", ideal RRC";
182  }
183  else
184  {
185  oss << ", real RRC";
186  }
187  return oss.str();
188 }
189 
191  uint32_t nDedicatedBearers,
192  std::list<HandoverEvent> handoverEventList,
193  std::string handoverEventListName,
194  std::string schedulerType,
195  bool admitHo,
196  bool useIdealRrc)
197  : TestCase(BuildNameString(nUes,
198  nDedicatedBearers,
199  handoverEventListName,
200  schedulerType,
201  admitHo,
202  useIdealRrc)),
203  m_nUes(nUes),
204  m_nDedicatedBearers(nDedicatedBearers),
205  m_handoverEventList(handoverEventList),
206  m_handoverEventListName(handoverEventListName),
207  m_epc(true),
208  m_schedulerType(schedulerType),
209  m_admitHo(admitHo),
210  m_useIdealRrc(useIdealRrc),
211  m_maxHoDuration(Seconds(0.1)),
212  m_statsDuration(Seconds(0.1)),
213  m_udpClientInterval(Seconds(0.01)),
214  m_udpClientPktSize(100)
215 
216 {
217 }
218 
219 void
221 {
226  m_admitHo,
227  m_useIdealRrc));
228 
229  uint32_t previousSeed = RngSeedManager::GetSeed();
230  uint64_t previousRun = RngSeedManager::GetRun();
231  Config::Reset();
232  // This test is sensitive to random variable stream assignments
233  RngSeedManager::SetSeed(1);
234  RngSeedManager::SetRun(3);
235  Config::SetDefault("ns3::UdpClient::Interval", TimeValue(m_udpClientInterval));
236  Config::SetDefault("ns3::UdpClient::MaxPackets", UintegerValue(1000000));
237  Config::SetDefault("ns3::UdpClient::PacketSize", UintegerValue(m_udpClientPktSize));
238 
239  // Disable Uplink Power Control
240  Config::SetDefault("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue(false));
241 
242  int64_t stream = 1;
243 
244  m_lteHelper = CreateObject<LteHelper>();
245  m_lteHelper->SetAttribute("PathlossModel",
246  StringValue("ns3::FriisSpectrumPropagationLossModel"));
249  "ns3::NoOpHandoverAlgorithm"); // disable automatic handover
251 
252  NodeContainer enbNodes;
253  enbNodes.Create(2);
254  NodeContainer ueNodes;
255  ueNodes.Create(m_nUes);
256 
257  if (m_epc)
258  {
259  m_epcHelper = CreateObject<PointToPointEpcHelper>();
261  }
262 
263  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
264  positionAlloc->Add(Vector(-3000, 0, 0)); // enb0
265  positionAlloc->Add(Vector(3000, 0, 0)); // enb1
266  for (uint32_t i = 0; i < m_nUes; i++)
267  {
268  positionAlloc->Add(Vector(-3000, 100, 0));
269  }
271  mobility.SetPositionAllocator(positionAlloc);
272  mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
273  mobility.Install(enbNodes);
274  mobility.Install(ueNodes);
275 
276  NetDeviceContainer enbDevices;
277  enbDevices = m_lteHelper->InstallEnbDevice(enbNodes);
278  stream += m_lteHelper->AssignStreams(enbDevices, stream);
279  for (auto it = enbDevices.Begin(); it != enbDevices.End(); ++it)
280  {
281  Ptr<LteEnbRrc> enbRrc = (*it)->GetObject<LteEnbNetDevice>()->GetRrc();
282  enbRrc->SetAttribute("AdmitHandoverRequest", BooleanValue(m_admitHo));
283  }
284 
285  NetDeviceContainer ueDevices;
286  ueDevices = m_lteHelper->InstallUeDevice(ueNodes);
287  stream += m_lteHelper->AssignStreams(ueDevices, stream);
288 
289  Ipv4Address remoteHostAddr;
290  Ipv4StaticRoutingHelper ipv4RoutingHelper;
291  Ipv4InterfaceContainer ueIpIfaces;
292  Ptr<Node> remoteHost;
293  if (m_epc)
294  {
295  // Create a single RemoteHost
296  NodeContainer remoteHostContainer;
297  remoteHostContainer.Create(1);
298  remoteHost = remoteHostContainer.Get(0);
300  internet.Install(remoteHostContainer);
301 
302  // Create the Internet
303  PointToPointHelper p2ph;
304  p2ph.SetDeviceAttribute("DataRate", DataRateValue(DataRate("100Gb/s")));
305  p2ph.SetDeviceAttribute("Mtu", UintegerValue(1500));
306  p2ph.SetChannelAttribute("Delay", TimeValue(Seconds(0.010)));
308  NetDeviceContainer internetDevices = p2ph.Install(pgw, remoteHost);
309  Ipv4AddressHelper ipv4h;
310  ipv4h.SetBase("1.0.0.0", "255.0.0.0");
311  Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign(internetDevices);
312  // in this container, interface 0 is the pgw, 1 is the remoteHost
313  remoteHostAddr = internetIpIfaces.GetAddress(1);
314 
315  Ipv4StaticRoutingHelper ipv4RoutingHelper;
316  Ptr<Ipv4StaticRouting> remoteHostStaticRouting =
317  ipv4RoutingHelper.GetStaticRouting(remoteHost->GetObject<Ipv4>());
318  remoteHostStaticRouting->AddNetworkRouteTo(Ipv4Address("7.0.0.0"),
319  Ipv4Mask("255.0.0.0"),
320  1);
321 
322  // Install the IP stack on the UEs
323  internet.Install(ueNodes);
324  ueIpIfaces = m_epcHelper->AssignUeIpv4Address(NetDeviceContainer(ueDevices));
325  }
326 
327  // attachment (needs to be done after IP stack configuration)
328  // all UEs attached to eNB 0 at the beginning
329  m_lteHelper->Attach(ueDevices, enbDevices.Get(0));
330 
331  if (m_epc)
332  {
333  // always true: bool epcDl = true;
334  // always true: bool epcUl = true;
335  // the rest of this block is copied from lena-dual-stripe
336 
337  // Install and start applications on UEs and remote host
338  uint16_t dlPort = 10000;
339  uint16_t ulPort = 20000;
340 
341  // randomize a bit start times to avoid simulation artifacts
342  // (e.g., buffer overflows due to packet transmissions happening
343  // exactly at the same time)
344  Ptr<UniformRandomVariable> startTimeSeconds = CreateObject<UniformRandomVariable>();
345  startTimeSeconds->SetAttribute("Min", DoubleValue(0));
346  startTimeSeconds->SetAttribute("Max", DoubleValue(0.010));
347  startTimeSeconds->SetStream(stream++);
348 
349  for (uint32_t u = 0; u < ueNodes.GetN(); ++u)
350  {
351  Ptr<Node> ue = ueNodes.Get(u);
352  // Set the default gateway for the UE
353  Ptr<Ipv4StaticRouting> ueStaticRouting =
354  ipv4RoutingHelper.GetStaticRouting(ue->GetObject<Ipv4>());
355  ueStaticRouting->SetDefaultRoute(m_epcHelper->GetUeDefaultGatewayAddress(), 1);
356 
357  UeData ueData;
358 
359  for (uint32_t b = 0; b < m_nDedicatedBearers; ++b)
360  {
361  ++dlPort;
362  ++ulPort;
363 
366  BearerData bearerData = BearerData();
367 
368  // always true: if (epcDl)
369  {
370  UdpClientHelper dlClientHelper(ueIpIfaces.GetAddress(u), dlPort);
371  clientApps.Add(dlClientHelper.Install(remoteHost));
372  PacketSinkHelper dlPacketSinkHelper(
373  "ns3::UdpSocketFactory",
374  InetSocketAddress(Ipv4Address::GetAny(), dlPort));
375  ApplicationContainer sinkContainer = dlPacketSinkHelper.Install(ue);
376  bearerData.dlSink = sinkContainer.Get(0)->GetObject<PacketSink>();
377  serverApps.Add(sinkContainer);
378  }
379  // always true: if (epcUl)
380  {
381  UdpClientHelper ulClientHelper(remoteHostAddr, ulPort);
382  clientApps.Add(ulClientHelper.Install(ue));
383  PacketSinkHelper ulPacketSinkHelper(
384  "ns3::UdpSocketFactory",
385  InetSocketAddress(Ipv4Address::GetAny(), ulPort));
386  ApplicationContainer sinkContainer = ulPacketSinkHelper.Install(remoteHost);
387  bearerData.ulSink = sinkContainer.Get(0)->GetObject<PacketSink>();
388  serverApps.Add(sinkContainer);
389  }
390 
391  Ptr<EpcTft> tft = Create<EpcTft>();
392  // always true: if (epcDl)
393  {
395  dlpf.localPortStart = dlPort;
396  dlpf.localPortEnd = dlPort;
397  tft->Add(dlpf);
398  }
399  // always true: if (epcUl)
400  {
402  ulpf.remotePortStart = ulPort;
403  ulpf.remotePortEnd = ulPort;
404  tft->Add(ulpf);
405  }
406 
407  // always true: if (epcDl || epcUl)
408  {
409  EpsBearer bearer(EpsBearer::NGBR_VIDEO_TCP_DEFAULT);
410  m_lteHelper->ActivateDedicatedEpsBearer(ueDevices.Get(u), bearer, tft);
411  }
412  double d = startTimeSeconds->GetValue();
413  Time startTime = Seconds(d);
414  serverApps.Start(startTime);
415  clientApps.Start(startTime);
416 
417  ueData.bearerDataList.push_back(bearerData);
418 
419  } // end for b
420 
421  m_ueDataVector.push_back(ueData);
422  }
423  }
424  else // (epc == false)
425  {
426  // for radio bearer activation purposes, consider together home UEs and macro UEs
427  for (uint32_t u = 0; u < ueDevices.GetN(); ++u)
428  {
429  Ptr<NetDevice> ueDev = ueDevices.Get(u);
430  for (uint32_t b = 0; b < m_nDedicatedBearers; ++b)
431  {
432  EpsBearer::Qci q = EpsBearer::NGBR_VIDEO_TCP_DEFAULT;
433  EpsBearer bearer(q);
434  m_lteHelper->ActivateDataRadioBearer(ueDev, bearer);
435  }
436  }
437  }
438 
439  m_lteHelper->AddX2Interface(enbNodes);
440 
441  // check initial RRC connection
442  const Time maxRrcConnectionEstablishmentDuration = Seconds(0.080);
443  for (auto it = ueDevices.Begin(); it != ueDevices.End(); ++it)
444  {
445  Simulator::Schedule(maxRrcConnectionEstablishmentDuration,
447  this,
448  *it,
449  enbDevices.Get(0));
450  }
451 
452  // schedule handover events and corresponding checks
453 
454  Time stopTime = Seconds(0);
455  for (auto hoEventIt = m_handoverEventList.begin(); hoEventIt != m_handoverEventList.end();
456  ++hoEventIt)
457  {
458  // Teleport the UE between both eNBs just before the handover starts
459  Simulator::Schedule(hoEventIt->startTime - MilliSeconds(10),
461  this,
462  ueNodes.Get(hoEventIt->ueDeviceIndex));
463 
464  Simulator::Schedule(hoEventIt->startTime,
466  this,
467  ueDevices.Get(hoEventIt->ueDeviceIndex),
468  enbDevices.Get(hoEventIt->sourceEnbDeviceIndex));
469 
470  m_lteHelper->HandoverRequest(hoEventIt->startTime,
471  ueDevices.Get(hoEventIt->ueDeviceIndex),
472  enbDevices.Get(hoEventIt->sourceEnbDeviceIndex),
473  enbDevices.Get(hoEventIt->targetEnbDeviceIndex));
474 
475  // Once the handover is finished, teleport the UE near the target eNB
476  Simulator::Schedule(hoEventIt->startTime + MilliSeconds(40),
478  this,
479  ueNodes.Get(hoEventIt->ueDeviceIndex),
480  enbNodes.Get(m_admitHo ? hoEventIt->targetEnbDeviceIndex
481  : hoEventIt->sourceEnbDeviceIndex));
482 
483  Time hoEndTime = hoEventIt->startTime + m_maxHoDuration;
484  Simulator::Schedule(hoEndTime,
486  this,
487  ueDevices.Get(hoEventIt->ueDeviceIndex),
488  enbDevices.Get(m_admitHo ? hoEventIt->targetEnbDeviceIndex
489  : hoEventIt->sourceEnbDeviceIndex));
490  Simulator::Schedule(hoEndTime,
492  this,
493  hoEventIt->ueDeviceIndex);
494 
495  Time checkStatsAfterHoTime = hoEndTime + m_statsDuration;
496  Simulator::Schedule(checkStatsAfterHoTime,
498  this,
499  hoEventIt->ueDeviceIndex);
500  if (stopTime <= checkStatsAfterHoTime)
501  {
502  stopTime = checkStatsAfterHoTime + MilliSeconds(1);
503  }
504  }
505 
506  // m_lteHelper->EnableRlcTraces ();
507  // m_lteHelper->EnablePdcpTraces();
508 
509  Simulator::Stop(stopTime);
510 
511  Simulator::Run();
512 
513  Simulator::Destroy();
514 
515  // Undo changes to default settings
516  Config::Reset();
517  // Restore the previous settings of RngSeed and RngRun
518  RngSeedManager::SetSeed(previousSeed);
519  RngSeedManager::SetRun(previousRun);
520 }
521 
522 void
524 {
525  Ptr<LteUeNetDevice> ueLteDevice = ueDevice->GetObject<LteUeNetDevice>();
526  Ptr<LteUeRrc> ueRrc = ueLteDevice->GetRrc();
527  NS_TEST_ASSERT_MSG_EQ(ueRrc->GetState(), LteUeRrc::CONNECTED_NORMALLY, "Wrong LteUeRrc state!");
528 
529  Ptr<LteEnbNetDevice> enbLteDevice = enbDevice->GetObject<LteEnbNetDevice>();
530  Ptr<LteEnbRrc> enbRrc = enbLteDevice->GetRrc();
531  uint16_t rnti = ueRrc->GetRnti();
532  Ptr<UeManager> ueManager = enbRrc->GetUeManager(rnti);
533  NS_TEST_ASSERT_MSG_NE(ueManager, nullptr, "RNTI " << rnti << " not found in eNB");
534 
535  UeManager::State ueManagerState = ueManager->GetState();
536  NS_TEST_ASSERT_MSG_EQ(ueManagerState, UeManager::CONNECTED_NORMALLY, "Wrong UeManager state!");
537  NS_ASSERT_MSG(ueManagerState == UeManager::CONNECTED_NORMALLY, "Wrong UeManager state!");
538 
539  uint16_t ueCellId = ueRrc->GetCellId();
540  uint16_t enbCellId = enbLteDevice->GetCellId();
541  uint8_t ueDlBandwidth = ueRrc->GetDlBandwidth();
542  uint8_t enbDlBandwidth = enbLteDevice->GetDlBandwidth();
543  uint8_t ueUlBandwidth = ueRrc->GetUlBandwidth();
544  uint8_t enbUlBandwidth = enbLteDevice->GetUlBandwidth();
545  uint8_t ueDlEarfcn = ueRrc->GetDlEarfcn();
546  uint8_t enbDlEarfcn = enbLteDevice->GetDlEarfcn();
547  uint8_t ueUlEarfcn = ueRrc->GetUlEarfcn();
548  uint8_t enbUlEarfcn = enbLteDevice->GetUlEarfcn();
549  uint64_t ueImsi = ueLteDevice->GetImsi();
550  uint64_t enbImsi = ueManager->GetImsi();
551 
552  NS_TEST_ASSERT_MSG_EQ(ueImsi, enbImsi, "inconsistent IMSI");
553  NS_TEST_ASSERT_MSG_EQ(ueCellId, enbCellId, "inconsistent CellId");
554  NS_TEST_ASSERT_MSG_EQ(ueDlBandwidth, enbDlBandwidth, "inconsistent DlBandwidth");
555  NS_TEST_ASSERT_MSG_EQ(ueUlBandwidth, enbUlBandwidth, "inconsistent UlBandwidth");
556  NS_TEST_ASSERT_MSG_EQ(ueDlEarfcn, enbDlEarfcn, "inconsistent DlEarfcn");
557  NS_TEST_ASSERT_MSG_EQ(ueUlEarfcn, enbUlEarfcn, "inconsistent UlEarfcn");
558 
559  ObjectMapValue enbDataRadioBearerMapValue;
560  ueManager->GetAttribute("DataRadioBearerMap", enbDataRadioBearerMapValue);
561  NS_TEST_ASSERT_MSG_EQ(enbDataRadioBearerMapValue.GetN(),
563  "wrong num bearers at eNB");
564 
565  ObjectMapValue ueDataRadioBearerMapValue;
566  ueRrc->GetAttribute("DataRadioBearerMap", ueDataRadioBearerMapValue);
567  NS_TEST_ASSERT_MSG_EQ(ueDataRadioBearerMapValue.GetN(),
569  "wrong num bearers at UE");
570 
571  auto enbBearerIt = enbDataRadioBearerMapValue.Begin();
572  auto ueBearerIt = ueDataRadioBearerMapValue.Begin();
573  while (enbBearerIt != enbDataRadioBearerMapValue.End() &&
574  ueBearerIt != ueDataRadioBearerMapValue.End())
575  {
576  Ptr<LteDataRadioBearerInfo> enbDrbInfo =
577  enbBearerIt->second->GetObject<LteDataRadioBearerInfo>();
578  Ptr<LteDataRadioBearerInfo> ueDrbInfo =
579  ueBearerIt->second->GetObject<LteDataRadioBearerInfo>();
580  // NS_TEST_ASSERT_MSG_EQ (enbDrbInfo->m_epsBearer, ueDrbInfo->m_epsBearer, "epsBearer
581  // differs");
582  NS_TEST_ASSERT_MSG_EQ((uint32_t)enbDrbInfo->m_epsBearerIdentity,
583  (uint32_t)ueDrbInfo->m_epsBearerIdentity,
584  "epsBearerIdentity differs");
585  NS_TEST_ASSERT_MSG_EQ((uint32_t)enbDrbInfo->m_drbIdentity,
586  (uint32_t)ueDrbInfo->m_drbIdentity,
587  "drbIdentity differs");
588  // NS_TEST_ASSERT_MSG_EQ (enbDrbInfo->m_rlcConfig, ueDrbInfo->m_rlcConfig, "rlcConfig
589  // differs");
590  NS_TEST_ASSERT_MSG_EQ((uint32_t)enbDrbInfo->m_logicalChannelIdentity,
591  (uint32_t)ueDrbInfo->m_logicalChannelIdentity,
592  "logicalChannelIdentity differs");
593  // NS_TEST_ASSERT_MSG_EQ (enbDrbInfo->m_logicalChannelConfig,
594  // ueDrbInfo->m_logicalChannelConfig, "logicalChannelConfig differs");
595 
596  ++enbBearerIt;
597  ++ueBearerIt;
598  }
599  NS_ASSERT_MSG(enbBearerIt == enbDataRadioBearerMapValue.End(), "too many bearers at eNB");
600  NS_ASSERT_MSG(ueBearerIt == ueDataRadioBearerMapValue.End(), "too many bearers at UE");
601 }
602 
603 void
605 {
606  Ptr<MobilityModel> ueMobility = ueNode->GetObject<MobilityModel>();
607  ueMobility->SetPosition(Vector(0.0, 0.0, 0.0));
608 }
609 
610 void
612 {
613  Ptr<MobilityModel> enbMobility = enbNode->GetObject<MobilityModel>();
614  Vector pos = enbMobility->GetPosition();
615 
616  Ptr<MobilityModel> ueMobility = ueNode->GetObject<MobilityModel>();
617  ueMobility->SetPosition(pos + Vector(0.0, 100.0, 0.0));
618 }
619 
620 void
622 {
623  for (auto it = m_ueDataVector.at(ueIndex).bearerDataList.begin();
624  it != m_ueDataVector.at(ueIndex).bearerDataList.end();
625  ++it)
626  {
627  it->dlOldTotalRx = it->dlSink->GetTotalRx();
628  it->ulOldTotalRx = it->ulSink->GetTotalRx();
629  }
630 }
631 
632 void
634 {
635  uint32_t b = 1;
636  for (auto it = m_ueDataVector.at(ueIndex).bearerDataList.begin();
637  it != m_ueDataVector.at(ueIndex).bearerDataList.end();
638  ++it)
639  {
640  uint32_t dlRx = it->dlSink->GetTotalRx() - it->dlOldTotalRx;
641  uint32_t ulRx = it->ulSink->GetTotalRx() - it->ulOldTotalRx;
642  uint32_t expectedBytes =
644 
646  expectedBytes,
647  "too few RX bytes in DL, ue=" << ueIndex << ", b=" << b);
649  expectedBytes,
650  "too few RX bytes in UL, ue=" << ueIndex << ", b=" << b);
651  ++b;
652  }
653 }
654 
670 {
671  public:
673 };
674 
676  : TestSuite("lte-x2-handover", SYSTEM)
677 {
678  // in the following:
679  // fwd means handover from enb 0 to enb 1
680  // bwd means handover from enb 1 to enb 0
681 
682  HandoverEvent ue1fwd;
683  ue1fwd.startTime = MilliSeconds(100);
684  ue1fwd.ueDeviceIndex = 0;
685  ue1fwd.sourceEnbDeviceIndex = 0;
686  ue1fwd.targetEnbDeviceIndex = 1;
687 
688  HandoverEvent ue1bwd;
689  ue1bwd.startTime = MilliSeconds(400);
690  ue1bwd.ueDeviceIndex = 0;
691  ue1bwd.sourceEnbDeviceIndex = 1;
692  ue1bwd.targetEnbDeviceIndex = 0;
693 
694  HandoverEvent ue1fwdagain;
695  ue1fwdagain.startTime = MilliSeconds(700);
696  ue1fwdagain.ueDeviceIndex = 0;
697  ue1fwdagain.sourceEnbDeviceIndex = 0;
698  ue1fwdagain.targetEnbDeviceIndex = 1;
699 
700  HandoverEvent ue2fwd;
701  ue2fwd.startTime = MilliSeconds(110);
702  ue2fwd.ueDeviceIndex = 1;
703  ue2fwd.sourceEnbDeviceIndex = 0;
704  ue2fwd.targetEnbDeviceIndex = 1;
705 
706  HandoverEvent ue2bwd;
707  ue2bwd.startTime = MilliSeconds(350);
708  ue2bwd.ueDeviceIndex = 1;
709  ue2bwd.sourceEnbDeviceIndex = 1;
710  ue2bwd.targetEnbDeviceIndex = 0;
711 
712  std::string handoverEventList0name("none");
713  std::list<HandoverEvent> handoverEventList0;
714 
715  std::string handoverEventList1name("1 fwd");
716  const std::list<HandoverEvent> handoverEventList1{
717  ue1fwd,
718  };
719 
720  std::string handoverEventList2name("1 fwd & bwd");
721  const std::list<HandoverEvent> handoverEventList2{
722  ue1fwd,
723  ue1bwd,
724  };
725 
726  std::string handoverEventList3name("1 fwd & bwd & fwd");
727  const std::list<HandoverEvent> handoverEventList3{
728  ue1fwd,
729  ue1bwd,
730  ue1fwdagain,
731  };
732 
733  std::string handoverEventList4name("1+2 fwd");
734  const std::list<HandoverEvent> handoverEventList4{
735  ue1fwd,
736  ue2fwd,
737  };
738 
739  std::string handoverEventList5name("1+2 fwd & bwd");
740  const std::list<HandoverEvent> handoverEventList5{
741  ue1fwd,
742  ue1bwd,
743  ue2fwd,
744  ue2bwd,
745  };
746 
747  // std::string handoverEventList6name("2 fwd");
748  // const std::list<HandoverEvent> handoverEventList6{
749  // ue2fwd,
750  // };
751 
752  // std::string handoverEventList7name("2 fwd & bwd");
753  // const std::list<HandoverEvent> handoverEventList7{
754  // ue2fwd,
755  // ue2bwd,
756  // };
757 
758  std::vector<std::string> schedulers{
759  "ns3::RrFfMacScheduler",
760  "ns3::PfFfMacScheduler",
761  };
762 
763  for (auto schedIt = schedulers.begin(); schedIt != schedulers.end(); ++schedIt)
764  {
765  for (auto useIdealRrc : {true, false})
766  {
767  // nUes, nDBearers, helist, name, sched, admitHo, idealRrc
769  0,
770  handoverEventList0,
771  handoverEventList0name,
772  *schedIt,
773  true,
774  useIdealRrc),
775  TestCase::EXTENSIVE);
777  0,
778  handoverEventList0,
779  handoverEventList0name,
780  *schedIt,
781  true,
782  useIdealRrc),
783  TestCase::EXTENSIVE);
785  5,
786  handoverEventList0,
787  handoverEventList0name,
788  *schedIt,
789  true,
790  useIdealRrc),
791  TestCase::EXTENSIVE);
793  5,
794  handoverEventList0,
795  handoverEventList0name,
796  *schedIt,
797  true,
798  useIdealRrc),
799  TestCase::EXTENSIVE);
801  0,
802  handoverEventList1,
803  handoverEventList1name,
804  *schedIt,
805  true,
806  useIdealRrc),
807  TestCase::EXTENSIVE);
809  1,
810  handoverEventList1,
811  handoverEventList1name,
812  *schedIt,
813  true,
814  useIdealRrc),
815  TestCase::EXTENSIVE);
817  2,
818  handoverEventList1,
819  handoverEventList1name,
820  *schedIt,
821  true,
822  useIdealRrc),
823  TestCase::EXTENSIVE);
825  0,
826  handoverEventList1,
827  handoverEventList1name,
828  *schedIt,
829  false,
830  useIdealRrc),
831  TestCase::EXTENSIVE);
833  1,
834  handoverEventList1,
835  handoverEventList1name,
836  *schedIt,
837  false,
838  useIdealRrc),
839  TestCase::EXTENSIVE);
841  2,
842  handoverEventList1,
843  handoverEventList1name,
844  *schedIt,
845  false,
846  useIdealRrc),
847  TestCase::EXTENSIVE);
849  0,
850  handoverEventList1,
851  handoverEventList1name,
852  *schedIt,
853  true,
854  useIdealRrc),
855  TestCase::EXTENSIVE);
857  1,
858  handoverEventList1,
859  handoverEventList1name,
860  *schedIt,
861  true,
862  useIdealRrc),
863  TestCase::EXTENSIVE);
865  2,
866  handoverEventList1,
867  handoverEventList1name,
868  *schedIt,
869  true,
870  useIdealRrc),
871  TestCase::EXTENSIVE);
873  0,
874  handoverEventList1,
875  handoverEventList1name,
876  *schedIt,
877  false,
878  useIdealRrc),
879  TestCase::EXTENSIVE);
881  1,
882  handoverEventList1,
883  handoverEventList1name,
884  *schedIt,
885  false,
886  useIdealRrc),
887  TestCase::EXTENSIVE);
889  2,
890  handoverEventList1,
891  handoverEventList1name,
892  *schedIt,
893  false,
894  useIdealRrc),
895  TestCase::EXTENSIVE);
897  0,
898  handoverEventList2,
899  handoverEventList2name,
900  *schedIt,
901  true,
902  useIdealRrc),
903  TestCase::EXTENSIVE);
905  1,
906  handoverEventList2,
907  handoverEventList2name,
908  *schedIt,
909  true,
910  useIdealRrc),
911  TestCase::EXTENSIVE);
913  2,
914  handoverEventList2,
915  handoverEventList2name,
916  *schedIt,
917  true,
918  useIdealRrc),
919  TestCase::EXTENSIVE);
921  0,
922  handoverEventList3,
923  handoverEventList3name,
924  *schedIt,
925  true,
926  useIdealRrc),
927  TestCase::EXTENSIVE);
929  1,
930  handoverEventList3,
931  handoverEventList3name,
932  *schedIt,
933  true,
934  useIdealRrc),
935  TestCase::EXTENSIVE);
937  2,
938  handoverEventList3,
939  handoverEventList3name,
940  *schedIt,
941  true,
942  useIdealRrc),
943  TestCase::EXTENSIVE);
945  0,
946  handoverEventList3,
947  handoverEventList3name,
948  *schedIt,
949  true,
950  useIdealRrc),
951  TestCase::EXTENSIVE);
953  1,
954  handoverEventList3,
955  handoverEventList3name,
956  *schedIt,
957  true,
958  useIdealRrc),
959  TestCase::EXTENSIVE);
961  2,
962  handoverEventList3,
963  handoverEventList3name,
964  *schedIt,
965  true,
966  useIdealRrc),
967  TestCase::QUICK);
969  0,
970  handoverEventList4,
971  handoverEventList4name,
972  *schedIt,
973  true,
974  useIdealRrc),
975  TestCase::EXTENSIVE);
977  1,
978  handoverEventList4,
979  handoverEventList4name,
980  *schedIt,
981  true,
982  useIdealRrc),
983  TestCase::EXTENSIVE);
985  2,
986  handoverEventList4,
987  handoverEventList4name,
988  *schedIt,
989  true,
990  useIdealRrc),
991  TestCase::EXTENSIVE);
993  0,
994  handoverEventList5,
995  handoverEventList5name,
996  *schedIt,
997  true,
998  useIdealRrc),
999  TestCase::EXTENSIVE);
1001  1,
1002  handoverEventList5,
1003  handoverEventList5name,
1004  *schedIt,
1005  true,
1006  useIdealRrc),
1007  TestCase::EXTENSIVE);
1009  2,
1010  handoverEventList5,
1011  handoverEventList5name,
1012  *schedIt,
1013  true,
1014  useIdealRrc),
1015  TestCase::EXTENSIVE);
1017  0,
1018  handoverEventList3,
1019  handoverEventList3name,
1020  *schedIt,
1021  true,
1022  useIdealRrc),
1023  TestCase::EXTENSIVE);
1025  1,
1026  handoverEventList3,
1027  handoverEventList3name,
1028  *schedIt,
1029  true,
1030  useIdealRrc),
1031  TestCase::EXTENSIVE);
1033  2,
1034  handoverEventList3,
1035  handoverEventList3name,
1036  *schedIt,
1037  true,
1038  useIdealRrc),
1039  TestCase::EXTENSIVE);
1041  0,
1042  handoverEventList4,
1043  handoverEventList4name,
1044  *schedIt,
1045  true,
1046  useIdealRrc),
1047  TestCase::EXTENSIVE);
1049  1,
1050  handoverEventList4,
1051  handoverEventList4name,
1052  *schedIt,
1053  true,
1054  useIdealRrc),
1055  TestCase::EXTENSIVE);
1057  2,
1058  handoverEventList4,
1059  handoverEventList4name,
1060  *schedIt,
1061  true,
1062  useIdealRrc),
1063  TestCase::EXTENSIVE);
1065  0,
1066  handoverEventList5,
1067  handoverEventList5name,
1068  *schedIt,
1069  true,
1070  useIdealRrc),
1071  TestCase::EXTENSIVE);
1073  1,
1074  handoverEventList5,
1075  handoverEventList5name,
1076  *schedIt,
1077  true,
1078  useIdealRrc),
1079  TestCase::EXTENSIVE);
1081  2,
1082  handoverEventList5,
1083  handoverEventList5name,
1084  *schedIt,
1085  true,
1086  useIdealRrc),
1087  TestCase::QUICK);
1088  }
1089  }
1090 }
1091 
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.
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.
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:42
Access to the IPv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:80
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:257
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:285
void HandoverRequest(Time hoTime, Ptr< NetDevice > ueDev, Ptr< NetDevice > sourceEnbDev, Ptr< NetDevice > targetEnbDev)
Manually trigger an X2-based handover.
Definition: lte-helper.cc:1338
NetDeviceContainer InstallEnbDevice(NodeContainer c)
Create a set of eNodeB devices.
Definition: lte-helper.cc:485
void SetHandoverAlgorithmType(std::string type)
Set the type of handover algorithm to be used by eNodeB devices.
Definition: lte-helper.cc:340
void SetSchedulerType(std::string type)
Set the type of scheduler to be used by eNodeB devices.
Definition: lte-helper.cc:292
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:1039
void ActivateDataRadioBearer(NetDeviceContainer ueDevices, EpsBearer bearer)
Activate a Data Radio Bearer on a given UE devices (for LTE-only simulation).
Definition: lte-helper.cc:1436
NetDeviceContainer InstallUeDevice(NodeContainer c)
Create a set of UE devices.
Definition: lte-helper.cc:500
void AddX2Interface(NodeContainer enbNodes)
Create an X2 interface between all the eNBs in a given set.
Definition: lte-helper.cc:1313
int64_t AssignStreams(NetDeviceContainer c, int64_t stream)
Assign a fixed random variable stream number to the random variables used.
Definition: lte-helper.cc:1567
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:1154
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.
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:204
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.
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:75
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:77
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:301
A suite of tests to run.
Definition: test.h:1256
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
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:78
Hold an unsigned integer type.
Definition: uinteger.h:45
double GetValue(double min, double max)
Get the next random value drawn from the distribution.
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:855
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:890
#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:327
#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:1326
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
serverApps
Definition: first.py:54
clientApps
Definition: first.py:64
Every class exported by the ns3 library is enclosed in the ns3 namespace.
mobility
Definition: third.py:105
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