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 
28 using namespace ns3;
29 
30 NS_LOG_COMPONENT_DEFINE("LteX2HandoverTest");
31 
38 {
40  uint32_t ueDeviceIndex;
43 };
44 
52 {
53  public:
65  LteX2HandoverTestCase(uint32_t nUes,
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 
111  uint32_t m_nUes;
113  std::list<HandoverEvent> m_handoverEventList;
115  bool m_epc;
116  std::string m_schedulerType;
117  bool m_admitHo;
121 
127  struct BearerData
128  {
129  uint32_t bid;
132  uint32_t dlOldTotalRx;
133  uint32_t ulOldTotalRx;
134  };
135 
141  struct UeData
142  {
143  uint32_t id;
144  std::list<BearerData> bearerDataList;
145  };
146 
151  void SaveStatsAfterHandover(uint32_t ueIndex);
156  void CheckStatsAWhileAfterHandover(uint32_t ueIndex);
157 
158  std::vector<UeData> m_ueDataVector;
159 
163  const uint32_t m_udpClientPktSize;
164 };
165 
166 std::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 
217 void
219 {
224  m_admitHo,
225  m_useIdealRrc));
226 
227  uint32_t previousSeed = RngSeedManager::GetSeed();
228  uint64_t previousRun = RngSeedManager::GetRun();
229  Config::Reset();
230  // This test is sensitive to random variable stream assignments
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
301  PointToPointHelper p2ph;
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
515  Config::Reset();
516  // Restore the previous settings of RngSeed and RngRun
517  RngSeedManager::SetSeed(previousSeed);
518  RngSeedManager::SetRun(previousRun);
519 }
520 
521 void
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>();
577  Ptr<LteDataRadioBearerInfo> ueDrbInfo =
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 
602 void
604 {
605  Ptr<MobilityModel> ueMobility = ueNode->GetObject<MobilityModel>();
606  ueMobility->SetPosition(Vector(0.0, 0.0, 0.0));
607 }
608 
609 void
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 
619 void
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 
631 void
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, idealRrc
769  AddTestCase(
770  new LteX2HandoverTestCase(1, 0, hel0, hel0name, *schedIt, true, useIdealRrc),
771  TestCase::EXTENSIVE);
772  AddTestCase(
773  new LteX2HandoverTestCase(2, 0, hel0, hel0name, *schedIt, true, useIdealRrc),
774  TestCase::EXTENSIVE);
775  AddTestCase(
776  new LteX2HandoverTestCase(1, 5, hel0, hel0name, *schedIt, true, useIdealRrc),
777  TestCase::EXTENSIVE);
778  AddTestCase(
779  new LteX2HandoverTestCase(2, 5, hel0, hel0name, *schedIt, true, useIdealRrc),
780  TestCase::EXTENSIVE);
781  AddTestCase(
782  new LteX2HandoverTestCase(1, 0, hel1, hel1name, *schedIt, true, useIdealRrc),
783  TestCase::EXTENSIVE);
784  AddTestCase(
785  new LteX2HandoverTestCase(1, 1, hel1, hel1name, *schedIt, true, useIdealRrc),
786  TestCase::EXTENSIVE);
787  AddTestCase(
788  new LteX2HandoverTestCase(1, 2, hel1, hel1name, *schedIt, true, useIdealRrc),
789  TestCase::EXTENSIVE);
790  AddTestCase(
791  new LteX2HandoverTestCase(1, 0, hel1, hel1name, *schedIt, false, useIdealRrc),
792  TestCase::EXTENSIVE);
793  AddTestCase(
794  new LteX2HandoverTestCase(1, 1, hel1, hel1name, *schedIt, false, useIdealRrc),
795  TestCase::EXTENSIVE);
796  AddTestCase(
797  new LteX2HandoverTestCase(1, 2, hel1, hel1name, *schedIt, false, useIdealRrc),
798  TestCase::EXTENSIVE);
799  AddTestCase(
800  new LteX2HandoverTestCase(2, 0, hel1, hel1name, *schedIt, true, useIdealRrc),
801  TestCase::EXTENSIVE);
802  AddTestCase(
803  new LteX2HandoverTestCase(2, 1, hel1, hel1name, *schedIt, true, useIdealRrc),
804  TestCase::EXTENSIVE);
805  AddTestCase(
806  new LteX2HandoverTestCase(2, 2, hel1, hel1name, *schedIt, true, useIdealRrc),
807  TestCase::EXTENSIVE);
808  AddTestCase(
809  new LteX2HandoverTestCase(2, 0, hel1, hel1name, *schedIt, false, useIdealRrc),
810  TestCase::EXTENSIVE);
811  AddTestCase(
812  new LteX2HandoverTestCase(2, 1, hel1, hel1name, *schedIt, false, useIdealRrc),
813  TestCase::EXTENSIVE);
814  AddTestCase(
815  new LteX2HandoverTestCase(2, 2, hel1, hel1name, *schedIt, false, useIdealRrc),
816  TestCase::EXTENSIVE);
817  AddTestCase(
818  new LteX2HandoverTestCase(1, 0, hel2, hel2name, *schedIt, true, useIdealRrc),
819  TestCase::EXTENSIVE);
820  AddTestCase(
821  new LteX2HandoverTestCase(1, 1, hel2, hel2name, *schedIt, true, useIdealRrc),
822  TestCase::EXTENSIVE);
823  AddTestCase(
824  new LteX2HandoverTestCase(1, 2, hel2, hel2name, *schedIt, true, useIdealRrc),
825  TestCase::EXTENSIVE);
826  AddTestCase(
827  new LteX2HandoverTestCase(1, 0, hel3, hel3name, *schedIt, true, useIdealRrc),
828  TestCase::EXTENSIVE);
829  AddTestCase(
830  new LteX2HandoverTestCase(1, 1, hel3, hel3name, *schedIt, true, useIdealRrc),
831  TestCase::EXTENSIVE);
832  AddTestCase(
833  new LteX2HandoverTestCase(1, 2, hel3, hel3name, *schedIt, true, useIdealRrc),
834  TestCase::EXTENSIVE);
835  AddTestCase(
836  new LteX2HandoverTestCase(2, 0, hel3, hel3name, *schedIt, true, useIdealRrc),
837  TestCase::EXTENSIVE);
838  AddTestCase(
839  new LteX2HandoverTestCase(2, 1, hel3, hel3name, *schedIt, true, useIdealRrc),
840  TestCase::EXTENSIVE);
841  AddTestCase(
842  new LteX2HandoverTestCase(2, 2, hel3, hel3name, *schedIt, true, useIdealRrc),
843  TestCase::QUICK);
844  AddTestCase(
845  new LteX2HandoverTestCase(2, 0, hel4, hel4name, *schedIt, true, useIdealRrc),
846  TestCase::EXTENSIVE);
847  AddTestCase(
848  new LteX2HandoverTestCase(2, 1, hel4, hel4name, *schedIt, true, useIdealRrc),
849  TestCase::EXTENSIVE);
850  AddTestCase(
851  new LteX2HandoverTestCase(2, 2, hel4, hel4name, *schedIt, true, useIdealRrc),
852  TestCase::EXTENSIVE);
853  AddTestCase(
854  new LteX2HandoverTestCase(2, 0, hel5, hel5name, *schedIt, true, useIdealRrc),
855  TestCase::EXTENSIVE);
856  AddTestCase(
857  new LteX2HandoverTestCase(2, 1, hel5, hel5name, *schedIt, true, useIdealRrc),
858  TestCase::EXTENSIVE);
859  AddTestCase(
860  new LteX2HandoverTestCase(2, 2, hel5, hel5name, *schedIt, true, useIdealRrc),
861  TestCase::EXTENSIVE);
862  AddTestCase(
863  new LteX2HandoverTestCase(3, 0, hel3, hel3name, *schedIt, true, useIdealRrc),
864  TestCase::EXTENSIVE);
865  AddTestCase(
866  new LteX2HandoverTestCase(3, 1, hel3, hel3name, *schedIt, true, useIdealRrc),
867  TestCase::EXTENSIVE);
868  AddTestCase(
869  new LteX2HandoverTestCase(3, 2, hel3, hel3name, *schedIt, true, useIdealRrc),
870  TestCase::EXTENSIVE);
871  AddTestCase(
872  new LteX2HandoverTestCase(3, 0, hel4, hel4name, *schedIt, true, useIdealRrc),
873  TestCase::EXTENSIVE);
874  AddTestCase(
875  new LteX2HandoverTestCase(3, 1, hel4, hel4name, *schedIt, true, useIdealRrc),
876  TestCase::EXTENSIVE);
877  AddTestCase(
878  new LteX2HandoverTestCase(3, 2, hel4, hel4name, *schedIt, true, useIdealRrc),
879  TestCase::EXTENSIVE);
880  AddTestCase(
881  new LteX2HandoverTestCase(3, 0, hel5, hel5name, *schedIt, true, useIdealRrc),
882  TestCase::EXTENSIVE);
883  AddTestCase(
884  new LteX2HandoverTestCase(3, 1, hel5, hel5name, *schedIt, true, useIdealRrc),
885  TestCase::EXTENSIVE);
886  AddTestCase(
887  new LteX2HandoverTestCase(3, 2, hel5, hel5name, *schedIt, true, useIdealRrc),
888  TestCase::QUICK);
889  }
890  }
891 }
892 
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 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: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