A Discrete-Event Network Simulator
API
test-lte-x2-handover.cc
Go to the documentation of this file.
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Nicola Baldo <nbaldo@cttc.es>
19  */
20 
21 
22 #include <ns3/core-module.h>
23 #include <ns3/network-module.h>
24 #include <ns3/mobility-module.h>
25 #include <ns3/lte-module.h>
26 #include <ns3/internet-module.h>
27 #include <ns3/applications-module.h>
28 #include <ns3/point-to-point-module.h>
29 
30 using namespace ns3;
31 
32 NS_LOG_COMPONENT_DEFINE ("LteX2HandoverTest");
33 
41 {
43  uint32_t ueDeviceIndex;
46 };
47 
48 
57 {
58 public:
70  LteX2HandoverTestCase (uint32_t nUes, uint32_t nDedicatedBearers, std::list<HandoverEvent> handoverEventList, std::string handoverEventListName, std::string schedulerType, bool admitHo, bool useIdealRrc);
71 
72 private:
83  static std::string BuildNameString (uint32_t nUes, uint32_t nDedicatedBearers, std::string handoverEventListName, std::string schedulerType, bool admitHo, bool useIdealRrc);
84  virtual void DoRun (void);
90  void CheckConnected (Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice);
91 
96  void TeleportUeToMiddle (Ptr<Node> ueNode);
97 
103  void TeleportUeNearTargetEnb (Ptr<Node> ueNode, Ptr<Node> enbNode);
104 
105  uint32_t m_nUes;
107  std::list<HandoverEvent> m_handoverEventList;
109  bool m_epc;
110  std::string m_schedulerType;
111  bool m_admitHo;
115 
122  struct BearerData
123  {
124  uint32_t bid;
127  uint32_t dlOldTotalRx;
128  uint32_t ulOldTotalRx;
129  };
130 
137  struct UeData
138  {
139  uint32_t id;
140  std::list<BearerData> bearerDataList;
141  };
142 
147  void SaveStatsAfterHandover (uint32_t ueIndex);
152  void CheckStatsAWhileAfterHandover (uint32_t ueIndex);
153 
154  std::vector<UeData> m_ueDataVector;
155 
159  const uint32_t m_udpClientPktSize;
160 
161 };
162 
163 
164 std::string LteX2HandoverTestCase::BuildNameString (uint32_t nUes, uint32_t nDedicatedBearers, std::string handoverEventListName, std::string schedulerType, bool admitHo, bool useIdealRrc)
165 {
166  std::ostringstream oss;
167  oss << " nUes=" << nUes
168  << " nDedicatedBearers=" << nDedicatedBearers
169  << " " << schedulerType
170  << " admitHo=" << admitHo
171  << " hoList: " << handoverEventListName;
172  if (useIdealRrc)
173  {
174  oss << ", ideal RRC";
175  }
176  else
177  {
178  oss << ", real RRC";
179  }
180  return oss.str ();
181 }
182 
183 LteX2HandoverTestCase::LteX2HandoverTestCase (uint32_t nUes, uint32_t nDedicatedBearers, std::list<HandoverEvent> handoverEventList, std::string handoverEventListName, std::string schedulerType, bool admitHo, bool useIdealRrc)
184  : TestCase (BuildNameString (nUes, nDedicatedBearers, handoverEventListName, schedulerType, admitHo, useIdealRrc)),
185  m_nUes (nUes),
186  m_nDedicatedBearers (nDedicatedBearers),
187  m_handoverEventList (handoverEventList),
188  m_handoverEventListName (handoverEventListName),
189  m_epc (true),
190  m_schedulerType (schedulerType),
191  m_admitHo (admitHo),
192  m_useIdealRrc (useIdealRrc),
193  m_maxHoDuration (Seconds (0.1)),
194  m_statsDuration (Seconds (0.1)),
195  m_udpClientInterval (Seconds (0.01)),
196  m_udpClientPktSize (100)
197 
198 {}
199 
200 void
202 {
204 
205  Config::Reset ();
206  Config::SetDefault ("ns3::UdpClient::Interval", TimeValue (m_udpClientInterval));
207  Config::SetDefault ("ns3::UdpClient::MaxPackets", UintegerValue (1000000));
208  Config::SetDefault ("ns3::UdpClient::PacketSize", UintegerValue (m_udpClientPktSize));
209 
210  //Disable Uplink Power Control
211  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (false));
212 
213  int64_t stream = 1;
214 
215  m_lteHelper = CreateObject<LteHelper> ();
216  m_lteHelper->SetAttribute ("PathlossModel", StringValue ("ns3::FriisSpectrumPropagationLossModel"));
218  m_lteHelper->SetHandoverAlgorithmType ("ns3::NoOpHandoverAlgorithm"); // disable automatic handover
220 
221 
222  NodeContainer enbNodes;
223  enbNodes.Create (2);
224  NodeContainer ueNodes;
225  ueNodes.Create (m_nUes);
226 
227  if (m_epc)
228  {
229  m_epcHelper = CreateObject<PointToPointEpcHelper> ();
231  }
232 
233  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
234  positionAlloc->Add (Vector (-3000, 0, 0)); // enb0
235  positionAlloc->Add (Vector ( 3000, 0, 0)); // enb1
236  for (uint16_t i = 0; i < m_nUes; i++)
237  {
238  positionAlloc->Add (Vector (-3000, 100, 0));
239  }
241  mobility.SetPositionAllocator (positionAlloc);
242  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
243  mobility.Install (enbNodes);
244  mobility.Install (ueNodes);
245 
246  NetDeviceContainer enbDevices;
247  enbDevices = m_lteHelper->InstallEnbDevice (enbNodes);
248  stream += m_lteHelper->AssignStreams (enbDevices, stream);
249  for (NetDeviceContainer::Iterator it = enbDevices.Begin ();
250  it != enbDevices.End ();
251  ++it)
252  {
253  Ptr<LteEnbRrc> enbRrc = (*it)->GetObject<LteEnbNetDevice> ()->GetRrc ();
254  enbRrc->SetAttribute ("AdmitHandoverRequest", BooleanValue (m_admitHo));
255  }
256 
257  NetDeviceContainer ueDevices;
258  ueDevices = m_lteHelper->InstallUeDevice (ueNodes);
259  stream += m_lteHelper->AssignStreams (ueDevices, stream);
260 
261  Ipv4Address remoteHostAddr;
262  Ipv4StaticRoutingHelper ipv4RoutingHelper;
263  Ipv4InterfaceContainer ueIpIfaces;
264  Ptr<Node> remoteHost;
265  if (m_epc)
266  {
267  // Create a single RemoteHost
268  NodeContainer remoteHostContainer;
269  remoteHostContainer.Create (1);
270  remoteHost = remoteHostContainer.Get (0);
271  InternetStackHelper internet;
272  internet.Install (remoteHostContainer);
273 
274  // Create the Internet
275  PointToPointHelper p2ph;
276  p2ph.SetDeviceAttribute ("DataRate", DataRateValue (DataRate ("100Gb/s")));
277  p2ph.SetDeviceAttribute ("Mtu", UintegerValue (1500));
278  p2ph.SetChannelAttribute ("Delay", TimeValue (Seconds (0.010)));
279  Ptr<Node> pgw = m_epcHelper->GetPgwNode ();
280  NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost);
281  Ipv4AddressHelper ipv4h;
282  ipv4h.SetBase ("1.0.0.0", "255.0.0.0");
283  Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign (internetDevices);
284  // in this container, interface 0 is the pgw, 1 is the remoteHost
285  remoteHostAddr = internetIpIfaces.GetAddress (1);
286 
287  Ipv4StaticRoutingHelper ipv4RoutingHelper;
288  Ptr<Ipv4StaticRouting> remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject<Ipv4> ());
289  remoteHostStaticRouting->AddNetworkRouteTo (Ipv4Address ("7.0.0.0"), Ipv4Mask ("255.0.0.0"), 1);
290 
291  // Install the IP stack on the UEs
292  internet.Install (ueNodes);
293  ueIpIfaces = m_epcHelper->AssignUeIpv4Address (NetDeviceContainer (ueDevices));
294  }
295 
296  // attachment (needs to be done after IP stack configuration)
297  // all UEs attached to eNB 0 at the beginning
298  m_lteHelper->Attach (ueDevices, enbDevices.Get (0));
299 
300  if (m_epc)
301  {
302  // always true: bool epcDl = true;
303  // always true: bool epcUl = true;
304  // the rest of this block is copied from lena-dual-stripe
305 
306 
307  // Install and start applications on UEs and remote host
308  uint16_t dlPort = 10000;
309  uint16_t ulPort = 20000;
310 
311  // randomize a bit start times to avoid simulation artifacts
312  // (e.g., buffer overflows due to packet transmissions happening
313  // exactly at the same time)
314  Ptr<UniformRandomVariable> startTimeSeconds = CreateObject<UniformRandomVariable> ();
315  startTimeSeconds->SetAttribute ("Min", DoubleValue (0));
316  startTimeSeconds->SetAttribute ("Max", DoubleValue (0.010));
317  startTimeSeconds->SetStream (stream++);
318 
319  for (uint32_t u = 0; u < ueNodes.GetN (); ++u)
320  {
321  Ptr<Node> ue = ueNodes.Get (u);
322  // Set the default gateway for the UE
323  Ptr<Ipv4StaticRouting> ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ue->GetObject<Ipv4> ());
324  ueStaticRouting->SetDefaultRoute (m_epcHelper->GetUeDefaultGatewayAddress (), 1);
325 
326  UeData ueData;
327 
328  for (uint32_t b = 0; b < m_nDedicatedBearers; ++b)
329  {
330  ++dlPort;
331  ++ulPort;
332 
335  BearerData bearerData = BearerData ();
336 
337  // always true: if (epcDl)
338  {
339  UdpClientHelper dlClientHelper (ueIpIfaces.GetAddress (u), dlPort);
340  clientApps.Add (dlClientHelper.Install (remoteHost));
341  PacketSinkHelper dlPacketSinkHelper ("ns3::UdpSocketFactory",
342  InetSocketAddress (Ipv4Address::GetAny (), dlPort));
343  ApplicationContainer sinkContainer = dlPacketSinkHelper.Install (ue);
344  bearerData.dlSink = sinkContainer.Get (0)->GetObject<PacketSink> ();
345  serverApps.Add (sinkContainer);
346 
347  }
348  // always true: if (epcUl)
349  {
350  UdpClientHelper ulClientHelper (remoteHostAddr, ulPort);
351  clientApps.Add (ulClientHelper.Install (ue));
352  PacketSinkHelper ulPacketSinkHelper ("ns3::UdpSocketFactory",
353  InetSocketAddress (Ipv4Address::GetAny (), ulPort));
354  ApplicationContainer sinkContainer = ulPacketSinkHelper.Install (remoteHost);
355  bearerData.ulSink = sinkContainer.Get (0)->GetObject<PacketSink> ();
356  serverApps.Add (sinkContainer);
357  }
358 
359  Ptr<EpcTft> tft = Create<EpcTft> ();
360  // always true: if (epcDl)
361  {
363  dlpf.localPortStart = dlPort;
364  dlpf.localPortEnd = dlPort;
365  tft->Add (dlpf);
366  }
367  // always true: if (epcUl)
368  {
370  ulpf.remotePortStart = ulPort;
371  ulpf.remotePortEnd = ulPort;
372  tft->Add (ulpf);
373  }
374 
375  // always true: if (epcDl || epcUl)
376  {
377  EpsBearer bearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT);
378  m_lteHelper->ActivateDedicatedEpsBearer (ueDevices.Get (u), bearer, tft);
379  }
380  Time startTime = Seconds (startTimeSeconds->GetValue ());
381  serverApps.Start (startTime);
382  clientApps.Start (startTime);
383 
384  ueData.bearerDataList.push_back (bearerData);
385 
386  } // end for b
387 
388  m_ueDataVector.push_back (ueData);
389  }
390 
391  }
392  else // (epc == false)
393  {
394  // for radio bearer activation purposes, consider together home UEs and macro UEs
395  for (uint32_t u = 0; u < ueDevices.GetN (); ++u)
396  {
397  Ptr<NetDevice> ueDev = ueDevices.Get (u);
398  for (uint32_t b = 0; b < m_nDedicatedBearers; ++b)
399  {
400  enum EpsBearer::Qci q = EpsBearer::NGBR_VIDEO_TCP_DEFAULT;
401  EpsBearer bearer (q);
402  m_lteHelper->ActivateDataRadioBearer (ueDev, bearer);
403  }
404  }
405  }
406 
407 
408  m_lteHelper->AddX2Interface (enbNodes);
409 
410  // check initial RRC connection
411  const Time maxRrcConnectionEstablishmentDuration = Seconds (0.080);
412  for (NetDeviceContainer::Iterator it = ueDevices.Begin (); it != ueDevices.End (); ++it)
413  {
414  Simulator::Schedule (maxRrcConnectionEstablishmentDuration,
416  this, *it, enbDevices.Get (0));
417  }
418 
419  // schedule handover events and corresponding checks
420 
421  Time stopTime = Seconds (0);
422  for (std::list<HandoverEvent>::iterator hoEventIt = m_handoverEventList.begin ();
423  hoEventIt != m_handoverEventList.end ();
424  ++hoEventIt)
425  {
426  // Teleport the UE between both eNBs just before the handover starts
427  Simulator::Schedule (hoEventIt->startTime - MilliSeconds (10),
429  this,
430  ueNodes.Get (hoEventIt->ueDeviceIndex));
431 
432  Simulator::Schedule (hoEventIt->startTime,
434  this,
435  ueDevices.Get (hoEventIt->ueDeviceIndex),
436  enbDevices.Get (hoEventIt->sourceEnbDeviceIndex));
437 
438  m_lteHelper->HandoverRequest (hoEventIt->startTime,
439  ueDevices.Get (hoEventIt->ueDeviceIndex),
440  enbDevices.Get (hoEventIt->sourceEnbDeviceIndex),
441  enbDevices.Get (hoEventIt->targetEnbDeviceIndex));
442 
443  // Once the handover is finished, teleport the UE near the target eNB
444  Simulator::Schedule (hoEventIt->startTime + MilliSeconds (40),
446  this,
447  ueNodes.Get (hoEventIt->ueDeviceIndex),
448  enbNodes.Get (m_admitHo ? hoEventIt->targetEnbDeviceIndex
449  : hoEventIt->sourceEnbDeviceIndex));
450 
451  Time hoEndTime = hoEventIt->startTime + m_maxHoDuration;
452  Simulator::Schedule (hoEndTime,
454  this,
455  ueDevices.Get (hoEventIt->ueDeviceIndex),
456  enbDevices.Get (m_admitHo ? hoEventIt->targetEnbDeviceIndex : hoEventIt->sourceEnbDeviceIndex));
457  Simulator::Schedule (hoEndTime, &LteX2HandoverTestCase::SaveStatsAfterHandover,
458  this, hoEventIt->ueDeviceIndex);
459 
460  Time checkStatsAfterHoTime = hoEndTime + m_statsDuration;
461  Simulator::Schedule (checkStatsAfterHoTime, &LteX2HandoverTestCase::CheckStatsAWhileAfterHandover,
462  this, hoEventIt->ueDeviceIndex);
463  if (stopTime <= checkStatsAfterHoTime)
464  {
465  stopTime = checkStatsAfterHoTime + MilliSeconds (1);
466  }
467  }
468 
469  // m_lteHelper->EnableRlcTraces ();
470  // m_lteHelper->EnablePdcpTraces();
471 
472 
473  Simulator::Stop (stopTime);
474 
475  Simulator::Run ();
476 
477  Simulator::Destroy ();
478 
479 }
480 
481 void
483 {
484  Ptr<LteUeNetDevice> ueLteDevice = ueDevice->GetObject<LteUeNetDevice> ();
485  Ptr<LteUeRrc> ueRrc = ueLteDevice->GetRrc ();
486  NS_TEST_ASSERT_MSG_EQ (ueRrc->GetState (), LteUeRrc::CONNECTED_NORMALLY, "Wrong LteUeRrc state!");
487 
488 
489  Ptr<LteEnbNetDevice> enbLteDevice = enbDevice->GetObject<LteEnbNetDevice> ();
490  Ptr<LteEnbRrc> enbRrc = enbLteDevice->GetRrc ();
491  uint16_t rnti = ueRrc->GetRnti ();
492  Ptr<UeManager> ueManager = enbRrc->GetUeManager (rnti);
493  NS_TEST_ASSERT_MSG_NE (ueManager, 0, "RNTI " << rnti << " not found in eNB");
494 
495  UeManager::State ueManagerState = ueManager->GetState ();
496  NS_TEST_ASSERT_MSG_EQ (ueManagerState, UeManager::CONNECTED_NORMALLY, "Wrong UeManager state!");
497  NS_ASSERT_MSG (ueManagerState == UeManager::CONNECTED_NORMALLY, "Wrong UeManager state!");
498 
499  uint16_t ueCellId = ueRrc->GetCellId ();
500  uint16_t enbCellId = enbLteDevice->GetCellId ();
501  uint8_t ueDlBandwidth = ueRrc->GetDlBandwidth ();
502  uint8_t enbDlBandwidth = enbLteDevice->GetDlBandwidth ();
503  uint8_t ueUlBandwidth = ueRrc->GetUlBandwidth ();
504  uint8_t enbUlBandwidth = enbLteDevice->GetUlBandwidth ();
505  uint8_t ueDlEarfcn = ueRrc->GetDlEarfcn ();
506  uint8_t enbDlEarfcn = enbLteDevice->GetDlEarfcn ();
507  uint8_t ueUlEarfcn = ueRrc->GetUlEarfcn ();
508  uint8_t enbUlEarfcn = enbLteDevice->GetUlEarfcn ();
509  uint64_t ueImsi = ueLteDevice->GetImsi ();
510  uint64_t enbImsi = ueManager->GetImsi ();
511 
512  NS_TEST_ASSERT_MSG_EQ (ueImsi, enbImsi, "inconsistent IMSI");
513  NS_TEST_ASSERT_MSG_EQ (ueCellId, enbCellId, "inconsistent CellId");
514  NS_TEST_ASSERT_MSG_EQ (ueDlBandwidth, enbDlBandwidth, "inconsistent DlBandwidth");
515  NS_TEST_ASSERT_MSG_EQ (ueUlBandwidth, enbUlBandwidth, "inconsistent UlBandwidth");
516  NS_TEST_ASSERT_MSG_EQ (ueDlEarfcn, enbDlEarfcn, "inconsistent DlEarfcn");
517  NS_TEST_ASSERT_MSG_EQ (ueUlEarfcn, enbUlEarfcn, "inconsistent UlEarfcn");
518 
519  ObjectMapValue enbDataRadioBearerMapValue;
520  ueManager->GetAttribute ("DataRadioBearerMap", enbDataRadioBearerMapValue);
521  NS_TEST_ASSERT_MSG_EQ (enbDataRadioBearerMapValue.GetN (), m_nDedicatedBearers + 1, "wrong num bearers at eNB");
522 
523  ObjectMapValue ueDataRadioBearerMapValue;
524  ueRrc->GetAttribute ("DataRadioBearerMap", ueDataRadioBearerMapValue);
525  NS_TEST_ASSERT_MSG_EQ (ueDataRadioBearerMapValue.GetN (), m_nDedicatedBearers + 1, "wrong num bearers at UE");
526 
527  ObjectMapValue::Iterator enbBearerIt = enbDataRadioBearerMapValue.Begin ();
528  ObjectMapValue::Iterator ueBearerIt = ueDataRadioBearerMapValue.Begin ();
529  while (enbBearerIt != enbDataRadioBearerMapValue.End ()
530  && ueBearerIt != ueDataRadioBearerMapValue.End ())
531  {
532  Ptr<LteDataRadioBearerInfo> enbDrbInfo = enbBearerIt->second->GetObject<LteDataRadioBearerInfo> ();
533  Ptr<LteDataRadioBearerInfo> ueDrbInfo = ueBearerIt->second->GetObject<LteDataRadioBearerInfo> ();
534  //NS_TEST_ASSERT_MSG_EQ (enbDrbInfo->m_epsBearer, ueDrbInfo->m_epsBearer, "epsBearer differs");
535  NS_TEST_ASSERT_MSG_EQ ((uint32_t) enbDrbInfo->m_epsBearerIdentity, (uint32_t) ueDrbInfo->m_epsBearerIdentity, "epsBearerIdentity differs");
536  NS_TEST_ASSERT_MSG_EQ ((uint32_t) enbDrbInfo->m_drbIdentity, (uint32_t) ueDrbInfo->m_drbIdentity, "drbIdentity differs");
537  //NS_TEST_ASSERT_MSG_EQ (enbDrbInfo->m_rlcConfig, ueDrbInfo->m_rlcConfig, "rlcConfig differs");
538  NS_TEST_ASSERT_MSG_EQ ((uint32_t) enbDrbInfo->m_logicalChannelIdentity, (uint32_t) ueDrbInfo->m_logicalChannelIdentity, "logicalChannelIdentity differs");
539  //NS_TEST_ASSERT_MSG_EQ (enbDrbInfo->m_logicalChannelConfig, ueDrbInfo->m_logicalChannelConfig, "logicalChannelConfig differs");
540 
541  ++enbBearerIt;
542  ++ueBearerIt;
543  }
544  NS_ASSERT_MSG (enbBearerIt == enbDataRadioBearerMapValue.End (), "too many bearers at eNB");
545  NS_ASSERT_MSG (ueBearerIt == ueDataRadioBearerMapValue.End (), "too many bearers at UE");
546 }
547 
548 void
550 {
551  Ptr<MobilityModel> ueMobility = ueNode->GetObject<MobilityModel> ();
552  ueMobility->SetPosition (Vector (0.0, 0.0, 0.0));
553 }
554 
555 void
557 {
558  Ptr<MobilityModel> enbMobility = enbNode->GetObject<MobilityModel> ();
559  Vector pos = enbMobility->GetPosition ();
560 
561  Ptr<MobilityModel> ueMobility = ueNode->GetObject<MobilityModel> ();
562  ueMobility->SetPosition (pos + Vector (0.0, 100.0, 0.0));
563 }
564 
565 void
567 {
568  for (std::list<BearerData>::iterator it = m_ueDataVector.at (ueIndex).bearerDataList.begin ();
569  it != m_ueDataVector.at (ueIndex).bearerDataList.end ();
570  ++it)
571  {
572  it->dlOldTotalRx = it->dlSink->GetTotalRx ();
573  it->ulOldTotalRx = it->ulSink->GetTotalRx ();
574  }
575 }
576 
577 void
579 {
580  uint32_t b = 1;
581  for (std::list<BearerData>::iterator it = m_ueDataVector.at (ueIndex).bearerDataList.begin ();
582  it != m_ueDataVector.at (ueIndex).bearerDataList.end ();
583  ++it)
584  {
585  uint32_t dlRx = it->dlSink->GetTotalRx () - it->dlOldTotalRx;
586  uint32_t ulRx = it->ulSink->GetTotalRx () - it->ulOldTotalRx;
587  uint32_t expectedBytes = m_udpClientPktSize * (m_statsDuration / m_udpClientInterval).GetDouble ();
588 
589  NS_TEST_ASSERT_MSG_EQ (dlRx, expectedBytes, "too few RX bytes in DL, ue=" << ueIndex << ", b=" << b);
590  NS_TEST_ASSERT_MSG_EQ (ulRx, expectedBytes, "too few RX bytes in UL, ue=" << ueIndex << ", b=" << b);
591  ++b;
592  }
593 }
594 
595 
612 {
613 public:
615 };
616 
617 
619  : TestSuite ("lte-x2-handover", SYSTEM)
620 {
621  // in the following:
622  // fwd means handover from enb 0 to enb 1
623  // bwd means handover from enb 1 to enb 0
624 
625  HandoverEvent ue1fwd;
626  ue1fwd.startTime = MilliSeconds (100);
627  ue1fwd.ueDeviceIndex = 0;
628  ue1fwd.sourceEnbDeviceIndex = 0;
629  ue1fwd.targetEnbDeviceIndex = 1;
630 
631  HandoverEvent ue1bwd;
632  ue1bwd.startTime = MilliSeconds (400);
633  ue1bwd.ueDeviceIndex = 0;
634  ue1bwd.sourceEnbDeviceIndex = 1;
635  ue1bwd.targetEnbDeviceIndex = 0;
636 
637  HandoverEvent ue1fwdagain;
638  ue1fwdagain.startTime = MilliSeconds (700);
639  ue1fwdagain.ueDeviceIndex = 0;
640  ue1fwdagain.sourceEnbDeviceIndex = 0;
641  ue1fwdagain.targetEnbDeviceIndex = 1;
642 
643  HandoverEvent ue2fwd;
644  ue2fwd.startTime = MilliSeconds (110);
645  ue2fwd.ueDeviceIndex = 1;
646  ue2fwd.sourceEnbDeviceIndex = 0;
647  ue2fwd.targetEnbDeviceIndex = 1;
648 
649  HandoverEvent ue2bwd;
650  ue2bwd.startTime = MilliSeconds (350);
651  ue2bwd.ueDeviceIndex = 1;
652  ue2bwd.sourceEnbDeviceIndex = 1;
653  ue2bwd.targetEnbDeviceIndex = 0;
654 
655  std::string hel0name ("none");
656  std::list<HandoverEvent> hel0;
657 
658  std::string hel1name ("1 fwd");
659  std::list<HandoverEvent> hel1;
660  hel1.push_back (ue1fwd);
661 
662  std::string hel2name ("1 fwd & bwd");
663  std::list<HandoverEvent> hel2;
664  hel2.push_back (ue1fwd);
665  hel2.push_back (ue1bwd);
666 
667  std::string hel3name ("1 fwd & bwd & fwd");
668  std::list<HandoverEvent> hel3;
669  hel3.push_back (ue1fwd);
670  hel3.push_back (ue1bwd);
671  hel3.push_back (ue1fwdagain);
672 
673  std::string hel4name ("1+2 fwd");
674  std::list<HandoverEvent> hel4;
675  hel4.push_back (ue1fwd);
676  hel4.push_back (ue2fwd);
677 
678  std::string hel5name ("1+2 fwd & bwd");
679  std::list<HandoverEvent> hel5;
680  hel5.push_back (ue1fwd);
681  hel5.push_back (ue1bwd);
682  hel5.push_back (ue2fwd);
683  hel5.push_back (ue2bwd);
684 
685  std::string hel6name ("2 fwd");
686  std::list<HandoverEvent> hel6;
687  hel6.push_back (ue2fwd);
688 
689  std::string hel7name ("2 fwd & bwd");
690  std::list<HandoverEvent> hel7;
691  hel7.push_back (ue2fwd);
692  hel7.push_back (ue2bwd);
693 
694  std::vector<std::string> schedulers;
695  schedulers.push_back ("ns3::RrFfMacScheduler");
696  schedulers.push_back ("ns3::PfFfMacScheduler");
697  for (std::vector<std::string>::iterator schedIt = schedulers.begin (); schedIt != schedulers.end (); ++schedIt)
698  {
699  for (int32_t useIdealRrc = 1; useIdealRrc >= 0; --useIdealRrc)
700  {
701  // nUes, nDBearers, helist, name, sched, admitHo, idealRrc
702  AddTestCase (new LteX2HandoverTestCase ( 1, 0, hel0, hel0name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
703  AddTestCase (new LteX2HandoverTestCase ( 2, 0, hel0, hel0name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
704  AddTestCase (new LteX2HandoverTestCase ( 1, 5, hel0, hel0name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
705  AddTestCase (new LteX2HandoverTestCase ( 2, 5, hel0, hel0name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
706  AddTestCase (new LteX2HandoverTestCase ( 1, 0, hel1, hel1name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
707  AddTestCase (new LteX2HandoverTestCase ( 1, 1, hel1, hel1name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
708  AddTestCase (new LteX2HandoverTestCase ( 1, 2, hel1, hel1name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
709  AddTestCase (new LteX2HandoverTestCase ( 1, 0, hel1, hel1name, *schedIt, false, useIdealRrc), TestCase::EXTENSIVE);
710  AddTestCase (new LteX2HandoverTestCase ( 1, 1, hel1, hel1name, *schedIt, false, useIdealRrc), TestCase::EXTENSIVE);
711  AddTestCase (new LteX2HandoverTestCase ( 1, 2, hel1, hel1name, *schedIt, false, useIdealRrc), TestCase::EXTENSIVE);
712  AddTestCase (new LteX2HandoverTestCase ( 2, 0, hel1, hel1name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
713  AddTestCase (new LteX2HandoverTestCase ( 2, 1, hel1, hel1name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
714  AddTestCase (new LteX2HandoverTestCase ( 2, 2, hel1, hel1name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
715  AddTestCase (new LteX2HandoverTestCase ( 2, 0, hel1, hel1name, *schedIt, false, useIdealRrc), TestCase::EXTENSIVE);
716  AddTestCase (new LteX2HandoverTestCase ( 2, 1, hel1, hel1name, *schedIt, false, useIdealRrc), TestCase::EXTENSIVE);
717  AddTestCase (new LteX2HandoverTestCase ( 2, 2, hel1, hel1name, *schedIt, false, useIdealRrc), TestCase::EXTENSIVE);
718  AddTestCase (new LteX2HandoverTestCase ( 1, 0, hel2, hel2name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
719  AddTestCase (new LteX2HandoverTestCase ( 1, 1, hel2, hel2name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
720  AddTestCase (new LteX2HandoverTestCase ( 1, 2, hel2, hel2name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
721  AddTestCase (new LteX2HandoverTestCase ( 1, 0, hel3, hel3name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
722  AddTestCase (new LteX2HandoverTestCase ( 1, 1, hel3, hel3name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
723  AddTestCase (new LteX2HandoverTestCase ( 1, 2, hel3, hel3name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
724  AddTestCase (new LteX2HandoverTestCase ( 2, 0, hel3, hel3name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
725  AddTestCase (new LteX2HandoverTestCase ( 2, 1, hel3, hel3name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
726  AddTestCase (new LteX2HandoverTestCase ( 2, 2, hel3, hel3name, *schedIt, true, useIdealRrc), TestCase::QUICK);
727  AddTestCase (new LteX2HandoverTestCase ( 2, 0, hel4, hel4name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
728  AddTestCase (new LteX2HandoverTestCase ( 2, 1, hel4, hel4name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
729  AddTestCase (new LteX2HandoverTestCase ( 2, 2, hel4, hel4name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
730  AddTestCase (new LteX2HandoverTestCase ( 2, 0, hel5, hel5name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
731  AddTestCase (new LteX2HandoverTestCase ( 2, 1, hel5, hel5name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
732  AddTestCase (new LteX2HandoverTestCase ( 2, 2, hel5, hel5name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
733  AddTestCase (new LteX2HandoverTestCase ( 3, 0, hel3, hel3name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
734  AddTestCase (new LteX2HandoverTestCase ( 3, 1, hel3, hel3name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
735  AddTestCase (new LteX2HandoverTestCase ( 3, 2, hel3, hel3name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
736  AddTestCase (new LteX2HandoverTestCase ( 3, 0, hel4, hel4name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
737  AddTestCase (new LteX2HandoverTestCase ( 3, 1, hel4, hel4name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
738  AddTestCase (new LteX2HandoverTestCase ( 3, 2, hel4, hel4name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
739  AddTestCase (new LteX2HandoverTestCase ( 3, 0, hel5, hel5name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
740  AddTestCase (new LteX2HandoverTestCase ( 3, 1, hel5, hel5name, *schedIt, true, useIdealRrc), TestCase::EXTENSIVE);
741  AddTestCase (new LteX2HandoverTestCase ( 3, 2, hel5, hel5name, *schedIt, true, useIdealRrc), TestCase::QUICK);
742 
743  }
744  }
745 }
746 
static std::string BuildNameString(uint32_t nUes, uint32_t nDedicatedBearers, std::string handoverEventListName, std::string schedulerType, bool admitHo, bool useIdealRrc)
Build name string.
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.
virtual void DoRun(void)
Implementation to actually run this TestCase.
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
Class for representing data rates.
Definition: data-rate.h:89
AttributeValue implementation for DataRate.
Definition: data-rate.h:298
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:41
This class contains the specification of EPS Bearers.
Definition: eps-bearer.h:92
Qci
QoS Class Indicator.
Definition: eps-bearer.h:107
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:41
Access to the IPv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:77
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:256
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:272
void HandoverRequest(Time hoTime, Ptr< NetDevice > ueDev, Ptr< NetDevice > sourceEnbDev, Ptr< NetDevice > targetEnbDev)
Manually trigger an X2-based handover.
Definition: lte-helper.cc:1245
NetDeviceContainer InstallEnbDevice(NodeContainer c)
Create a set of eNodeB devices.
Definition: lte-helper.cc:474
void SetHandoverAlgorithmType(std::string type)
Set the type of handover algorithm to be used by eNodeB devices.
Definition: lte-helper.cc:327
void SetSchedulerType(std::string type)
Set the type of scheduler to be used by eNodeB devices.
Definition: lte-helper.cc:279
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:959
void ActivateDataRadioBearer(NetDeviceContainer ueDevices, EpsBearer bearer)
Activate a Data Radio Bearer on a given UE devices (for LTE-only simulation).
Definition: lte-helper.cc:1313
NetDeviceContainer InstallUeDevice(NodeContainer c)
Create a set of UE devices.
Definition: lte-helper.cc:489
void AddX2Interface(NodeContainer enbNodes)
Create an X2 interface between all the eNBs in a given set.
Definition: lte-helper.cc:1220
int64_t AssignStreams(NetDeviceContainer c, int64_t stream)
Assign a fixed random variable stream number to the random variables used.
Definition: lte-helper.cc:1443
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:1068
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.
void SetPosition(const Vector &position)
Vector GetPosition(void) const
holds a vector of ns3::NetDevice pointers
Iterator End(void) const
Get an iterator which indicates past-the-last NetDevice in the container.
uint32_t GetN(void) const
Get the number of Ptr<NetDevice> stored in this container.
std::vector< Ptr< NetDevice > >::const_iterator Iterator
NetDevice container iterator.
Iterator Begin(void) const
Get an iterator which refers to the first NetDevice in the container.
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
virtual Ipv4Address GetUeDefaultGatewayAddress()
virtual Ptr< Node > GetPgwNode() const
Get the PGW node.
virtual Ipv4InterfaceContainer AssignUeIpv4Address(NetDeviceContainer ueDevices)
Assign IPv4 addresses to UE devices.
keep track of a set of node pointers.
uint32_t GetN(void) 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:256
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
Container for a set of ns3::Object pointers.
std::size_t GetN(void) const
Get the number of Objects.
Iterator Begin(void) const
Get an iterator to the first Object.
std::map< std::size_t, Ptr< Object > >::const_iterator Iterator
Iterator type for traversing this container.
Iterator End(void) const
Get an iterator to the past-the-end 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:72
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)
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
Hold variables of type string.
Definition: string.h:41
encapsulates test code
Definition: test.h:994
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
A suite of tests to run.
Definition: test.h:1188
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
AttributeValue implementation for Time.
Definition: nstime.h:1308
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:87
Hold an unsigned integer type.
Definition: uinteger.h:44
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:88
void Reset(void)
Reset the initial value of every attribute as well as the value of every global to what they were bef...
Definition: config.cc:820
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:849
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#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:141
#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:542
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1252
serverApps
Definition: first.py:52
clientApps
Definition: first.py:61
Every class exported by the ns3 library is enclosed in the ns3 namespace.
mobility
Definition: third.py:108
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:75
uint16_t localPortEnd
end of the port number range of the UE
Definition: epc-tft.h:140
uint16_t remotePortEnd
end of the port number range of the remote host
Definition: epc-tft.h:138
uint16_t remotePortStart
start of the port number range of the remote host
Definition: epc-tft.h:137
uint16_t localPortStart
start of the port number range of the UE
Definition: epc-tft.h:139
double startTime
static LteX2HandoverTestSuite g_lteX2HandoverTestSuiteInstance