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<LteCtrlSinrChunkProcessor> pCtrl = Create<LteCtrlSinrChunkProcessor> (phy->GetObject<LtePhy> ());
322  ulPhy->AddCtrlSinrChunkProcessor (pCtrl); // for evaluating SRS UL-CQI
323 
324  Ptr<LteDataSinrChunkProcessor> pData = Create<LteDataSinrChunkProcessor> (ulPhy, phy);
325  ulPhy->AddDataSinrChunkProcessor (pData); // for evaluating PUSCH UL-CQI
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->SetLtePhyRxDataEndOkCallback (MakeCallback (&LteEnbPhy::PhyPduReceived, phy));
372  ulPhy->SetLtePhyRxCtrlEndOkCallback (MakeCallback (&LteEnbPhy::ReceiveLteControlMessageList, phy));
373  rrc->SetForwardUpCallback (MakeCallback (&LteEnbNetDevice::Receive, dev));
374 
375  NS_LOG_LOGIC ("set the propagation model frequencies");
377  NS_LOG_LOGIC ("DL freq: " << dlFreq);
378  bool dlFreqOk = m_downlinkPathlossModel->SetAttributeFailSafe ("Frequency", DoubleValue (dlFreq));
379  if (!dlFreqOk)
380  {
381  NS_LOG_WARN ("DL propagation model does not have a Frequency attribute");
382  }
384  NS_LOG_LOGIC ("UL freq: " << ulFreq);
385  bool ulFreqOk = m_uplinkPathlossModel->SetAttributeFailSafe ("Frequency", DoubleValue (ulFreq));
386  if (!ulFreqOk)
387  {
388  NS_LOG_WARN ("UL propagation model does not have a Frequency attribute");
389  }
390 
391 
392  dev->Start ();
393 
394  m_uplinkChannel->AddRx (ulPhy);
395 
396  if (m_epcHelper != 0)
397  {
398  NS_LOG_INFO ("adding this eNB to the EPC");
399  m_epcHelper->AddEnb (n, dev);
400  }
401 
402  return dev;
403 }
404 
407 {
408  NS_LOG_FUNCTION (this);
409  Ptr<LteSpectrumPhy> dlPhy = CreateObject<LteSpectrumPhy> ();
410  Ptr<LteSpectrumPhy> ulPhy = CreateObject<LteSpectrumPhy> ();
411 
412  Ptr<LteUePhy> phy = CreateObject<LteUePhy> (dlPhy, ulPhy);
413 
414  Ptr<LteCtrlSinrChunkProcessor> pCtrl = Create<LteCtrlSinrChunkProcessor> (phy->GetObject<LtePhy> (), dlPhy);
415  dlPhy->AddCtrlSinrChunkProcessor (pCtrl);
416 
417  Ptr<LteDataSinrChunkProcessor> pData = Create<LteDataSinrChunkProcessor> (dlPhy);
418  dlPhy->AddDataSinrChunkProcessor (pData);
419 
420  dlPhy->SetChannel (m_downlinkChannel);
421  ulPhy->SetChannel (m_uplinkChannel);
422 
424  NS_ASSERT_MSG (mm, "MobilityModel needs to be set on node before calling LteHelper::InstallUeDevice ()");
425  dlPhy->SetMobility (mm);
426  ulPhy->SetMobility (mm);
427 
428 
429  Ptr<AntennaModel> antenna = (m_ueAntennaModelFactory.Create ())->GetObject<AntennaModel> ();
430  NS_ASSERT_MSG (antenna, "error in creating the AntennaModel object");
431  dlPhy->SetAntenna (antenna);
432  ulPhy->SetAntenna (antenna);
433 
434  Ptr<LteUeMac> mac = CreateObject<LteUeMac> ();
435  Ptr<LteUeRrc> rrc = CreateObject<LteUeRrc> ();
436 
437  // connect SAPs
439  mac->SetLteUeCmacSapUser (rrc->GetLteUeCmacSapUser ());
440  rrc->SetLteMacSapProvider (mac->GetLteMacSapProvider ());
441 
442  phy->SetLteUePhySapUser (mac->GetLteUePhySapUser ());
443  mac->SetLteUePhySapProvider (phy->GetLteUePhySapProvider ());
444 
445  Ptr<LteUeNetDevice> dev = CreateObject<LteUeNetDevice> (n, phy, mac, rrc);
446  phy->SetDevice (dev);
447  dlPhy->SetDevice (dev);
448  ulPhy->SetDevice (dev);
449 
450  n->AddDevice (dev);
451  dlPhy->SetLtePhyRxDataEndOkCallback (MakeCallback (&LteUePhy::PhyPduReceived, phy));
452  dlPhy->SetLtePhyRxCtrlEndOkCallback (MakeCallback (&LteUePhy::ReceiveLteControlMessageList, phy));
453  rrc->SetForwardUpCallback (MakeCallback (&LteUeNetDevice::Receive, dev));
454 
455  return dev;
456 }
457 
458 
459 void
461 {
462  NS_LOG_FUNCTION (this);
463  for (NetDeviceContainer::Iterator i = ueDevices.Begin (); i != ueDevices.End (); ++i)
464  {
465  Attach (*i, enbDevice);
466  }
467 }
468 
469 void
471 {
472  NS_LOG_FUNCTION (this);
473  // setup RRC connection
474  Ptr<LteEnbRrc> enbRrc = enbDevice->GetObject<LteEnbNetDevice> ()->GetRrc ();
475  uint16_t rnti = enbRrc->AddUe (ueDevice->GetObject<LteUeNetDevice> ()->GetImsi ());
476  Ptr<LteUeRrc> ueRrc = ueDevice->GetObject<LteUeNetDevice> ()->GetRrc ();
477  ueRrc->ConfigureUe (rnti, enbDevice->GetObject<LteEnbNetDevice> ()->GetCellId () );
478  //enbRrc->SetCellId (enbDevice->GetObject<LteEnbNetDevice> ()->GetCellId ());
479 
480  // attach UE to eNB
481  ueDevice->GetObject<LteUeNetDevice> ()->SetTargetEnb (enbDevice->GetObject<LteEnbNetDevice> ());
482 
483 
484  // connect at the PHY layer
485  Ptr<LteEnbPhy> enbPhy = enbDevice->GetObject<LteEnbNetDevice> ()->GetPhy ();
486  Ptr<LteUePhy> uePhy = ueDevice->GetObject<LteUeNetDevice> ()->GetPhy ();
487  enbPhy->AddUePhy (rnti);
488 
489 //
490  // WILD HACK - should be done through PHY SAP, probably passing by RRC
491  NS_LOG_DEBUG ("!Attach eNB " << enbDevice->GetObject<LteEnbNetDevice> ()->GetCellId () << " with UE " << rnti);
492  uePhy->SetRnti (rnti);
493  uePhy->DoSetBandwidth (enbDevice->GetObject<LteEnbNetDevice> ()->GetUlBandwidth (),
494  enbDevice->GetObject<LteEnbNetDevice> ()->GetDlBandwidth ());
495  uePhy->DoSetEarfcn (enbDevice->GetObject<LteEnbNetDevice> ()->GetDlEarfcn (),
496  enbDevice->GetObject<LteEnbNetDevice> ()->GetUlEarfcn ());
497  enbRrc->ConfigureNewUe (rnti);
498  ueDevice->Start ();
499 
501 }
502 
503 void
505 {
506  NS_LOG_FUNCTION (this);
507  for (NetDeviceContainer::Iterator i = ueDevices.Begin (); i != ueDevices.End (); ++i)
508  {
509  AttachToClosestEnb (*i, enbDevices);
510  }
511 }
512 
513 void
515 {
516  NS_LOG_FUNCTION (this);
517  NS_ASSERT_MSG (enbDevices.GetN () > 0, "empty enb device container");
518  Vector uepos = ueDevice->GetNode ()->GetObject<MobilityModel> ()->GetPosition ();
519  double minDistance = std::numeric_limits<double>::infinity ();
520  Ptr<NetDevice> closestEnbDevice;
521  for (NetDeviceContainer::Iterator i = enbDevices.Begin (); i != enbDevices.End (); ++i)
522  {
523  Vector enbpos = (*i)->GetNode ()->GetObject<MobilityModel> ()->GetPosition ();
524  double distance = CalculateDistance (uepos, enbpos);
525  if (distance < minDistance)
526  {
527  minDistance = distance;
528  closestEnbDevice = *i;
529  }
530  }
531  NS_ASSERT (closestEnbDevice != 0);
532  Attach (ueDevice, closestEnbDevice);
533 }
534 
535 void
537 {
538  NS_LOG_FUNCTION (this);
539  for (NetDeviceContainer::Iterator i = ueDevices.Begin (); i != ueDevices.End (); ++i)
540  {
541  ActivateEpsBearer (*i, bearer, tft);
542  }
543 }
544 
545 
546 void
548 {
549  NS_LOG_FUNCTION (this);
550  NS_LOG_INFO (" setting up Radio Bearer");
551  Ptr<LteEnbNetDevice> enbDevice = ueDevice->GetObject<LteUeNetDevice> ()->GetTargetEnb ();
552  Ptr<LteEnbRrc> enbRrc = enbDevice->GetObject<LteEnbNetDevice> ()->GetRrc ();
553  Ptr<LteUeRrc> ueRrc = ueDevice->GetObject<LteUeNetDevice> ()->GetRrc ();
554  uint16_t rnti = ueRrc->GetRnti ();
555  TypeId rlcTypeId = GetRlcType (bearer);
556  uint8_t lcid = enbRrc->SetupRadioBearer (rnti, bearer, rlcTypeId);
557  ueRrc->SetupRadioBearer (rnti, bearer, rlcTypeId, lcid, tft);
558 
559  if (m_epcHelper != 0)
560  {
561  NS_LOG_INFO (" setting up S1 Bearer");
562  m_epcHelper->ActivateEpsBearer (ueDevice, enbDevice, tft, rnti, lcid);
563 
564  }
565 }
566 
567 TypeId
569 {
570  switch (m_epsBearerToRlcMapping)
571  {
572  case RLC_SM_ALWAYS:
573  return LteRlcSm::GetTypeId ();
574  break;
575 
576  case RLC_UM_ALWAYS:
577  return LteRlcUm::GetTypeId ();
578  break;
579 
580  case RLC_AM_ALWAYS:
581  return LteRlcAm::GetTypeId ();
582  break;
583 
584  case PER_BASED:
585  if (bearer.GetPacketErrorLossRate () > 1.0e-5)
586  {
587  return LteRlcUm::GetTypeId ();
588  }
589  else
590  {
591  return LteRlcAm::GetTypeId ();
592  }
593  break;
594 
595  default:
596  return LteRlcSm::GetTypeId ();
597  break;
598  }
599 }
600 
601 void
603 {
604  LogComponentEnable ("LteHelper", LOG_LEVEL_ALL);
605  LogComponentEnable ("LteEnbRrc", LOG_LEVEL_ALL);
606  LogComponentEnable ("LteUeRrc", LOG_LEVEL_ALL);
607  LogComponentEnable ("LteEnbMac", LOG_LEVEL_ALL);
608  LogComponentEnable ("LteUeMac", LOG_LEVEL_ALL);
609  LogComponentEnable ("LteRlc", LOG_LEVEL_ALL);
610  LogComponentEnable ("LteRlcUm", LOG_LEVEL_ALL);
611  LogComponentEnable ("LteRlcAm", LOG_LEVEL_ALL);
612  LogComponentEnable ("RrFfMacScheduler", LOG_LEVEL_ALL);
613  LogComponentEnable ("PfFfMacScheduler", LOG_LEVEL_ALL);
614 
615  LogComponentEnable ("LtePhy", LOG_LEVEL_ALL);
616  LogComponentEnable ("LteEnbPhy", LOG_LEVEL_ALL);
617  LogComponentEnable ("LteUePhy", LOG_LEVEL_ALL);
618  LogComponentEnable ("LteSpectrumValueHelper", LOG_LEVEL_ALL);
619  LogComponentEnable ("LteSpectrumPhy", LOG_LEVEL_ALL);
620  LogComponentEnable ("LteInterference", LOG_LEVEL_ALL);
621  LogComponentEnable ("LteSinrChunkProcessor", LOG_LEVEL_ALL);
622 
623  std::string propModelStr = m_dlPathlossModelFactory.GetTypeId ().GetName ().erase (0,5).c_str ();
624  LogComponentEnable ("LteNetDevice", LOG_LEVEL_ALL);
625  LogComponentEnable ("LteUeNetDevice", LOG_LEVEL_ALL);
626  LogComponentEnable ("LteEnbNetDevice", LOG_LEVEL_ALL);
627 
628  LogComponentEnable ("RadioBearerStatsCalculator", LOG_LEVEL_ALL);
629  LogComponentEnable ("MacStatsCalculator", LOG_LEVEL_ALL);
630 }
631 
632 void
634 {
635  EnableMacTraces ();
636  EnableRlcTraces ();
637  EnablePdcpTraces ();
638 }
639 
640 void
642 {
645 }
646 
647 int64_t
649 {
650  int64_t currentStream = stream;
651  Ptr<NetDevice> netDevice;
652  for (NetDeviceContainer::Iterator i = c.Begin (); i != c.End (); ++i)
653  {
654  netDevice = (*i);
655  Ptr<LteEnbNetDevice> lteEnb = DynamicCast<LteEnbNetDevice> (netDevice);
656  if (lteEnb)
657  {
658  Ptr<LteSpectrumPhy> dlPhy = lteEnb->GetPhy ()->GetDownlinkSpectrumPhy ();
659  Ptr<LteSpectrumPhy> ulPhy = lteEnb->GetPhy ()->GetUplinkSpectrumPhy ();
660  currentStream += dlPhy->AssignStreams (currentStream);
661  currentStream += ulPhy->AssignStreams (currentStream);
662  }
663  Ptr<LteUeNetDevice> lteUe = DynamicCast<LteUeNetDevice> (netDevice);
664  if (lteUe)
665  {
666  Ptr<LteSpectrumPhy> dlPhy = lteUe->GetPhy ()->GetDownlinkSpectrumPhy ();
667  Ptr<LteSpectrumPhy> ulPhy = lteUe->GetPhy ()->GetUplinkSpectrumPhy ();
668  currentStream += dlPhy->AssignStreams (currentStream);
669  currentStream += ulPhy->AssignStreams (currentStream);
670  }
671  }
672  return (currentStream - stream);
673 }
674 
675 uint64_t
676 FindImsiFromEnbRlcPath (std::string path)
677 {
678  NS_LOG_FUNCTION (path);
679  // Sample path input:
680  // /NodeList/#NodeId/DeviceList/#DeviceId/LteEnbRrc/UeMap/#C-RNTI/RadioBearerMap/#LCID/LteRlc/RxPDU
681 
682  // We retrieve the UeInfo associated to the C-RNTI and perform the IMSI lookup
683  std::string ueMapPath = path.substr (0, path.find ("/RadioBearerMap"));
684  Config::MatchContainer match = Config::LookupMatches (ueMapPath);
685 
686  if (match.GetN () != 0)
687  {
688  Ptr<Object> ueInfo = match.Get (0);
689  NS_LOG_LOGIC ("FindImsiFromEnbRlcPath: " << path << ", " << ueInfo->GetObject<UeInfo> ()->GetImsi ());
690  return ueInfo->GetObject<UeInfo> ()->GetImsi ();
691  }
692  else
693  {
694  NS_FATAL_ERROR ("Lookup " << ueMapPath << " got no matches");
695  }
696 }
697 
698 uint16_t
699 FindCellIdFromEnbRlcPath (std::string path)
700 {
701  NS_LOG_FUNCTION (path);
702  // Sample path input:
703  // /NodeList/#NodeId/DeviceList/#DeviceId/LteEnbRrc/UeMap/#C-RNTI/RadioBearerMap/#LCID/LteRlc/RxPDU
704 
705  // We retrieve the CellId associated to the Enb
706  std::string enbNetDevicePath = path.substr (0, path.find ("/LteEnbRrc"));
707  Config::MatchContainer match = Config::LookupMatches (enbNetDevicePath);
708 
709  if (match.GetN () != 0)
710  {
711  Ptr<Object> enbNetDevice = match.Get (0);
712  NS_LOG_LOGIC ("FindCellIdFromEnbRlcPath: " << path << ", " << enbNetDevice->GetObject<LteEnbNetDevice> ()->GetCellId ());
713  return enbNetDevice->GetObject<LteEnbNetDevice> ()->GetCellId ();
714  }
715  else
716  {
717  NS_FATAL_ERROR ("Lookup " << enbNetDevicePath << " got no matches");
718  }
719 }
720 
721 uint64_t
722 FindImsiFromUeRlcPath (std::string path)
723 {
724  NS_LOG_FUNCTION (path);
725  // Sample path input:
726  // /NodeList/#NodeId/DeviceList/#DeviceId/LteUeRrc/RadioBearer/#LCID/RxPDU
727 
728  // We retrieve the LteUeNetDevice path
729  std::string lteUeNetDevicePath = path.substr (0, path.find ("/LteUeRrc"));
730  Config::MatchContainer match = Config::LookupMatches (lteUeNetDevicePath);
731 
732  if (match.GetN () != 0)
733  {
734  Ptr<Object> ueNetDevice = match.Get (0);
735  NS_LOG_LOGIC ("FindImsiFromUeRlcPath: " << path << ", " << ueNetDevice->GetObject<LteUeNetDevice> ()->GetImsi ());
736  return ueNetDevice->GetObject<LteUeNetDevice> ()->GetImsi ();
737  }
738  else
739  {
740  NS_FATAL_ERROR ("Lookup " << lteUeNetDevicePath << " got no matches");
741  }
742 
743 }
744 
745 uint64_t
746 FindImsiFromEnbMac (std::string path, uint16_t rnti)
747 {
748  NS_LOG_FUNCTION (path << rnti);
749  // /NodeList/#NodeId/DeviceList/#DeviceId/LteEnbMac/DlScheduling
750  std::ostringstream oss;
751  std::string p = path.substr (0, path.find ("/LteEnbMac"));
752  oss << rnti;
753  p += "/LteEnbRrc/UeMap/" + oss.str ();
754  uint64_t imsi = FindImsiFromEnbRlcPath (p);
755  NS_LOG_LOGIC ("FindImsiFromEnbMac: " << path << ", " << rnti << ", " << imsi);
756  return imsi;
757 }
758 
759 uint16_t
760 FindCellIdFromEnbMac (std::string path, uint16_t rnti)
761 {
762  NS_LOG_FUNCTION (path << rnti);
763  // /NodeList/#NodeId/DeviceList/#DeviceId/LteEnbMac/DlScheduling
764  std::ostringstream oss;
765  std::string p = path.substr (0, path.find ("/LteEnbMac"));
766  oss << rnti;
767  p += "/LteEnbRrc/UeMap/" + oss.str ();
768  uint16_t cellId = FindCellIdFromEnbRlcPath (p);
769  NS_LOG_LOGIC ("FindCellIdFromEnbMac: " << path << ", "<< rnti << ", " << cellId);
770  return cellId;
771 }
772 
773 
774 void
776  uint16_t rnti, uint8_t lcid, uint32_t packetSize)
777 {
778  NS_LOG_FUNCTION (rlcStats << path << rnti << (uint16_t)lcid << packetSize);
779  uint64_t imsi = 0;
780  if (rlcStats->ExistsImsiPath (path) == true)
781  {
782  imsi = rlcStats->GetImsiPath (path);
783  }
784  else
785  {
786  imsi = FindImsiFromEnbRlcPath (path);
787  rlcStats->SetImsiPath (path, imsi);
788  }
789  uint16_t cellId = 0;
790  if (rlcStats->ExistsCellIdPath (path) == true)
791  {
792  cellId = rlcStats->GetCellIdPath (path);
793  }
794  else
795  {
796  cellId = FindCellIdFromEnbRlcPath (path);
797  rlcStats->SetCellIdPath (path, cellId);
798  }
799  rlcStats->DlTxPdu (cellId, imsi, rnti, lcid, packetSize);
800 }
801 
802 void
804  uint16_t rnti, uint8_t lcid, uint32_t packetSize, uint64_t delay)
805 {
806  NS_LOG_FUNCTION (rlcStats << path << rnti << (uint16_t)lcid << packetSize << delay);
807  uint64_t imsi = 0;
808  if (rlcStats->ExistsImsiPath (path) == true)
809  {
810  imsi = rlcStats->GetImsiPath (path);
811  }
812  else
813  {
814  imsi = FindImsiFromUeRlcPath (path);
815  rlcStats->SetImsiPath (path, imsi);
816  }
817  rlcStats->DlRxPdu (imsi, rnti, lcid, packetSize, delay);
818 }
819 
820 void
822 {
824  Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/UeMap/*/RadioBearerMap/*/LteRlc/TxPDU",
826  Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/RadioBearerMap/*/LteRlc/RxPDU",
828 }
829 
830 void
832  uint16_t rnti, uint8_t lcid, uint32_t packetSize)
833 {
834  NS_LOG_FUNCTION (rlcStats << path << rnti << (uint16_t)lcid << packetSize);
835  uint64_t imsi = 0;
836  if (rlcStats->ExistsImsiPath (path) == true)
837  {
838  imsi = rlcStats->GetImsiPath (path);
839  }
840  else
841  {
842  imsi = FindImsiFromUeRlcPath (path);
843  rlcStats->SetImsiPath (path, imsi);
844  }
845  rlcStats->UlTxPdu (imsi, rnti, lcid, packetSize);
846 }
847 
848 void
850  uint16_t rnti, uint8_t lcid, uint32_t packetSize, uint64_t delay)
851 {
852  NS_LOG_FUNCTION (rlcStats << path << rnti << (uint16_t)lcid << packetSize << delay);
853  uint64_t imsi = 0;
854  if (rlcStats->ExistsImsiPath (path) == true)
855  {
856  imsi = rlcStats->GetImsiPath (path);
857  }
858  else
859  {
860  imsi = FindImsiFromEnbRlcPath (path);
861  rlcStats->SetImsiPath (path, imsi);
862  }
863  uint16_t cellId = 0;
864  if (rlcStats->ExistsCellIdPath (path) == true)
865  {
866  cellId = rlcStats->GetCellIdPath (path);
867  }
868  else
869  {
870  cellId = FindCellIdFromEnbRlcPath (path);
871  rlcStats->SetCellIdPath (path, cellId);
872  }
873  rlcStats->UlRxPdu (cellId, imsi, rnti, lcid, packetSize, delay);
874 }
875 
876 
877 void
879  std::string path, uint32_t frameNo, uint32_t subframeNo,
880  uint16_t rnti, uint8_t mcsTb1, uint16_t sizeTb1,
881  uint8_t mcsTb2, uint16_t sizeTb2)
882 {
883  NS_LOG_FUNCTION (macStats << path);
884  uint64_t imsi = 0;
885  std::ostringstream pathAndRnti;
886  pathAndRnti << path << "/" << rnti;
887  if (macStats->ExistsImsiPath (pathAndRnti.str ()) == true)
888  {
889  imsi = macStats->GetImsiPath (pathAndRnti.str ());
890  }
891  else
892  {
893  imsi = FindImsiFromEnbMac (path, rnti);
894  macStats->SetImsiPath (pathAndRnti.str (), imsi);
895  }
896 
897  uint16_t cellId = 0;
898  if (macStats->ExistsCellIdPath (pathAndRnti.str ()) == true)
899  {
900  cellId = macStats->GetCellIdPath (pathAndRnti.str ());
901  }
902  else
903  {
904  cellId = FindCellIdFromEnbMac (path, rnti);
905  macStats->SetCellIdPath (pathAndRnti.str (), cellId);
906  }
907 
908  macStats->DlScheduling (cellId, imsi, frameNo, subframeNo, rnti, mcsTb1, sizeTb1, mcsTb2, sizeTb2);
909 }
910 
911 void
913 {
914  Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/RadioBearerMap/*/LteRlc/TxPDU",
916  Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/UeMap/*/RadioBearerMap/*/LteRlc/RxPDU",
918 }
919 
920 void
922 {
925 }
926 
927 
928 void
930 {
931  Config::Connect ("/NodeList/*/DeviceList/*/LteEnbMac/DlScheduling",
933 }
934 
935 void
936 UlSchedulingCallback (Ptr<MacStatsCalculator> macStats, std::string path,
937  uint32_t frameNo, uint32_t subframeNo, uint16_t rnti,
938  uint8_t mcs, uint16_t size)
939 {
940  NS_LOG_FUNCTION (macStats << path);
941 
942  uint64_t imsi = 0;
943  std::ostringstream pathAndRnti;
944  pathAndRnti << path << "/" << rnti;
945  if (macStats->ExistsImsiPath (pathAndRnti.str ()) == true)
946  {
947  imsi = macStats->GetImsiPath (pathAndRnti.str ());
948  }
949  else
950  {
951  imsi = FindImsiFromEnbMac (path, rnti);
952  macStats->SetImsiPath (pathAndRnti.str (), imsi);
953  }
954  uint16_t cellId = 0;
955  if (macStats->ExistsCellIdPath (pathAndRnti.str ()) == true)
956  {
957  cellId = macStats->GetCellIdPath (pathAndRnti.str ());
958  }
959  else
960  {
961  cellId = FindCellIdFromEnbMac (path, rnti);
962  macStats->SetCellIdPath (pathAndRnti.str (), cellId);
963  }
964 
965  macStats->UlScheduling (cellId, imsi, frameNo, subframeNo, rnti, mcs, size);
966 }
967 
968 void
970 {
971  Config::Connect ("/NodeList/*/DeviceList/*/LteEnbMac/UlScheduling",
973 }
974 
977 {
978  return m_rlcStats;
979 }
980 
981 void
983 {
986 }
987 
988 void
990 {
992  Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/UeMap/*/RadioBearerMap/*/LtePdcp/TxPDU",
994  Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/RadioBearerMap/*/LtePdcp/RxPDU",
996 }
997 
998 void
1000 {
1001  Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/RadioBearerMap/*/LtePdcp/TxPDU",
1003  Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/UeMap/*/RadioBearerMap/*/LtePdcp/RxPDU",
1005 }
1006 
1009 {
1010  return m_pdcpStats;
1011 }
1012 
1013 } // namespace ns3