A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
lte-helper.cc
Go to the documentation of this file.
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2011 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> (re-wrote from scratch this helper)
19  * Giuseppe Piro <g.piro@poliba.it> (parts of the PHY & channel creation & configuration copied from the GSoC 2011 code)
20  */
21 
22 
23 #include "lte-helper.h"
24 #include <ns3/string.h>
25 #include <ns3/log.h>
26 #include <ns3/abort.h>
27 #include <ns3/pointer.h>
28 #include <ns3/lte-enb-rrc.h>
29 #include <ns3/lte-ue-rrc.h>
30 #include <ns3/lte-ue-mac.h>
31 #include <ns3/lte-enb-mac.h>
32 #include <ns3/lte-enb-net-device.h>
33 #include <ns3/lte-enb-phy.h>
34 #include <ns3/lte-ue-phy.h>
35 #include <ns3/lte-spectrum-phy.h>
36 #include <ns3/lte-sinr-chunk-processor.h>
37 #include <ns3/single-model-spectrum-channel.h>
38 #include <ns3/friis-spectrum-propagation-loss.h>
39 #include <ns3/isotropic-antenna-model.h>
40 #include <ns3/lte-enb-net-device.h>
41 #include <ns3/lte-ue-net-device.h>
42 #include <ns3/ff-mac-scheduler.h>
43 #include <ns3/lte-rlc.h>
44 #include <ns3/lte-rlc-um.h>
45 #include <ns3/lte-rlc-am.h>
46 
47 #include <ns3/epc-helper.h>
48 #include <iostream>
49 #include <ns3/buildings-propagation-loss-model.h>
50 #include <ns3/lte-spectrum-value-helper.h>
51 
52 
53 NS_LOG_COMPONENT_DEFINE ("LteHelper");
54 
55 namespace ns3 {
56 
57 NS_OBJECT_ENSURE_REGISTERED (LteHelper);
58 
60 {
61  NS_LOG_FUNCTION (this);
66 }
67 
68 void
70 {
71  NS_LOG_FUNCTION (this);
74 
76  Ptr<SpectrumPropagationLossModel> dlSplm = m_downlinkPathlossModel->GetObject<SpectrumPropagationLossModel> ();
77  if (dlSplm != 0)
78  {
79  NS_LOG_LOGIC (this << " using a SpectrumPropagationLossModel in DL");
81  }
82  else
83  {
84  NS_LOG_LOGIC (this << " using a PropagationLossModel in DL");
85  Ptr<PropagationLossModel> dlPlm = m_downlinkPathlossModel->GetObject<PropagationLossModel> ();
86  NS_ASSERT_MSG (dlPlm != 0, " " << m_downlinkPathlossModel << " is neither PropagationLossModel nor SpectrumPropagationLossModel");
88  }
89 
92  if (ulSplm != 0)
93  {
94  NS_LOG_LOGIC (this << " using a SpectrumPropagationLossModel in UL");
95  m_uplinkChannel->AddSpectrumPropagationLossModel (ulSplm);
96  }
97  else
98  {
99  NS_LOG_LOGIC (this << " using a PropagationLossModel in UL");
101  NS_ASSERT_MSG (ulPlm != 0, " " << m_uplinkPathlossModel << " is neither PropagationLossModel nor SpectrumPropagationLossModel");
102  m_uplinkChannel->AddPropagationLossModel (ulPlm);
103  }
104  if (!m_fadingModelType.empty ())
105  {
106  Ptr<SpectrumPropagationLossModel> m_fadingModule;
108  m_fadingModule->Start ();
110  m_uplinkChannel->AddSpectrumPropagationLossModel (m_fadingModule);
111  }
112  m_macStats = CreateObject<MacStatsCalculator> ();
113  m_rlcStats = CreateObject<RadioBearerStatsCalculator> ("RLC");
114  m_pdcpStats = CreateObject<RadioBearerStatsCalculator> ("PDCP");
115 
116  Object::DoStart ();
117 
118 }
119 
121 {
122  NS_LOG_FUNCTION (this);
123 }
124 
126 {
127  static TypeId
128  tid =
129  TypeId ("ns3::LteHelper")
130  .SetParent<Object> ()
131  .AddConstructor<LteHelper> ()
132  .AddAttribute ("Scheduler",
133  "The type of scheduler to be used for eNBs",
134  StringValue ("ns3::PfFfMacScheduler"),
135  MakeStringAccessor (&LteHelper::SetSchedulerType),
136  MakeStringChecker ())
137  .AddAttribute ("PathlossModel",
138  "The type of pathloss model to be used",
139  StringValue ("ns3::FriisPropagationLossModel"),
140  MakeStringAccessor (&LteHelper::SetPathlossModelType),
141  MakeStringChecker ())
142  .AddAttribute ("FadingModel",
143  "The type of fading model to be used",
144  StringValue (""), // fake module -> no fading
145  MakeStringAccessor (&LteHelper::SetFadingModel),
146  MakeStringChecker ())
147  .AddAttribute ("EpsBearerToRlcMapping",
148  "Specify which type of RLC will be used for each type of EPS bearer. ",
151  MakeEnumChecker (RLC_SM_ALWAYS, "RlcSmAlways",
152  RLC_UM_ALWAYS, "RlcUmAlways",
153  RLC_AM_ALWAYS, "RlcAmAlways",
154  PER_BASED, "PacketErrorRateBased"))
155  ;
156  return tid;
157 }
158 
159 void
161 {
162  NS_LOG_FUNCTION (this);
163  m_downlinkChannel = 0;
164  m_uplinkChannel = 0;
166 }
167 
168 
169 void
171 {
172  NS_LOG_FUNCTION (this << h);
173  m_epcHelper = h;
174  // it does not make sense to use RLC/SM when also using the EPC
176  {
178  }
179 }
180 
181 void
182 LteHelper::SetSchedulerType (std::string type)
183 {
184  NS_LOG_FUNCTION (this << type);
187 }
188 
189 void
191 {
192  NS_LOG_FUNCTION (this << n);
193  m_schedulerFactory.Set (n, v);
194 }
195 
196 
197 void
199 {
200  NS_LOG_FUNCTION (this << type);
205 }
206 
207 void
209 {
210  NS_LOG_FUNCTION (this << n);
213 }
214 
215 void
217 {
218  NS_LOG_FUNCTION (this);
219  m_enbNetDeviceFactory.Set (n, v);
220 }
221 
222 
223 void
225 {
226  NS_LOG_FUNCTION (this);
228 }
229 
230 void
232 {
233  NS_LOG_FUNCTION (this);
235 }
236 
237 void
239 {
240  NS_LOG_FUNCTION (this);
242 }
243 
244 void
246 {
247  NS_LOG_FUNCTION (this);
249 }
250 
251 void
252 LteHelper::SetFadingModel (std::string type)
253 {
254  NS_LOG_FUNCTION (this << type);
255  m_fadingModelType = type;
256  if (!type.empty ())
257  {
260  }
261 }
262 
263 void
265 {
266  m_fadingModelFactory.Set (n, v);
267 }
268 
269 void
271 {
272  NS_LOG_FUNCTION (this << type);
274 }
275 
276 void
278 {
279  m_channelFactory.Set (n, v);
280 }
281 
282 
285 {
286  NS_LOG_FUNCTION (this);
287  Start (); // will run DoStart () if necessary
288  NetDeviceContainer devices;
289  for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
290  {
291  Ptr<Node> node = *i;
292  Ptr<NetDevice> device = InstallSingleEnbDevice (node);
293  devices.Add (device);
294  }
295  return devices;
296 }
297 
300 {
301  NS_LOG_FUNCTION (this);
302  NetDeviceContainer devices;
303  for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
304  {
305  Ptr<Node> node = *i;
306  Ptr<NetDevice> device = InstallSingleUeDevice (node);
307  devices.Add (device);
308  }
309  return devices;
310 }
311 
312 
315 {
316  Ptr<LteSpectrumPhy> dlPhy = CreateObject<LteSpectrumPhy> ();
317  Ptr<LteSpectrumPhy> ulPhy = CreateObject<LteSpectrumPhy> ();
318 
319  Ptr<LteEnbPhy> phy = CreateObject<LteEnbPhy> (dlPhy, ulPhy);
320 
321  Ptr<LteCqiSinrChunkProcessor> p = Create<LteCqiSinrChunkProcessor> (phy->GetObject<LtePhy> ());
322  ulPhy->AddSinrChunkProcessor (p);
323 
324  Ptr<LtePemSinrChunkProcessor> pPem = Create<LtePemSinrChunkProcessor> (ulPhy);
325  ulPhy->AddSinrChunkProcessor (pPem);
326 
327  dlPhy->SetChannel (m_downlinkChannel);
328  ulPhy->SetChannel (m_uplinkChannel);
329 
331  NS_ASSERT_MSG (mm, "MobilityModel needs to be set on node before calling LteHelper::InstallUeDevice ()");
332  dlPhy->SetMobility (mm);
333  ulPhy->SetMobility (mm);
334 
335  Ptr<AntennaModel> antenna = (m_enbAntennaModelFactory.Create ())->GetObject<AntennaModel> ();
336  NS_ASSERT_MSG (antenna, "error in creating the AntennaModel object");
337  dlPhy->SetAntenna (antenna);
338  ulPhy->SetAntenna (antenna);
339 
340  Ptr<LteEnbMac> mac = CreateObject<LteEnbMac> ();
342  Ptr<LteEnbRrc> rrc = CreateObject<LteEnbRrc> ();
343 
344 
345  // connect SAPs
347  mac->SetLteEnbCmacSapUser (rrc->GetLteEnbCmacSapUser ());
348  rrc->SetLteMacSapProvider (mac->GetLteMacSapProvider ());
349 
350  mac->SetFfMacSchedSapProvider (sched->GetFfMacSchedSapProvider ());
351  mac->SetFfMacCschedSapProvider (sched->GetFfMacCschedSapProvider ());
352 
353  sched->SetFfMacSchedSapUser (mac->GetFfMacSchedSapUser ());
354  sched->SetFfMacCschedSapUser (mac->GetFfMacCschedSapUser ());
355 
356  phy->SetLteEnbPhySapUser (mac->GetLteEnbPhySapUser ());
357  mac->SetLteEnbPhySapProvider (phy->GetLteEnbPhySapProvider ());
358 
360  dev->SetNode (n);
361  dev->SetAttribute ("LteEnbPhy", PointerValue (phy));
362  dev->SetAttribute ("LteEnbMac", PointerValue (mac));
363  dev->SetAttribute ("FfMacScheduler", PointerValue (sched));
364  dev->SetAttribute ("LteEnbRrc", PointerValue (rrc));
365 
366  phy->SetDevice (dev);
367  dlPhy->SetDevice (dev);
368  ulPhy->SetDevice (dev);
369 
370  n->AddDevice (dev);
371  ulPhy->SetGenericPhyRxEndOkCallback (MakeCallback (&LteEnbPhy::PhyPduReceived, phy));
372  rrc->SetForwardUpCallback (MakeCallback (&LteEnbNetDevice::Receive, dev));
373 
374  NS_LOG_LOGIC ("set the propagation model frequencies");
376  NS_LOG_LOGIC ("DL freq: " << dlFreq);
377  bool dlFreqOk = m_downlinkPathlossModel->SetAttributeFailSafe ("Frequency", DoubleValue (dlFreq));
378  if (!dlFreqOk)
379  {
380  NS_LOG_WARN ("DL propagation model does not have a Frequency attribute");
381  }
383  NS_LOG_LOGIC ("UL freq: " << ulFreq);
384  bool ulFreqOk = m_uplinkPathlossModel->SetAttributeFailSafe ("Frequency", DoubleValue (ulFreq));
385  if (!ulFreqOk)
386  {
387  NS_LOG_WARN ("UL propagation model does not have a Frequency attribute");
388  }
389 
390 
391  dev->Start ();
392 
393  m_uplinkChannel->AddRx (ulPhy);
394 
395  if (m_epcHelper != 0)
396  {
397  NS_LOG_INFO ("adding this eNB to the EPC");
398  m_epcHelper->AddEnb (n, dev);
399  }
400 
401  return dev;
402 }
403 
406 {
407  NS_LOG_FUNCTION (this);
408  Ptr<LteSpectrumPhy> dlPhy = CreateObject<LteSpectrumPhy> ();
409  Ptr<LteSpectrumPhy> ulPhy = CreateObject<LteSpectrumPhy> ();
410 
411  Ptr<LteUePhy> phy = CreateObject<LteUePhy> (dlPhy, ulPhy);
412 
413  Ptr<LteCqiSinrChunkProcessor> p = Create<LteCqiSinrChunkProcessor> (phy->GetObject<LtePhy> ());
414  dlPhy->AddSinrChunkProcessor (p);
415 
416  Ptr<LtePemSinrChunkProcessor> pPem = Create<LtePemSinrChunkProcessor> (dlPhy);
417  dlPhy->AddSinrChunkProcessor (pPem);
418 
419  dlPhy->SetChannel (m_downlinkChannel);
420  ulPhy->SetChannel (m_uplinkChannel);
421 
423  NS_ASSERT_MSG (mm, "MobilityModel needs to be set on node before calling LteHelper::InstallUeDevice ()");
424  dlPhy->SetMobility (mm);
425  ulPhy->SetMobility (mm);
426 
427 
428  Ptr<AntennaModel> antenna = (m_ueAntennaModelFactory.Create ())->GetObject<AntennaModel> ();
429  NS_ASSERT_MSG (antenna, "error in creating the AntennaModel object");
430  dlPhy->SetAntenna (antenna);
431  ulPhy->SetAntenna (antenna);
432 
433  Ptr<LteUeMac> mac = CreateObject<LteUeMac> ();
434  Ptr<LteUeRrc> rrc = CreateObject<LteUeRrc> ();
435 
436  // connect SAPs
438  mac->SetLteUeCmacSapUser (rrc->GetLteUeCmacSapUser ());
439  rrc->SetLteMacSapProvider (mac->GetLteMacSapProvider ());
440 
441  phy->SetLteUePhySapUser (mac->GetLteUePhySapUser ());
442  mac->SetLteUePhySapProvider (phy->GetLteUePhySapProvider ());
443 
444  Ptr<LteUeNetDevice> dev = CreateObject<LteUeNetDevice> (n, phy, mac, rrc);
445  phy->SetDevice (dev);
446  dlPhy->SetDevice (dev);
447  ulPhy->SetDevice (dev);
448 
449  n->AddDevice (dev);
450  dlPhy->SetGenericPhyRxEndOkCallback (MakeCallback (&LteUePhy::PhyPduReceived, phy));
451  rrc->SetForwardUpCallback (MakeCallback (&LteUeNetDevice::Receive, dev));
452 
453  return dev;
454 }
455 
456 
457 void
459 {
460  NS_LOG_FUNCTION (this);
461  for (NetDeviceContainer::Iterator i = ueDevices.Begin (); i != ueDevices.End (); ++i)
462  {
463  Attach (*i, enbDevice);
464  }
465 }
466 
467 void
469 {
470  NS_LOG_FUNCTION (this);
471  // setup RRC connection
472  Ptr<LteEnbRrc> enbRrc = enbDevice->GetObject<LteEnbNetDevice> ()->GetRrc ();
473  uint16_t rnti = enbRrc->AddUe (ueDevice->GetObject<LteUeNetDevice> ()->GetImsi ());
474  Ptr<LteUeRrc> ueRrc = ueDevice->GetObject<LteUeNetDevice> ()->GetRrc ();
475  ueRrc->ConfigureUe (rnti, enbDevice->GetObject<LteEnbNetDevice> ()->GetCellId () );
476 
477  // attach UE to eNB
478  ueDevice->GetObject<LteUeNetDevice> ()->SetTargetEnb (enbDevice->GetObject<LteEnbNetDevice> ());
479 
480 
481  // connect at the PHY layer
482  Ptr<LteEnbPhy> enbPhy = enbDevice->GetObject<LteEnbNetDevice> ()->GetPhy ();
483  Ptr<LteUePhy> uePhy = ueDevice->GetObject<LteUeNetDevice> ()->GetPhy ();
484  enbPhy->AddUePhy (rnti, uePhy);
485 
486 //
487  // WILD HACK - should be done through PHY SAP, probably passing by RRC
488  uePhy->SetRnti (rnti);
489  uePhy->DoSetBandwidth (enbDevice->GetObject<LteEnbNetDevice> ()->GetUlBandwidth (),
490  enbDevice->GetObject<LteEnbNetDevice> ()->GetDlBandwidth ());
491  uePhy->DoSetEarfcn (enbDevice->GetObject<LteEnbNetDevice> ()->GetDlEarfcn (),
492  enbDevice->GetObject<LteEnbNetDevice> ()->GetUlEarfcn ());
493 
494  ueDevice->Start ();
495 
497 }
498 
499 void
501 {
502  NS_LOG_FUNCTION (this);
503  for (NetDeviceContainer::Iterator i = ueDevices.Begin (); i != ueDevices.End (); ++i)
504  {
505  AttachToClosestEnb (*i, enbDevices);
506  }
507 }
508 
509 void
511 {
512  NS_LOG_FUNCTION (this);
513  NS_ASSERT_MSG (enbDevices.GetN () > 0, "empty enb device container");
514  Vector uepos = ueDevice->GetNode ()->GetObject<MobilityModel> ()->GetPosition ();
515  double minDistance = std::numeric_limits<double>::infinity ();
516  Ptr<NetDevice> closestEnbDevice;
517  for (NetDeviceContainer::Iterator i = enbDevices.Begin (); i != enbDevices.End (); ++i)
518  {
519  Vector enbpos = (*i)->GetNode ()->GetObject<MobilityModel> ()->GetPosition ();
520  double distance = CalculateDistance (uepos, enbpos);
521  if (distance < minDistance)
522  {
523  minDistance = distance;
524  closestEnbDevice = *i;
525  }
526  }
527  NS_ASSERT (closestEnbDevice != 0);
528  Attach (ueDevice, closestEnbDevice);
529 }
530 
531 void
533 {
534  NS_LOG_FUNCTION (this);
535  for (NetDeviceContainer::Iterator i = ueDevices.Begin (); i != ueDevices.End (); ++i)
536  {
537  ActivateEpsBearer (*i, bearer, tft);
538  }
539 }
540 
541 
542 void
544 {
545  NS_LOG_FUNCTION (this);
546  NS_LOG_INFO (" setting up Radio Bearer");
547  Ptr<LteEnbNetDevice> enbDevice = ueDevice->GetObject<LteUeNetDevice> ()->GetTargetEnb ();
548  Ptr<LteEnbRrc> enbRrc = enbDevice->GetObject<LteEnbNetDevice> ()->GetRrc ();
549  Ptr<LteUeRrc> ueRrc = ueDevice->GetObject<LteUeNetDevice> ()->GetRrc ();
550  uint16_t rnti = ueRrc->GetRnti ();
551  TypeId rlcTypeId = GetRlcType (bearer);
552  uint8_t lcid = enbRrc->SetupRadioBearer (rnti, bearer, rlcTypeId);
553  ueRrc->SetupRadioBearer (rnti, bearer, rlcTypeId, lcid, tft);
554 
555  if (m_epcHelper != 0)
556  {
557  NS_LOG_INFO (" setting up S1 Bearer");
558  m_epcHelper->ActivateEpsBearer (ueDevice, enbDevice, tft, rnti, lcid);
559 
560  }
561 }
562 
563 TypeId
565 {
566  switch (m_epsBearerToRlcMapping)
567  {
568  case RLC_SM_ALWAYS:
569  return LteRlcSm::GetTypeId ();
570  break;
571 
572  case RLC_UM_ALWAYS:
573  return LteRlcUm::GetTypeId ();
574  break;
575 
576  case RLC_AM_ALWAYS:
577  return LteRlcAm::GetTypeId ();
578  break;
579 
580  case PER_BASED:
581  if (bearer.GetPacketErrorLossRate () > 1.0e-5)
582  {
583  return LteRlcUm::GetTypeId ();
584  }
585  else
586  {
587  return LteRlcAm::GetTypeId ();
588  }
589  break;
590 
591  default:
592  return LteRlcSm::GetTypeId ();
593  break;
594  }
595 }
596 
597 void
599 {
600  LogComponentEnable ("LteHelper", LOG_LEVEL_ALL);
601  LogComponentEnable ("LteEnbRrc", LOG_LEVEL_ALL);
602  LogComponentEnable ("LteUeRrc", LOG_LEVEL_ALL);
603  LogComponentEnable ("LteEnbMac", LOG_LEVEL_ALL);
604  LogComponentEnable ("LteUeMac", LOG_LEVEL_ALL);
605  LogComponentEnable ("LteRlc", LOG_LEVEL_ALL);
606  LogComponentEnable ("LteRlcUm", LOG_LEVEL_ALL);
607  LogComponentEnable ("LteRlcAm", LOG_LEVEL_ALL);
608  LogComponentEnable ("RrFfMacScheduler", LOG_LEVEL_ALL);
609  LogComponentEnable ("PfFfMacScheduler", LOG_LEVEL_ALL);
610 
611  LogComponentEnable ("LtePhy", LOG_LEVEL_ALL);
612  LogComponentEnable ("LteEnbPhy", LOG_LEVEL_ALL);
613  LogComponentEnable ("LteUePhy", LOG_LEVEL_ALL);
614  LogComponentEnable ("LteSpectrumValueHelper", LOG_LEVEL_ALL);
615  LogComponentEnable ("LteSpectrumPhy", LOG_LEVEL_ALL);
616  LogComponentEnable ("LteInterference", LOG_LEVEL_ALL);
617  LogComponentEnable ("LteSinrChunkProcessor", LOG_LEVEL_ALL);
618 
619  std::string propModelStr = m_dlPathlossModelFactory.GetTypeId ().GetName ().erase (0,5).c_str ();
620  LogComponentEnable ("LteNetDevice", LOG_LEVEL_ALL);
621  LogComponentEnable ("LteUeNetDevice", LOG_LEVEL_ALL);
622  LogComponentEnable ("LteEnbNetDevice", LOG_LEVEL_ALL);
623 
624  LogComponentEnable ("RadioBearerStatsCalculator", LOG_LEVEL_ALL);
625  LogComponentEnable ("MacStatsCalculator", LOG_LEVEL_ALL);
626 }
627 
628 void
630 {
631  EnableMacTraces ();
632  EnableRlcTraces ();
633  EnablePdcpTraces ();
634 }
635 
636 void
638 {
641 }
642 
643 int64_t
645 {
646  int64_t currentStream = stream;
647  Ptr<NetDevice> netDevice;
648  for (NetDeviceContainer::Iterator i = c.Begin (); i != c.End (); ++i)
649  {
650  netDevice = (*i);
651  Ptr<LteEnbNetDevice> lteEnb = DynamicCast<LteEnbNetDevice> (netDevice);
652  if (lteEnb)
653  {
654  Ptr<LteSpectrumPhy> dlPhy = lteEnb->GetPhy ()->GetDownlinkSpectrumPhy ();
655  Ptr<LteSpectrumPhy> ulPhy = lteEnb->GetPhy ()->GetUplinkSpectrumPhy ();
656  currentStream += dlPhy->AssignStreams (currentStream);
657  currentStream += ulPhy->AssignStreams (currentStream);
658  }
659  Ptr<LteUeNetDevice> lteUe = DynamicCast<LteUeNetDevice> (netDevice);
660  if (lteUe)
661  {
662  Ptr<LteSpectrumPhy> dlPhy = lteUe->GetPhy ()->GetDownlinkSpectrumPhy ();
663  Ptr<LteSpectrumPhy> ulPhy = lteUe->GetPhy ()->GetUplinkSpectrumPhy ();
664  currentStream += dlPhy->AssignStreams (currentStream);
665  currentStream += ulPhy->AssignStreams (currentStream);
666  }
667  }
668  return (currentStream - stream);
669 }
670 
671 uint64_t
672 FindImsiFromEnbRlcPath (std::string path)
673 {
674  NS_LOG_FUNCTION (path);
675  // Sample path input:
676  // /NodeList/#NodeId/DeviceList/#DeviceId/LteEnbRrc/UeMap/#C-RNTI/RadioBearerMap/#LCID/LteRlc/RxPDU
677 
678  // We retrieve the UeInfo associated to the C-RNTI and perform the IMSI lookup
679  std::string ueMapPath = path.substr (0, path.find ("/RadioBearerMap"));
680  Config::MatchContainer match = Config::LookupMatches (ueMapPath);
681 
682  if (match.GetN () != 0)
683  {
684  Ptr<Object> ueInfo = match.Get (0);
685  NS_LOG_LOGIC ("FindImsiFromEnbRlcPath: " << path << ", " << ueInfo->GetObject<UeInfo> ()->GetImsi ());
686  return ueInfo->GetObject<UeInfo> ()->GetImsi ();
687  }
688  else
689  {
690  NS_FATAL_ERROR ("Lookup " << ueMapPath << " got no matches");
691  }
692 }
693 
694 uint16_t
695 FindCellIdFromEnbRlcPath (std::string path)
696 {
697  NS_LOG_FUNCTION (path);
698  // Sample path input:
699  // /NodeList/#NodeId/DeviceList/#DeviceId/LteEnbRrc/UeMap/#C-RNTI/RadioBearerMap/#LCID/LteRlc/RxPDU
700 
701  // We retrieve the CellId associated to the Enb
702  std::string enbNetDevicePath = path.substr (0, path.find ("/LteEnbRrc"));
703  Config::MatchContainer match = Config::LookupMatches (enbNetDevicePath);
704 
705  if (match.GetN () != 0)
706  {
707  Ptr<Object> enbNetDevice = match.Get (0);
708  NS_LOG_LOGIC ("FindCellIdFromEnbRlcPath: " << path << ", " << enbNetDevice->GetObject<LteEnbNetDevice> ()->GetCellId ());
709  return enbNetDevice->GetObject<LteEnbNetDevice> ()->GetCellId ();
710  }
711  else
712  {
713  NS_FATAL_ERROR ("Lookup " << enbNetDevicePath << " got no matches");
714  }
715 }
716 
717 uint64_t
718 FindImsiFromUeRlcPath (std::string path)
719 {
720  NS_LOG_FUNCTION (path);
721  // Sample path input:
722  // /NodeList/#NodeId/DeviceList/#DeviceId/LteUeRrc/RadioBearer/#LCID/RxPDU
723 
724  // We retrieve the LteUeNetDevice path
725  std::string lteUeNetDevicePath = path.substr (0, path.find ("/LteUeRrc"));
726  Config::MatchContainer match = Config::LookupMatches (lteUeNetDevicePath);
727 
728  if (match.GetN () != 0)
729  {
730  Ptr<Object> ueNetDevice = match.Get (0);
731  NS_LOG_LOGIC ("FindImsiFromUeRlcPath: " << path << ", " << ueNetDevice->GetObject<LteUeNetDevice> ()->GetImsi ());
732  return ueNetDevice->GetObject<LteUeNetDevice> ()->GetImsi ();
733  }
734  else
735  {
736  NS_FATAL_ERROR ("Lookup " << lteUeNetDevicePath << " got no matches");
737  }
738 
739 }
740 
741 uint64_t
742 FindImsiFromEnbMac (std::string path, uint16_t rnti)
743 {
744  NS_LOG_FUNCTION (path << rnti);
745  // /NodeList/#NodeId/DeviceList/#DeviceId/LteEnbMac/DlScheduling
746  std::ostringstream oss;
747  std::string p = path.substr (0, path.find ("/LteEnbMac"));
748  oss << rnti;
749  p += "/LteEnbRrc/UeMap/" + oss.str ();
750  uint64_t imsi = FindImsiFromEnbRlcPath (p);
751  NS_LOG_LOGIC ("FindImsiFromEnbMac: " << path << ", " << rnti << ", " << imsi);
752  return imsi;
753 }
754 
755 uint16_t
756 FindCellIdFromEnbMac (std::string path, uint16_t rnti)
757 {
758  NS_LOG_FUNCTION (path << rnti);
759  // /NodeList/#NodeId/DeviceList/#DeviceId/LteEnbMac/DlScheduling
760  std::ostringstream oss;
761  std::string p = path.substr (0, path.find ("/LteEnbMac"));
762  oss << rnti;
763  p += "/LteEnbRrc/UeMap/" + oss.str ();
764  uint16_t cellId = FindCellIdFromEnbRlcPath (p);
765  NS_LOG_LOGIC ("FindCellIdFromEnbMac: " << path << ", "<< rnti << ", " << cellId);
766  return cellId;
767 }
768 
769 
770 void
772  uint16_t rnti, uint8_t lcid, uint32_t packetSize)
773 {
774  NS_LOG_FUNCTION (rlcStats << path << rnti << (uint16_t)lcid << packetSize);
775  uint64_t imsi = 0;
776  if (rlcStats->ExistsImsiPath (path) == true)
777  {
778  imsi = rlcStats->GetImsiPath (path);
779  }
780  else
781  {
782  imsi = FindImsiFromEnbRlcPath (path);
783  rlcStats->SetImsiPath (path, imsi);
784  }
785  uint16_t cellId = 0;
786  if (rlcStats->ExistsCellIdPath (path) == true)
787  {
788  cellId = rlcStats->GetCellIdPath (path);
789  }
790  else
791  {
792  cellId = FindCellIdFromEnbRlcPath (path);
793  rlcStats->SetCellIdPath (path, cellId);
794  }
795  rlcStats->DlTxPdu (cellId, imsi, rnti, lcid, packetSize);
796 }
797 
798 void
800  uint16_t rnti, uint8_t lcid, uint32_t packetSize, uint64_t delay)
801 {
802  NS_LOG_FUNCTION (rlcStats << path << rnti << (uint16_t)lcid << packetSize << delay);
803  uint64_t imsi = 0;
804  if (rlcStats->ExistsImsiPath (path) == true)
805  {
806  imsi = rlcStats->GetImsiPath (path);
807  }
808  else
809  {
810  imsi = FindImsiFromUeRlcPath (path);
811  rlcStats->SetImsiPath (path, imsi);
812  }
813  rlcStats->DlRxPdu (imsi, rnti, lcid, packetSize, delay);
814 }
815 
816 void
818 {
820  Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/UeMap/*/RadioBearerMap/*/LteRlc/TxPDU",
822  Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/RadioBearerMap/*/LteRlc/RxPDU",
824 }
825 
826 void
828  uint16_t rnti, uint8_t lcid, uint32_t packetSize)
829 {
830  NS_LOG_FUNCTION (rlcStats << path << rnti << (uint16_t)lcid << packetSize);
831  uint64_t imsi = 0;
832  if (rlcStats->ExistsImsiPath (path) == true)
833  {
834  imsi = rlcStats->GetImsiPath (path);
835  }
836  else
837  {
838  imsi = FindImsiFromUeRlcPath (path);
839  rlcStats->SetImsiPath (path, imsi);
840  }
841  rlcStats->UlTxPdu (imsi, rnti, lcid, packetSize);
842 }
843 
844 void
846  uint16_t rnti, uint8_t lcid, uint32_t packetSize, uint64_t delay)
847 {
848  NS_LOG_FUNCTION (rlcStats << path << rnti << (uint16_t)lcid << packetSize << delay);
849  uint64_t imsi = 0;
850  if (rlcStats->ExistsImsiPath (path) == true)
851  {
852  imsi = rlcStats->GetImsiPath (path);
853  }
854  else
855  {
856  imsi = FindImsiFromEnbRlcPath (path);
857  rlcStats->SetImsiPath (path, imsi);
858  }
859  uint16_t cellId = 0;
860  if (rlcStats->ExistsCellIdPath (path) == true)
861  {
862  cellId = rlcStats->GetCellIdPath (path);
863  }
864  else
865  {
866  cellId = FindCellIdFromEnbRlcPath (path);
867  rlcStats->SetCellIdPath (path, cellId);
868  }
869  rlcStats->UlRxPdu (cellId, imsi, rnti, lcid, packetSize, delay);
870 }
871 
872 
873 void
875  std::string path, uint32_t frameNo, uint32_t subframeNo,
876  uint16_t rnti, uint8_t mcsTb1, uint16_t sizeTb1,
877  uint8_t mcsTb2, uint16_t sizeTb2)
878 {
879  NS_LOG_FUNCTION (macStats << path);
880  uint64_t imsi = 0;
881  std::ostringstream pathAndRnti;
882  pathAndRnti << path << "/" << rnti;
883  if (macStats->ExistsImsiPath (pathAndRnti.str ()) == true)
884  {
885  imsi = macStats->GetImsiPath (pathAndRnti.str ());
886  }
887  else
888  {
889  imsi = FindImsiFromEnbMac (path, rnti);
890  macStats->SetImsiPath (pathAndRnti.str (), imsi);
891  }
892 
893  uint16_t cellId = 0;
894  if (macStats->ExistsCellIdPath (pathAndRnti.str ()) == true)
895  {
896  cellId = macStats->GetCellIdPath (pathAndRnti.str ());
897  }
898  else
899  {
900  cellId = FindCellIdFromEnbMac (path, rnti);
901  macStats->SetCellIdPath (pathAndRnti.str (), cellId);
902  }
903 
904  macStats->DlScheduling (cellId, imsi, frameNo, subframeNo, rnti, mcsTb1, sizeTb1, mcsTb2, sizeTb2);
905 }
906 
907 void
909 {
910  Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/RadioBearerMap/*/LteRlc/TxPDU",
912  Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/UeMap/*/RadioBearerMap/*/LteRlc/RxPDU",
914 }
915 
916 void
918 {
921 }
922 
923 
924 void
926 {
927  Config::Connect ("/NodeList/*/DeviceList/*/LteEnbMac/DlScheduling",
929 }
930 
931 void
932 UlSchedulingCallback (Ptr<MacStatsCalculator> macStats, std::string path,
933  uint32_t frameNo, uint32_t subframeNo, uint16_t rnti,
934  uint8_t mcs, uint16_t size)
935 {
936  NS_LOG_FUNCTION (macStats << path);
937 
938  uint64_t imsi = 0;
939  std::ostringstream pathAndRnti;
940  pathAndRnti << path << "/" << rnti;
941  if (macStats->ExistsImsiPath (pathAndRnti.str ()) == true)
942  {
943  imsi = macStats->GetImsiPath (pathAndRnti.str ());
944  }
945  else
946  {
947  imsi = FindImsiFromEnbMac (path, rnti);
948  macStats->SetImsiPath (pathAndRnti.str (), imsi);
949  }
950  uint16_t cellId = 0;
951  if (macStats->ExistsCellIdPath (pathAndRnti.str ()) == true)
952  {
953  cellId = macStats->GetCellIdPath (pathAndRnti.str ());
954  }
955  else
956  {
957  cellId = FindCellIdFromEnbMac (path, rnti);
958  macStats->SetCellIdPath (pathAndRnti.str (), cellId);
959  }
960 
961  macStats->UlScheduling (cellId, imsi, frameNo, subframeNo, rnti, mcs, size);
962 }
963 
964 void
966 {
967  Config::Connect ("/NodeList/*/DeviceList/*/LteEnbMac/UlScheduling",
969 }
970 
973 {
974  return m_rlcStats;
975 }
976 
977 void
979 {
982 }
983 
984 void
986 {
988  Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/UeMap/*/RadioBearerMap/*/LtePdcp/TxPDU",
990  Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/RadioBearerMap/*/LtePdcp/RxPDU",
992 }
993 
994 void
996 {
997  Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/RadioBearerMap/*/LtePdcp/TxPDU",
999  Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/UeMap/*/RadioBearerMap/*/LtePdcp/RxPDU",
1001 }
1002 
1005 {
1006  return m_pdcpStats;
1007 }
1008 
1009 } // namespace ns3