aboutsummaryrefslogtreecommitdiffstats
path: root/emu-radio/lte-emulator/extensions/lte-tap-helper.cc
diff options
context:
space:
mode:
Diffstat (limited to 'emu-radio/lte-emulator/extensions/lte-tap-helper.cc')
-rw-r--r--emu-radio/lte-emulator/extensions/lte-tap-helper.cc1350
1 files changed, 1350 insertions, 0 deletions
diff --git a/emu-radio/lte-emulator/extensions/lte-tap-helper.cc b/emu-radio/lte-emulator/extensions/lte-tap-helper.cc
new file mode 100644
index 00000000..15d35b3a
--- /dev/null
+++ b/emu-radio/lte-emulator/extensions/lte-tap-helper.cc
@@ -0,0 +1,1350 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "lte-tap-helper.h"
+#include <ns3/string.h>
+#include <ns3/log.h>
+#include <ns3/abort.h>
+#include <ns3/pointer.h>
+#include <ns3/lte-enb-rrc.h>
+#include <ns3/epc-ue-nas.h>
+#include <ns3/epc-enb-application.h>
+#include <ns3/lte-ue-rrc.h>
+#include <ns3/lte-ue-mac.h>
+#include <ns3/lte-enb-mac.h>
+#include <ns3/lte-enb-net-device.h>
+#include <ns3/lte-enb-phy.h>
+#include <ns3/lte-ue-phy.h>
+#include <ns3/lte-spectrum-phy.h>
+#include <ns3/lte-chunk-processor.h>
+#include <ns3/multi-model-spectrum-channel.h>
+#include <ns3/friis-spectrum-propagation-loss.h>
+#include <ns3/trace-fading-loss-model.h>
+#include <ns3/isotropic-antenna-model.h>
+#include <ns3/lte-enb-net-device.h>
+#include <ns3/lte-ue-net-device.h>
+#include <ns3/ff-mac-scheduler.h>
+#include <ns3/lte-ffr-algorithm.h>
+#include <ns3/lte-handover-algorithm.h>
+#include <ns3/lte-anr.h>
+#include <ns3/lte-rlc.h>
+#include <ns3/lte-rlc-um.h>
+#include <ns3/lte-rlc-am.h>
+#include <ns3/epc-enb-s1-sap.h>
+#include <ns3/lte-rrc-protocol-ideal.h>
+#include <ns3/lte-rrc-protocol-real.h>
+#include <ns3/mac-stats-calculator.h>
+#include <ns3/phy-stats-calculator.h>
+#include <ns3/phy-tx-stats-calculator.h>
+#include <ns3/phy-rx-stats-calculator.h>
+#include <ns3/epc-helper.h>
+#include <iostream>
+#include <ns3/buildings-propagation-loss-model.h>
+#include <ns3/lte-spectrum-value-helper.h>
+#include <ns3/epc-x2.h>
+
+#include "lte-tap-ue-net-device.h"
+#define ALPHA 0.999
+
+/**
+ * \brief this file has been modified from that of lte-helper.cpp in ns3 lte module to support emulation of lte channel
+ */
+
+namespace ns3 {
+
+NS_LOG_COMPONENT_DEFINE ("LteTapHelper");
+
+NS_OBJECT_ENSURE_REGISTERED (LteTapHelper);
+
+LteTapHelper::LteTapHelper (void)
+ : m_fadingStreamsAssigned (false),
+ m_imsiCounter (0),
+ m_cellIdCounter (0)
+{
+ NS_LOG_FUNCTION (this);
+ m_enbNetDeviceFactory.SetTypeId (LteEnbNetDevice::GetTypeId ());
+ m_enbAntennaModelFactory.SetTypeId (IsotropicAntennaModel::GetTypeId ());
+ m_ueNetDeviceFactory.SetTypeId (LteTapUeNetDevice::GetTypeId ());
+ m_ueAntennaModelFactory.SetTypeId (IsotropicAntennaModel::GetTypeId ());
+ m_channelFactory.SetTypeId (MultiModelSpectrumChannel::GetTypeId ());
+}
+
+void
+LteTapHelper::DoInitialize (void)
+{
+ NS_LOG_FUNCTION (this);
+ m_downlinkChannel = m_channelFactory.Create<SpectrumChannel> ();
+ m_uplinkChannel = m_channelFactory.Create<SpectrumChannel> ();
+
+ m_downlinkPathlossModel = m_dlPathlossModelFactory.Create ();
+ Ptr<SpectrumPropagationLossModel> dlSplm = m_downlinkPathlossModel->GetObject<SpectrumPropagationLossModel> ();
+ if (dlSplm != 0)
+ {
+ NS_LOG_LOGIC (this << " using a SpectrumPropagationLossModel in DL");
+ m_downlinkChannel->AddSpectrumPropagationLossModel (dlSplm);
+ }
+ else
+ {
+ NS_LOG_LOGIC (this << " using a PropagationLossModel in DL");
+ Ptr<PropagationLossModel> dlPlm = m_downlinkPathlossModel->GetObject<PropagationLossModel> ();
+ NS_ASSERT_MSG (dlPlm != 0, " " << m_downlinkPathlossModel << " is neither PropagationLossModel nor SpectrumPropagationLossModel");
+ m_downlinkChannel->AddPropagationLossModel (dlPlm);
+ }
+
+ m_uplinkPathlossModel = m_ulPathlossModelFactory.Create ();
+ Ptr<SpectrumPropagationLossModel> ulSplm = m_uplinkPathlossModel->GetObject<SpectrumPropagationLossModel> ();
+ if (ulSplm != 0)
+ {
+ NS_LOG_LOGIC (this << " using a SpectrumPropagationLossModel in UL");
+ m_uplinkChannel->AddSpectrumPropagationLossModel (ulSplm);
+ }
+ else
+ {
+ NS_LOG_LOGIC (this << " using a PropagationLossModel in UL");
+ Ptr<PropagationLossModel> ulPlm = m_uplinkPathlossModel->GetObject<PropagationLossModel> ();
+ NS_ASSERT_MSG (ulPlm != 0, " " << m_uplinkPathlossModel << " is neither PropagationLossModel nor SpectrumPropagationLossModel");
+ m_uplinkChannel->AddPropagationLossModel (ulPlm);
+ }
+ if (!m_fadingModelType.empty ())
+ {
+ m_fadingModule = m_fadingModelFactory.Create<SpectrumPropagationLossModel> ();
+ m_fadingModule->Initialize ();
+ m_downlinkChannel->AddSpectrumPropagationLossModel (m_fadingModule);
+ m_uplinkChannel->AddSpectrumPropagationLossModel (m_fadingModule);
+ }
+ m_phyStats = CreateObject<PhyStatsCalculator> ();
+ m_phyTxStats = CreateObject<PhyTxStatsCalculator> ();
+ m_phyRxStats = CreateObject<PhyRxStatsCalculator> ();
+ m_macStats = CreateObject<MacStatsCalculator> ();
+ Object::DoInitialize ();
+
+}
+
+LteTapHelper::~LteTapHelper (void)
+{
+ NS_LOG_FUNCTION (this);
+}
+
+TypeId LteTapHelper::GetTypeId (void)
+{
+ static TypeId
+ tid =
+ TypeId ("ns3::LteTapHelper")
+ .SetParent<Object> ()
+ .AddConstructor<LteTapHelper> ()
+ .AddAttribute ("Scheduler",
+ "The type of scheduler to be used for eNBs. "
+ "The allowed values for this attributes are the type names "
+ "of any class inheriting from ns3::FfMacScheduler.",
+ StringValue ("ns3::PfFfMacScheduler"),
+ MakeStringAccessor (&LteTapHelper::SetSchedulerType,
+ &LteTapHelper::GetSchedulerType),
+ MakeStringChecker ())
+ .AddAttribute ("FfrAlgorithm",
+ "The type of FFR algorithm to be used for eNBs. "
+ "The allowed values for this attributes are the type names "
+ "of any class inheriting from ns3::LteFfrAlgorithm.",
+ StringValue ("ns3::LteFrNoOpAlgorithm"),
+ MakeStringAccessor (&LteTapHelper::SetFfrAlgorithmType,
+ &LteTapHelper::GetFfrAlgorithmType),
+ MakeStringChecker ())
+ .AddAttribute ("HandoverAlgorithm",
+ "The type of handover algorithm to be used for eNBs. "
+ "The allowed values for this attributes are the type names "
+ "of any class inheriting from ns3::LteHandoverAlgorithm.",
+ StringValue ("ns3::NoOpHandoverAlgorithm"),
+ MakeStringAccessor (&LteTapHelper::SetHandoverAlgorithmType,
+ &LteTapHelper::GetHandoverAlgorithmType),
+ MakeStringChecker ())
+ .AddAttribute ("PathlossModel",
+ "The type of pathloss model to be used. "
+ "The allowed values for this attributes are the type names "
+ "of any class inheriting from ns3::PropagationLossModel.",
+ StringValue ("ns3::FriisPropagationLossModel"),
+ MakeStringAccessor (&LteTapHelper::SetPathlossModelType),
+ MakeStringChecker ())
+ .AddAttribute ("FadingModel",
+ "The type of fading model to be used."
+ "The allowed values for this attributes are the type names "
+ "of any class inheriting from ns3::SpectrumPropagationLossModel."
+ "If the type is set to an empty string, no fading model is used.",
+ StringValue (""),
+ MakeStringAccessor (&LteTapHelper::SetFadingModel),
+ MakeStringChecker ())
+ .AddAttribute ("UseIdealRrc",
+ "If true, LteRrcProtocolIdeal will be used for RRC signaling. "
+ "If false, LteRrcProtocolReal will be used.",
+ BooleanValue (true),
+ MakeBooleanAccessor (&LteTapHelper::m_useIdealRrc),
+ MakeBooleanChecker ())
+ .AddAttribute ("AnrEnabled",
+ "Activate or deactivate Automatic Neighbour Relation function",
+ BooleanValue (true),
+ MakeBooleanAccessor (&LteTapHelper::m_isAnrEnabled),
+ MakeBooleanChecker ())
+ .AddAttribute ("UsePdschForCqiGeneration",
+ "If true, DL-CQI will be calculated from PDCCH as signal and PDSCH as interference "
+ "If false, DL-CQI will be calculated from PDCCH as signal and PDCCH as interference ",
+ BooleanValue (true),
+ MakeBooleanAccessor (&LteTapHelper::m_usePdschForCqiGeneration),
+ MakeBooleanChecker ())
+ ;
+ return tid;
+}
+
+void
+LteTapHelper::DoDispose ()
+{
+ NS_LOG_FUNCTION (this);
+ m_downlinkChannel = 0;
+ m_uplinkChannel = 0;
+ Object::DoDispose ();
+}
+
+
+void
+LteTapHelper::SetEpcHelper (Ptr<EpcHelper> h)
+{
+ NS_LOG_FUNCTION (this << h);
+ m_epcHelper = h;
+}
+
+void
+LteTapHelper::SetSchedulerType (std::string type)
+{
+ NS_LOG_FUNCTION (this << type);
+ m_schedulerFactory = ObjectFactory ();
+ m_schedulerFactory.SetTypeId (type);
+}
+
+std::string
+LteTapHelper::GetSchedulerType () const
+{
+ return m_schedulerFactory.GetTypeId ().GetName ();
+}
+
+void
+LteTapHelper::SetSchedulerAttribute (std::string n, const AttributeValue &v)
+{
+ NS_LOG_FUNCTION (this << n);
+ m_schedulerFactory.Set (n, v);
+}
+
+std::string
+LteTapHelper::GetFfrAlgorithmType () const
+{
+ return m_ffrAlgorithmFactory.GetTypeId ().GetName ();
+}
+
+void
+LteTapHelper::SetFfrAlgorithmType (std::string type)
+{
+ NS_LOG_FUNCTION (this << type);
+ m_ffrAlgorithmFactory = ObjectFactory ();
+ m_ffrAlgorithmFactory.SetTypeId (type);
+}
+
+void
+LteTapHelper::SetFfrAlgorithmAttribute (std::string n, const AttributeValue &v)
+{
+ NS_LOG_FUNCTION (this << n);
+ m_ffrAlgorithmFactory.Set (n, v);
+}
+
+std::string
+LteTapHelper::GetHandoverAlgorithmType () const
+{
+ return m_handoverAlgorithmFactory.GetTypeId ().GetName ();
+}
+
+void
+LteTapHelper::SetHandoverAlgorithmType (std::string type)
+{
+ NS_LOG_FUNCTION (this << type);
+ m_handoverAlgorithmFactory = ObjectFactory ();
+ m_handoverAlgorithmFactory.SetTypeId (type);
+}
+
+void
+LteTapHelper::SetHandoverAlgorithmAttribute (std::string n, const AttributeValue &v)
+{
+ NS_LOG_FUNCTION (this << n);
+ m_handoverAlgorithmFactory.Set (n, v);
+}
+
+
+void
+LteTapHelper::SetPathlossModelType (std::string type)
+{
+ NS_LOG_FUNCTION (this << type);
+ m_dlPathlossModelFactory = ObjectFactory ();
+ m_dlPathlossModelFactory.SetTypeId (type);
+ m_ulPathlossModelFactory = ObjectFactory ();
+ m_ulPathlossModelFactory.SetTypeId (type);
+}
+
+void
+LteTapHelper::SetPathlossModelAttribute (std::string n, const AttributeValue &v)
+{
+ NS_LOG_FUNCTION (this << n);
+ m_dlPathlossModelFactory.Set (n, v);
+ m_ulPathlossModelFactory.Set (n, v);
+}
+
+void
+LteTapHelper::SetEnbDeviceAttribute (std::string n, const AttributeValue &v)
+{
+ NS_LOG_FUNCTION (this);
+ m_enbNetDeviceFactory.Set (n, v);
+}
+
+
+void
+LteTapHelper::SetEnbAntennaModelType (std::string type)
+{
+ NS_LOG_FUNCTION (this);
+ m_enbAntennaModelFactory.SetTypeId (type);
+}
+
+void
+LteTapHelper::SetEnbAntennaModelAttribute (std::string n, const AttributeValue &v)
+{
+ NS_LOG_FUNCTION (this);
+ m_enbAntennaModelFactory.Set (n, v);
+}
+
+void
+LteTapHelper::SetUeDeviceAttribute (std::string n, const AttributeValue &v)
+{
+ NS_LOG_FUNCTION (this);
+ m_ueNetDeviceFactory.Set (n, v);
+}
+
+void
+LteTapHelper::SetUeAntennaModelType (std::string type)
+{
+ NS_LOG_FUNCTION (this);
+ m_ueAntennaModelFactory.SetTypeId (type);
+}
+
+void
+LteTapHelper::SetUeAntennaModelAttribute (std::string n, const AttributeValue &v)
+{
+ NS_LOG_FUNCTION (this);
+ m_ueAntennaModelFactory.Set (n, v);
+}
+
+void
+LteTapHelper::SetFadingModel (std::string type)
+{
+ NS_LOG_FUNCTION (this << type);
+ m_fadingModelType = type;
+ if (!type.empty ())
+ {
+ m_fadingModelFactory = ObjectFactory ();
+ m_fadingModelFactory.SetTypeId (type);
+ }
+}
+
+void
+LteTapHelper::SetFadingModelAttribute (std::string n, const AttributeValue &v)
+{
+ m_fadingModelFactory.Set (n, v);
+}
+
+void
+LteTapHelper::SetSpectrumChannelType (std::string type)
+{
+ NS_LOG_FUNCTION (this << type);
+ m_channelFactory.SetTypeId (type);
+}
+
+void
+LteTapHelper::SetSpectrumChannelAttribute (std::string n, const AttributeValue &v)
+{
+ m_channelFactory.Set (n, v);
+}
+
+
+NetDeviceContainer
+LteTapHelper::InstallEnbDevice (NodeContainer c)
+{
+ NS_LOG_FUNCTION (this);
+ Initialize (); // will run DoInitialize () if necessary
+ NetDeviceContainer devices;
+ for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
+ {
+ Ptr<Node> node = *i;
+ Ptr<NetDevice> device = InstallSingleEnbDevice (node);
+ devices.Add (device);
+ }
+ return devices;
+}
+
+NetDeviceContainer
+LteTapHelper::InstallUeDevice (NodeContainer c)
+{
+ NS_LOG_FUNCTION (this);
+ NetDeviceContainer devices;
+ for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
+ {
+ Ptr<Node> node = *i;
+ Ptr<NetDevice> device = InstallSingleUeDevice (node);
+ devices.Add (device);
+ }
+ return devices;
+}
+
+
+Ptr<NetDevice>
+LteTapHelper::InstallSingleEnbDevice (Ptr<Node> n)
+{
+
+ NS_ABORT_MSG_IF (m_cellIdCounter == 65535, "max num eNBs exceeded");
+ uint16_t cellId = ++m_cellIdCounter;
+
+ Ptr<LteSpectrumPhy> dlPhy = CreateObject<LteSpectrumPhy> ();
+ Ptr<LteSpectrumPhy> ulPhy = CreateObject<LteSpectrumPhy> ();
+
+ Ptr<LteEnbPhy> phy = CreateObject<LteEnbPhy> (dlPhy, ulPhy);
+
+ Ptr<LteHarqPhy> harq = Create<LteHarqPhy> ();
+ dlPhy->SetHarqPhyModule (harq);
+ ulPhy->SetHarqPhyModule (harq);
+ phy->SetHarqPhyModule (harq);
+
+ Ptr<LteChunkProcessor> pCtrl = Create<LteChunkProcessor> ();
+ pCtrl->AddCallback (MakeCallback (&LteEnbPhy::GenerateCtrlCqiReport, phy));
+ ulPhy->AddCtrlSinrChunkProcessor (pCtrl); // for evaluating SRS UL-CQI
+
+ Ptr<LteChunkProcessor> pData = Create<LteChunkProcessor> ();
+ pData->AddCallback (MakeCallback (&LteEnbPhy::GenerateDataCqiReport, phy));
+ pData->AddCallback (MakeCallback (&LteSpectrumPhy::UpdateSinrPerceived, ulPhy));
+ ulPhy->AddDataSinrChunkProcessor (pData); // for evaluating PUSCH UL-CQI
+
+ Ptr<LteChunkProcessor> pInterf = Create<LteChunkProcessor> ();
+ pInterf->AddCallback (MakeCallback (&LteEnbPhy::ReportInterference, phy));
+ ulPhy->AddInterferenceDataChunkProcessor (pInterf); // for interference power tracing
+
+ dlPhy->SetChannel (m_downlinkChannel);
+ ulPhy->SetChannel (m_uplinkChannel);
+
+ Ptr<MobilityModel> mm = n->GetObject<MobilityModel> ();
+ NS_ASSERT_MSG (mm, "MobilityModel needs to be set on node before calling LteTapHelper::InstallUeDevice ()");
+ dlPhy->SetMobility (mm);
+ ulPhy->SetMobility (mm);
+
+ Ptr<AntennaModel> antenna = (m_enbAntennaModelFactory.Create ())->GetObject<AntennaModel> ();
+ NS_ASSERT_MSG (antenna, "error in creating the AntennaModel object");
+ dlPhy->SetAntenna (antenna);
+ ulPhy->SetAntenna (antenna);
+
+ Ptr<LteEnbMac> mac = CreateObject<LteEnbMac> ();
+ Ptr<FfMacScheduler> sched = m_schedulerFactory.Create<FfMacScheduler> ();
+ Ptr<LteFfrAlgorithm> ffrAlgorithm = m_ffrAlgorithmFactory.Create<LteFfrAlgorithm> ();
+ Ptr<LteHandoverAlgorithm> handoverAlgorithm = m_handoverAlgorithmFactory.Create<LteHandoverAlgorithm> ();
+ Ptr<LteEnbRrc> rrc = CreateObject<LteEnbRrc> ();
+
+ if (m_useIdealRrc)
+ {
+ Ptr<LteEnbRrcProtocolIdeal> rrcProtocol = CreateObject<LteEnbRrcProtocolIdeal> ();
+ rrcProtocol->SetLteEnbRrcSapProvider (rrc->GetLteEnbRrcSapProvider ());
+ rrc->SetLteEnbRrcSapUser (rrcProtocol->GetLteEnbRrcSapUser ());
+ rrc->AggregateObject (rrcProtocol);
+ rrcProtocol->SetCellId (cellId);
+ }
+ else
+ {
+ Ptr<LteEnbRrcProtocolReal> rrcProtocol = CreateObject<LteEnbRrcProtocolReal> ();
+ rrcProtocol->SetLteEnbRrcSapProvider (rrc->GetLteEnbRrcSapProvider ());
+ rrc->SetLteEnbRrcSapUser (rrcProtocol->GetLteEnbRrcSapUser ());
+ rrc->AggregateObject (rrcProtocol);
+ rrcProtocol->SetCellId (cellId);
+ }
+
+ if (m_epcHelper != 0)
+ {
+ EnumValue epsBearerToRlcMapping;
+ rrc->GetAttribute ("EpsBearerToRlcMapping", epsBearerToRlcMapping);
+ // it does not make sense to use RLC/SM when also using the EPC
+ if (epsBearerToRlcMapping.Get () == LteEnbRrc::RLC_SM_ALWAYS)
+ {
+ rrc->SetAttribute ("EpsBearerToRlcMapping", EnumValue (LteEnbRrc::RLC_UM_ALWAYS));
+ }
+ }
+
+ rrc->SetLteEnbCmacSapProvider (mac->GetLteEnbCmacSapProvider ());
+ mac->SetLteEnbCmacSapUser (rrc->GetLteEnbCmacSapUser ());
+ rrc->SetLteMacSapProvider (mac->GetLteMacSapProvider ());
+
+ rrc->SetLteHandoverManagementSapProvider (handoverAlgorithm->GetLteHandoverManagementSapProvider ());
+ handoverAlgorithm->SetLteHandoverManagementSapUser (rrc->GetLteHandoverManagementSapUser ());
+
+ mac->SetFfMacSchedSapProvider (sched->GetFfMacSchedSapProvider ());
+ mac->SetFfMacCschedSapProvider (sched->GetFfMacCschedSapProvider ());
+
+ sched->SetFfMacSchedSapUser (mac->GetFfMacSchedSapUser ());
+ sched->SetFfMacCschedSapUser (mac->GetFfMacCschedSapUser ());
+
+ phy->SetLteEnbPhySapUser (mac->GetLteEnbPhySapUser ());
+ mac->SetLteEnbPhySapProvider (phy->GetLteEnbPhySapProvider ());
+
+ phy->SetLteEnbCphySapUser (rrc->GetLteEnbCphySapUser ());
+ rrc->SetLteEnbCphySapProvider (phy->GetLteEnbCphySapProvider ());
+
+ //FFR SAP
+ sched->SetLteFfrSapProvider (ffrAlgorithm->GetLteFfrSapProvider ());
+ ffrAlgorithm->SetLteFfrSapUser (sched->GetLteFfrSapUser ());
+
+ rrc->SetLteFfrRrcSapProvider (ffrAlgorithm->GetLteFfrRrcSapProvider ());
+ ffrAlgorithm->SetLteFfrRrcSapUser (rrc->GetLteFfrRrcSapUser ());
+ //FFR SAP END
+
+ Ptr<LteEnbNetDevice> dev = m_enbNetDeviceFactory.Create<LteEnbNetDevice> ();
+ dev->SetNode (n);
+ dev->SetAttribute ("CellId", UintegerValue (cellId));
+ dev->SetAttribute ("LteEnbPhy", PointerValue (phy));
+ dev->SetAttribute ("LteEnbMac", PointerValue (mac));
+ dev->SetAttribute ("FfMacScheduler", PointerValue (sched));
+ dev->SetAttribute ("LteEnbRrc", PointerValue (rrc));
+ dev->SetAttribute ("LteHandoverAlgorithm", PointerValue (handoverAlgorithm));
+ dev->SetAttribute ("LteFfrAlgorithm", PointerValue (ffrAlgorithm));
+
+ if (m_isAnrEnabled)
+ {
+ Ptr<LteAnr> anr = CreateObject<LteAnr> (cellId);
+ rrc->SetLteAnrSapProvider (anr->GetLteAnrSapProvider ());
+ anr->SetLteAnrSapUser (rrc->GetLteAnrSapUser ());
+ dev->SetAttribute ("LteAnr", PointerValue (anr));
+ }
+
+ phy->SetDevice (dev);
+ dlPhy->SetDevice (dev);
+ ulPhy->SetDevice (dev);
+
+ n->AddDevice (dev);
+ ulPhy->SetLtePhyRxDataEndOkCallback (MakeCallback (&LteEnbPhy::PhyPduReceived, phy));
+ ulPhy->SetLtePhyRxCtrlEndOkCallback (MakeCallback (&LteEnbPhy::ReceiveLteControlMessageList, phy));
+ ulPhy->SetLtePhyUlHarqFeedbackCallback (MakeCallback (&LteEnbPhy::ReceiveLteUlHarqFeedback, phy));
+ rrc->SetForwardUpCallback (MakeCallback (&LteEnbNetDevice::Receive, dev));
+
+ NS_LOG_LOGIC ("set the propagation model frequencies");
+ double dlFreq = LteSpectrumValueHelper::GetCarrierFrequency (dev->GetDlEarfcn ());
+ NS_LOG_LOGIC ("DL freq: " << dlFreq);
+ bool dlFreqOk = m_downlinkPathlossModel->SetAttributeFailSafe ("Frequency", DoubleValue (dlFreq));
+ if (!dlFreqOk)
+ {
+ NS_LOG_WARN ("DL propagation model does not have a Frequency attribute");
+ }
+ double ulFreq = LteSpectrumValueHelper::GetCarrierFrequency (dev->GetUlEarfcn ());
+ NS_LOG_LOGIC ("UL freq: " << ulFreq);
+ bool ulFreqOk = m_uplinkPathlossModel->SetAttributeFailSafe ("Frequency", DoubleValue (ulFreq));
+ if (!ulFreqOk)
+ {
+ NS_LOG_WARN ("UL propagation model does not have a Frequency attribute");
+ }
+
+ dev->Initialize ();
+
+ m_uplinkChannel->AddRx (ulPhy);
+
+ if (m_epcHelper != 0)
+ {
+ NS_LOG_INFO ("adding this eNB to the EPC");
+ m_epcHelper->AddEnb (n, dev, dev->GetCellId ());
+ Ptr<EpcEnbApplication> enbApp = n->GetApplication (0)->GetObject<EpcEnbApplication> ();
+ NS_ASSERT_MSG (enbApp != 0, "cannot retrieve EpcEnbApplication");
+
+ // S1 SAPs
+ rrc->SetS1SapProvider (enbApp->GetS1SapProvider ());
+ enbApp->SetS1SapUser (rrc->GetS1SapUser ());
+
+ // X2 SAPs
+ Ptr<EpcX2> x2 = n->GetObject<EpcX2> ();
+ x2->SetEpcX2SapUser (rrc->GetEpcX2SapUser ());
+ rrc->SetEpcX2SapProvider (x2->GetEpcX2SapProvider ());
+ }
+
+ return dev;
+}
+
+Ptr<NetDevice>
+LteTapHelper::InstallSingleUeDevice (Ptr<Node> n)
+{
+ NS_LOG_FUNCTION (this);
+ Ptr<LteSpectrumPhy> dlPhy = CreateObject<LteSpectrumPhy> ();
+ Ptr<LteSpectrumPhy> ulPhy = CreateObject<LteSpectrumPhy> ();
+
+ Ptr<LteUePhy> phy = CreateObject<LteUePhy> (dlPhy, ulPhy);
+
+ Ptr<LteHarqPhy> harq = Create<LteHarqPhy> ();
+ dlPhy->SetHarqPhyModule (harq);
+ ulPhy->SetHarqPhyModule (harq);
+ phy->SetHarqPhyModule (harq);
+
+ Ptr<LteChunkProcessor> pRs = Create<LteChunkProcessor> ();
+ pRs->AddCallback (MakeCallback (&LteUePhy::ReportRsReceivedPower, phy));
+ dlPhy->AddRsPowerChunkProcessor (pRs);
+
+ Ptr<LteChunkProcessor> pInterf = Create<LteChunkProcessor> ();
+ pInterf->AddCallback (MakeCallback (&LteUePhy::ReportInterference, phy));
+ dlPhy->AddInterferenceCtrlChunkProcessor (pInterf); // for RSRQ evaluation of UE Measurements
+
+ Ptr<LteChunkProcessor> pCtrl = Create<LteChunkProcessor> ();
+ pCtrl->AddCallback (MakeCallback (&LteSpectrumPhy::UpdateSinrPerceived, dlPhy));
+ dlPhy->AddCtrlSinrChunkProcessor (pCtrl);
+
+ Ptr<LteChunkProcessor> pData = Create<LteChunkProcessor> ();
+ pData->AddCallback (MakeCallback (&LteSpectrumPhy::UpdateSinrPerceived, dlPhy));
+ dlPhy->AddDataSinrChunkProcessor (pData);
+
+ if (m_usePdschForCqiGeneration)
+ {
+ // CQI calculation based on PDCCH for signal and PDSCH for interference
+ pCtrl->AddCallback (MakeCallback (&LteUePhy::GenerateMixedCqiReport, phy));
+ Ptr<LteChunkProcessor> pDataInterf = Create<LteChunkProcessor> ();
+ pDataInterf->AddCallback (MakeCallback (&LteUePhy::ReportDataInterference, phy));
+ dlPhy->AddInterferenceDataChunkProcessor (pDataInterf);
+ }
+ else
+ {
+ // CQI calculation based on PDCCH for both signal and interference
+ pCtrl->AddCallback (MakeCallback (&LteUePhy::GenerateCtrlCqiReport, phy));
+ }
+
+
+
+ dlPhy->SetChannel (m_downlinkChannel);
+ ulPhy->SetChannel (m_uplinkChannel);
+
+ Ptr<MobilityModel> mm = n->GetObject<MobilityModel> ();
+ NS_ASSERT_MSG (mm, "MobilityModel needs to be set on node before calling LteTapHelper::InstallUeDevice ()");
+ dlPhy->SetMobility (mm);
+ ulPhy->SetMobility (mm);
+
+ Ptr<AntennaModel> antenna = (m_ueAntennaModelFactory.Create ())->GetObject<AntennaModel> ();
+ NS_ASSERT_MSG (antenna, "error in creating the AntennaModel object");
+ dlPhy->SetAntenna (antenna);
+ ulPhy->SetAntenna (antenna);
+
+ Ptr<LteUeMac> mac = CreateObject<LteUeMac> ();
+ Ptr<LteUeRrc> rrc = CreateObject<LteUeRrc> ();
+
+ if (m_useIdealRrc)
+ {
+ Ptr<LteUeRrcProtocolIdeal> rrcProtocol = CreateObject<LteUeRrcProtocolIdeal> ();
+ rrcProtocol->SetUeRrc (rrc);
+ rrc->AggregateObject (rrcProtocol);
+ rrcProtocol->SetLteUeRrcSapProvider (rrc->GetLteUeRrcSapProvider ());
+ rrc->SetLteUeRrcSapUser (rrcProtocol->GetLteUeRrcSapUser ());
+ }
+ else
+ {
+ Ptr<LteUeRrcProtocolReal> rrcProtocol = CreateObject<LteUeRrcProtocolReal> ();
+ rrcProtocol->SetUeRrc (rrc);
+ rrc->AggregateObject (rrcProtocol);
+ rrcProtocol->SetLteUeRrcSapProvider (rrc->GetLteUeRrcSapProvider ());
+ rrc->SetLteUeRrcSapUser (rrcProtocol->GetLteUeRrcSapUser ());
+ }
+
+ if (m_epcHelper != 0)
+ {
+ rrc->SetUseRlcSm (false);
+ }
+ Ptr<EpcUeNas> nas = CreateObject<EpcUeNas> ();
+
+ nas->SetAsSapProvider (rrc->GetAsSapProvider ());
+ rrc->SetAsSapUser (nas->GetAsSapUser ());
+
+ rrc->SetLteUeCmacSapProvider (mac->GetLteUeCmacSapProvider ());
+ mac->SetLteUeCmacSapUser (rrc->GetLteUeCmacSapUser ());
+ rrc->SetLteMacSapProvider (mac->GetLteMacSapProvider ());
+
+ phy->SetLteUePhySapUser (mac->GetLteUePhySapUser ());
+ mac->SetLteUePhySapProvider (phy->GetLteUePhySapProvider ());
+
+ phy->SetLteUeCphySapUser (rrc->GetLteUeCphySapUser ());
+ rrc->SetLteUeCphySapProvider (phy->GetLteUeCphySapProvider ());
+
+ NS_ABORT_MSG_IF (m_imsiCounter >= 0xFFFFFFFF, "max num UEs exceeded");
+ uint64_t imsi = ++m_imsiCounter;
+
+ Ptr<LteTapUeNetDevice> dev = m_ueNetDeviceFactory.Create<LteTapUeNetDevice> ();
+ dev->SetNode (n);
+ dev->SetAttribute ("Imsi", UintegerValue (imsi));
+ dev->SetAttribute ("LteUePhy", PointerValue (phy));
+ dev->SetAttribute ("LteUeMac", PointerValue (mac));
+ dev->SetAttribute ("LteUeRrc", PointerValue (rrc));
+ dev->SetAttribute ("EpcUeNas", PointerValue (nas));
+
+ phy->SetDevice (dev);
+ dlPhy->SetDevice (dev);
+ ulPhy->SetDevice (dev);
+ nas->SetDevice (dev);
+
+ n->AddDevice (dev);
+ dlPhy->SetLtePhyRxDataEndOkCallback (MakeCallback (&LteUePhy::PhyPduReceived, phy));
+ dlPhy->SetLtePhyRxCtrlEndOkCallback (MakeCallback (&LteUePhy::ReceiveLteControlMessageList, phy));
+ dlPhy->SetLtePhyRxPssCallback (MakeCallback (&LteUePhy::ReceivePss, phy));
+ dlPhy->SetLtePhyDlHarqFeedbackCallback (MakeCallback (&LteUePhy::ReceiveLteDlHarqFeedback, phy));
+ nas->SetForwardUpCallback (MakeCallback (&LteTapUeNetDevice::Receive, dev));
+
+ if (m_epcHelper != 0)
+ {
+ m_epcHelper->AddUe (dev, dev->GetImsi ());
+ }
+
+ dev->Initialize ();
+
+ return dev;
+}
+
+
+void
+LteTapHelper::Attach (NetDeviceContainer ueDevices)
+{
+ NS_LOG_FUNCTION (this);
+ for (NetDeviceContainer::Iterator i = ueDevices.Begin (); i != ueDevices.End (); ++i)
+ {
+ Attach (*i);
+ }
+}
+
+void
+LteTapHelper::Attach (Ptr<NetDevice> ueDevice)
+{
+ NS_LOG_FUNCTION (this);
+
+ if (m_epcHelper == 0)
+ {
+ NS_FATAL_ERROR ("This function is not valid without properly configured EPC");
+ }
+
+ Ptr<LteUeNetDevice> ueLteDevice = ueDevice->GetObject<LteUeNetDevice> ();
+ if (ueLteDevice == 0)
+ {
+ NS_FATAL_ERROR ("The passed NetDevice must be an LteUeNetDevice");
+ }
+
+ // initiate cell selection
+ Ptr<EpcUeNas> ueNas = ueLteDevice->GetNas ();
+ NS_ASSERT (ueNas != 0);
+ uint16_t dlEarfcn = ueLteDevice->GetDlEarfcn ();
+ ueNas->StartCellSelection (dlEarfcn);
+
+ // instruct UE to immediately enter CONNECTED mode after camping
+ ueNas->Connect ();
+
+ // activate default EPS bearer
+ m_epcHelper->ActivateEpsBearer (ueDevice, ueLteDevice->GetImsi (),
+ EpcTft::Default (),
+ EpsBearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT));
+}
+
+void
+LteTapHelper::Attach (NetDeviceContainer ueDevices, Ptr<NetDevice> enbDevice)
+{
+ NS_LOG_FUNCTION (this);
+ for (NetDeviceContainer::Iterator i = ueDevices.Begin (); i != ueDevices.End (); ++i)
+ {
+ Attach (*i, enbDevice);
+ }
+}
+
+void
+LteTapHelper::Attach (Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice)
+{
+ NS_LOG_FUNCTION (this);
+ //enbRrc->SetCellId (enbDevice->GetObject<LteEnbNetDevice> ()->GetCellId ());
+
+ Ptr<LteTapUeNetDevice> ueLteDevice = ueDevice->GetObject<LteTapUeNetDevice> ();
+ Ptr<LteEnbNetDevice> enbLteDevice = enbDevice->GetObject<LteEnbNetDevice> ();
+
+ Ptr<EpcUeNas> ueNas = ueLteDevice->GetNas ();
+ ueNas->Connect (enbLteDevice->GetCellId (), enbLteDevice->GetDlEarfcn ());
+
+ if (m_epcHelper != 0)
+ {
+ // activate default EPS bearer
+ m_epcHelper->ActivateEpsBearer (ueDevice, ueLteDevice->GetImsi (), EpcTft::Default (), EpsBearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT));
+ }
+
+ // tricks needed for the simplified LTE-only simulations
+ if (m_epcHelper == 0)
+ {
+ ueDevice->GetObject<LteTapUeNetDevice> ()->SetTargetEnb (enbDevice->GetObject<LteEnbNetDevice> ());
+ }
+}
+
+void
+LteTapHelper::AttachToClosestEnb (NetDeviceContainer ueDevices, NetDeviceContainer enbDevices)
+{
+ NS_LOG_FUNCTION (this);
+ for (NetDeviceContainer::Iterator i = ueDevices.Begin (); i != ueDevices.End (); ++i)
+ {
+ AttachToClosestEnb (*i, enbDevices);
+ }
+}
+
+void
+LteTapHelper::AttachToClosestEnb (Ptr<NetDevice> ueDevice, NetDeviceContainer enbDevices)
+{
+ NS_LOG_FUNCTION (this);
+ NS_ASSERT_MSG (enbDevices.GetN () > 0, "empty enb device container");
+ Vector uepos = ueDevice->GetNode ()->GetObject<MobilityModel> ()->GetPosition ();
+ double minDistance = std::numeric_limits<double>::infinity ();
+ Ptr<NetDevice> closestEnbDevice;
+ for (NetDeviceContainer::Iterator i = enbDevices.Begin (); i != enbDevices.End (); ++i)
+ {
+ Vector enbpos = (*i)->GetNode ()->GetObject<MobilityModel> ()->GetPosition ();
+ double distance = CalculateDistance (uepos, enbpos);
+ if (distance < minDistance)
+ {
+ minDistance = distance;
+ closestEnbDevice = *i;
+ }
+ }
+ NS_ASSERT (closestEnbDevice != 0);
+ Attach (ueDevice, closestEnbDevice);
+}
+
+uint8_t
+LteTapHelper::ActivateDedicatedEpsBearer (NetDeviceContainer ueDevices, EpsBearer bearer, Ptr<EpcTft> tft)
+{
+ NS_LOG_FUNCTION (this);
+ for (NetDeviceContainer::Iterator i = ueDevices.Begin (); i != ueDevices.End (); ++i)
+ {
+ uint8_t bearerId = ActivateDedicatedEpsBearer (*i, bearer, tft);
+ return bearerId;
+ }
+ return 0;
+}
+
+
+uint8_t
+LteTapHelper::ActivateDedicatedEpsBearer (Ptr<NetDevice> ueDevice, EpsBearer bearer, Ptr<EpcTft> tft)
+{
+ NS_LOG_FUNCTION (this);
+
+ NS_ASSERT_MSG (m_epcHelper != 0, "dedicated EPS bearers cannot be set up when the EPC is not used");
+
+ uint64_t imsi = ueDevice->GetObject<LteUeNetDevice> ()->GetImsi ();
+ uint8_t bearerId = m_epcHelper->ActivateEpsBearer (ueDevice, imsi, tft, bearer);
+ return bearerId;
+}
+
+/**
+ * \ingroup lte
+ *
+ * TapDrbActivatior allows user to activate bearers for UEs
+ * when EPC is not used. Activation function is hooked to
+ * the Enb RRC Connection Estabilished trace source. When
+ * UE change its RRC state to CONNECTED_NORMALLY, activation
+ * function is called and bearer is activated.
+*/
+class TapDrbActivator : public SimpleRefCount<TapDrbActivator>
+{
+public:
+ /**
+ * TapDrbActivator Constructor
+ *
+ * \param ueDevice the UeNetDevice for which bearer will be activated
+ * \param bearer the bearer configuration
+ */
+ TapDrbActivator (Ptr<NetDevice> ueDevice, EpsBearer bearer);
+
+ /**
+ * Function hooked to the Enb RRC Connection Established trace source
+ * Fired upon successful RRC connection establishment.
+ *
+ * \param a TapDrbActivator object
+ * \param context
+ * \param imsi
+ * \param cellId
+ * \param rnti
+ */
+ static void ActivateCallback (Ptr<TapDrbActivator> a, std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti);
+
+ /**
+ * Procedure firstly checks if bearer was not activated, if IMSI
+ * from trace source equals configured one and if UE is really
+ * in RRC connected state. If all requirements are met, it performs
+ * bearer activation.
+ *
+ * \param imsi
+ * \param cellId
+ * \param rnti
+ */
+ void ActivateTapDrb (uint64_t imsi, uint16_t cellId, uint16_t rnti);
+private:
+ /**
+ * Bearer can be activated only once. This value stores state of
+ * bearer. Initially is set to false and changed to true during
+ * bearer activation.
+ */
+ bool m_active;
+ /**
+ * UeNetDevice for which bearer will be activated
+ */
+ Ptr<NetDevice> m_ueDevice;
+ /**
+ * Configuration of bearer which will be activated
+ */
+ EpsBearer m_bearer;
+ /**
+ * imsi the unique UE identifier
+ */
+ uint64_t m_imsi;
+};
+
+TapDrbActivator::TapDrbActivator (Ptr<NetDevice> ueDevice, EpsBearer bearer)
+ : m_active (false),
+ m_ueDevice (ueDevice),
+ m_bearer (bearer),
+ m_imsi (m_ueDevice->GetObject<LteUeNetDevice> ()->GetImsi ())
+{
+}
+
+void
+TapDrbActivator::ActivateCallback (Ptr<TapDrbActivator> a, std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti)
+{
+ NS_LOG_FUNCTION (a << context << imsi << cellId << rnti);
+ a->ActivateTapDrb (imsi, cellId, rnti);
+}
+
+void
+TapDrbActivator::ActivateTapDrb (uint64_t imsi, uint16_t cellId, uint16_t rnti)
+{
+ NS_LOG_FUNCTION (this << imsi << cellId << rnti << m_active);
+ if ((!m_active) && (imsi == m_imsi))
+ {
+ Ptr<LteUeRrc> ueRrc = m_ueDevice->GetObject<LteUeNetDevice> ()->GetRrc ();
+ NS_ASSERT (ueRrc->GetState () == LteUeRrc::CONNECTED_NORMALLY);
+ uint16_t rnti = ueRrc->GetRnti ();
+ Ptr<LteEnbNetDevice> enbLteDevice = m_ueDevice->GetObject<LteUeNetDevice> ()->GetTargetEnb ();
+ Ptr<LteEnbRrc> enbRrc = enbLteDevice->GetObject<LteEnbNetDevice> ()->GetRrc ();
+ NS_ASSERT (ueRrc->GetCellId () == enbLteDevice->GetCellId ());
+ Ptr<UeManager> ueManager = enbRrc->GetUeManager (rnti);
+ NS_ASSERT (ueManager->GetState () == UeManager::CONNECTED_NORMALLY
+ || ueManager->GetState () == UeManager::CONNECTION_RECONFIGURATION);
+ EpcEnbS1SapUser::DataRadioBearerSetupRequestParameters params;
+ params.rnti = rnti;
+ params.bearer = m_bearer;
+ params.bearerId = 0;
+ params.gtpTeid = 0; // don't care
+ enbRrc->GetS1SapUser ()->DataRadioBearerSetupRequest (params);
+ m_active = true;
+ }
+}
+
+
+void
+LteTapHelper::ActivateDataRadioBearer (Ptr<NetDevice> ueDevice, EpsBearer bearer)
+{
+ NS_LOG_FUNCTION (this << ueDevice);
+ NS_ASSERT_MSG (m_epcHelper == 0, "this method must not be used when the EPC is being used");
+
+ // Normally it is the EPC that takes care of activating DRBs
+ // when the UE gets connected. When the EPC is not used, we achieve
+ // the same behavior by hooking a dedicated DRB activation function
+ // to the Enb RRC Connection Established trace source
+
+
+ Ptr<LteEnbNetDevice> enbLteDevice = ueDevice->GetObject<LteUeNetDevice> ()->GetTargetEnb ();
+
+ std::ostringstream path;
+ path << "/NodeList/" << enbLteDevice->GetNode ()->GetId ()
+ << "/DeviceList/" << enbLteDevice->GetIfIndex ()
+ << "/LteEnbRrc/ConnectionEstablished";
+ Ptr<TapDrbActivator> arg = Create<TapDrbActivator> (ueDevice, bearer);
+ Config::Connect (path.str (), MakeBoundCallback (&TapDrbActivator::ActivateCallback, arg));
+}
+
+void
+LteTapHelper::AddX2Interface (NodeContainer enbNodes)
+{
+ NS_LOG_FUNCTION (this);
+
+ NS_ASSERT_MSG (m_epcHelper != 0, "X2 interfaces cannot be set up when the EPC is not used");
+
+ for (NodeContainer::Iterator i = enbNodes.Begin (); i != enbNodes.End (); ++i)
+ {
+ for (NodeContainer::Iterator j = i + 1; j != enbNodes.End (); ++j)
+ {
+ AddX2Interface (*i, *j);
+ }
+ }
+}
+
+void
+LteTapHelper::AddX2Interface (Ptr<Node> enbNode1, Ptr<Node> enbNode2)
+{
+ NS_LOG_FUNCTION (this);
+ NS_LOG_INFO ("setting up the X2 interface");
+
+ m_epcHelper->AddX2Interface (enbNode1, enbNode2);
+}
+
+void
+LteTapHelper::HandoverRequest (Time hoTime, Ptr<NetDevice> ueDev, Ptr<NetDevice> sourceEnbDev, Ptr<NetDevice> targetEnbDev)
+{
+ NS_LOG_FUNCTION (this << ueDev << sourceEnbDev << targetEnbDev);
+ NS_ASSERT_MSG (m_epcHelper, "Handover requires the use of the EPC - did you forget to call LteTapHelper::SetEpcHelper () ?");
+ Simulator::Schedule (hoTime, &LteTapHelper::DoHandoverRequest, this, ueDev, sourceEnbDev, targetEnbDev);
+}
+
+void
+LteTapHelper::DoHandoverRequest (Ptr<NetDevice> ueDev, Ptr<NetDevice> sourceEnbDev, Ptr<NetDevice> targetEnbDev)
+{
+ NS_LOG_FUNCTION (this << ueDev << sourceEnbDev << targetEnbDev);
+
+ uint16_t targetCellId = targetEnbDev->GetObject<LteEnbNetDevice> ()->GetCellId ();
+ Ptr<LteEnbRrc> sourceRrc = sourceEnbDev->GetObject<LteEnbNetDevice> ()->GetRrc ();
+ uint16_t rnti = ueDev->GetObject<LteUeNetDevice> ()->GetRrc ()->GetRnti ();
+ sourceRrc->SendHandoverRequest (rnti, targetCellId);
+}
+
+void
+LteTapHelper::DeActivateDedicatedEpsBearer (Ptr<NetDevice> ueDevice,Ptr<NetDevice> enbDevice, uint8_t bearerId)
+{
+ NS_LOG_FUNCTION (this << ueDevice << bearerId);
+ NS_ASSERT_MSG (m_epcHelper != 0, "Dedicated EPS bearers cannot be de-activated when the EPC is not used");
+ NS_ASSERT_MSG (bearerId != 1, "Default bearer cannot be de-activated until and unless and UE is released");
+
+ DoDeActivateDedicatedEpsBearer (ueDevice, enbDevice, bearerId);
+}
+
+void
+LteTapHelper::DoDeActivateDedicatedEpsBearer (Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice, uint8_t bearerId)
+{
+ NS_LOG_FUNCTION (this << ueDevice << bearerId);
+
+ //Extract IMSI and rnti
+ uint64_t imsi = ueDevice->GetObject<LteUeNetDevice> ()->GetImsi ();
+ uint16_t rnti = ueDevice->GetObject<LteUeNetDevice> ()->GetRrc ()->GetRnti ();
+
+
+ Ptr<LteEnbRrc> enbRrc = enbDevice->GetObject<LteEnbNetDevice> ()->GetRrc ();
+
+ enbRrc->DoSendReleaseDataRadioBearer (imsi,rnti,bearerId);
+}
+
+
+void
+LteTapHelper::ActivateDataRadioBearer (NetDeviceContainer ueDevices, EpsBearer bearer)
+{
+ NS_LOG_FUNCTION (this);
+ for (NetDeviceContainer::Iterator i = ueDevices.Begin (); i != ueDevices.End (); ++i)
+ {
+ ActivateDataRadioBearer (*i, bearer);
+ }
+}
+
+void
+LteTapHelper::EnableLogComponents (void)
+{
+ LogComponentEnable ("LteTapHelper", LOG_LEVEL_ALL);
+ LogComponentEnable ("LteEnbRrc", LOG_LEVEL_ALL);
+ LogComponentEnable ("LteUeRrc", LOG_LEVEL_ALL);
+ LogComponentEnable ("LteEnbMac", LOG_LEVEL_ALL);
+ LogComponentEnable ("LteUeMac", LOG_LEVEL_ALL);
+ LogComponentEnable ("LteRlc", LOG_LEVEL_ALL);
+ LogComponentEnable ("LteRlcUm", LOG_LEVEL_ALL);
+ LogComponentEnable ("LteRlcAm", LOG_LEVEL_ALL);
+ LogComponentEnable ("RrFfMacScheduler", LOG_LEVEL_ALL);
+ LogComponentEnable ("PfFfMacScheduler", LOG_LEVEL_ALL);
+
+ LogComponentEnable ("LtePhy", LOG_LEVEL_ALL);
+ LogComponentEnable ("LteEnbPhy", LOG_LEVEL_ALL);
+ LogComponentEnable ("LteUePhy", LOG_LEVEL_ALL);
+ LogComponentEnable ("LteSpectrumValueHelper", LOG_LEVEL_ALL);
+ LogComponentEnable ("LteSpectrumPhy", LOG_LEVEL_ALL);
+ LogComponentEnable ("LteInterference", LOG_LEVEL_ALL);
+ LogComponentEnable ("LteChunkProcessor", LOG_LEVEL_ALL);
+
+ std::string propModelStr = m_dlPathlossModelFactory.GetTypeId ().GetName ().erase (0,5).c_str ();
+ LogComponentEnable ("LteNetDevice", LOG_LEVEL_ALL);
+ LogComponentEnable ("LteUeNetDevice", LOG_LEVEL_ALL);
+ LogComponentEnable ("LteEnbNetDevice", LOG_LEVEL_ALL);
+
+ LogComponentEnable ("RadioBearerStatsCalculator", LOG_LEVEL_ALL);
+ LogComponentEnable ("LteStatsCalculator", LOG_LEVEL_ALL);
+ LogComponentEnable ("MacStatsCalculator", LOG_LEVEL_ALL);
+ LogComponentEnable ("PhyTxStatsCalculator", LOG_LEVEL_ALL);
+ LogComponentEnable ("PhyRxStatsCalculator", LOG_LEVEL_ALL);
+ LogComponentEnable ("PhyStatsCalculator", LOG_LEVEL_ALL);
+
+
+}
+
+void
+LteTapHelper::EnableTraces (void)
+{
+ EnablePhyTraces ();
+ EnableMacTraces ();
+ EnableRlcTraces ();
+ EnablePdcpTraces ();
+}
+
+void
+LteTapHelper::EnableRlcTraces (void)
+{
+ NS_ASSERT_MSG (m_rlcStats == 0, "please make sure that LteTapHelper::EnableRlcTraces is called at most once");
+ m_rlcStats = CreateObject<RadioBearerStatsCalculator> ("RLC");
+ m_radioBearerStatsConnector.EnableRlcStats (m_rlcStats);
+}
+
+int64_t
+LteTapHelper::AssignStreams (NetDeviceContainer c, int64_t stream)
+{
+ int64_t currentStream = stream;
+ if ((m_fadingModule != 0) && (m_fadingStreamsAssigned == false))
+ {
+ Ptr<TraceFadingLossModel> tflm = m_fadingModule->GetObject<TraceFadingLossModel> ();
+ if (tflm != 0)
+ {
+ currentStream += tflm->AssignStreams (currentStream);
+ m_fadingStreamsAssigned = true;
+ }
+ }
+ Ptr<NetDevice> netDevice;
+ for (NetDeviceContainer::Iterator i = c.Begin (); i != c.End (); ++i)
+ {
+ netDevice = (*i);
+ Ptr<LteEnbNetDevice> lteEnb = DynamicCast<LteEnbNetDevice> (netDevice);
+ if (lteEnb)
+ {
+ Ptr<LteSpectrumPhy> dlPhy = lteEnb->GetPhy ()->GetDownlinkSpectrumPhy ();
+ Ptr<LteSpectrumPhy> ulPhy = lteEnb->GetPhy ()->GetUplinkSpectrumPhy ();
+ currentStream += dlPhy->AssignStreams (currentStream);
+ currentStream += ulPhy->AssignStreams (currentStream);
+ }
+ Ptr<LteUeNetDevice> lteUe = DynamicCast<LteUeNetDevice> (netDevice);
+ if (lteUe)
+ {
+ Ptr<LteSpectrumPhy> dlPhy = lteUe->GetPhy ()->GetDownlinkSpectrumPhy ();
+ Ptr<LteSpectrumPhy> ulPhy = lteUe->GetPhy ()->GetUplinkSpectrumPhy ();
+ Ptr<LteUeMac> ueMac = lteUe->GetMac ();
+ currentStream += dlPhy->AssignStreams (currentStream);
+ currentStream += ulPhy->AssignStreams (currentStream);
+ currentStream += ueMac->AssignStreams (currentStream);
+ }
+ }
+ return (currentStream - stream);
+}
+
+
+void
+LteTapHelper::EnablePhyTraces (void)
+{
+ EnableDlPhyTraces ();
+ EnableUlPhyTraces ();
+ EnableDlTxPhyTraces ();
+ EnableUlTxPhyTraces ();
+ EnableDlRxPhyTraces ();
+ EnableUlRxPhyTraces ();
+}
+
+void
+LteTapHelper::EnableTxPhyTraces (void)
+{
+ EnableDlTxPhyTraces ();
+ EnableUlTxPhyTraces ();
+}
+
+
+void
+LteTapHelper::NewEnableTxPhyTraces (void)
+{
+ NewEnableDlTxPhyTraces ();
+ NewEnableUlTxPhyTraces ();
+}
+void
+LteTapHelper::EnableDlTxPhyTraces (void)
+{
+ Config::Connect ("/NodeList/*/DeviceList/*/LteEnbPhy/DlPhyTransmission",
+ MakeBoundCallback (&PhyTxStatsCalculator::DlPhyTransmissionCallback, m_phyTxStats));
+}
+
+void
+LteTapHelper::EnableUlTxPhyTraces (void)
+{
+ Config::Connect ("/NodeList/*/DeviceList/*/LteUePhy/UlPhyTransmission",
+ MakeBoundCallback (&PhyTxStatsCalculator::UlPhyTransmissionCallback, m_phyTxStats));
+}
+
+void
+LteTapHelper::NewEnableUlTxPhyTraces(void)
+{
+ Config::Connect ("/NodeList/*/DeviceList/*/LteUePhy/UlPhyTransmission",
+ MakeCallback (&LteTapHelper::WriteUlPhyTransmissionMcsCallback, this));
+}
+
+void
+LteTapHelper::NewEnableDlTxPhyTraces(void)
+{
+ Config::Connect ("/NodeList/*/DeviceList/*/LteEnbPhy/DlPhyTransmission",
+ MakeCallback (&LteTapHelper::WriteDlPhyTransmissionMcsCallback, this));
+}
+
+void
+LteTapHelper::WriteDlPhyTransmissionMcsCallback(std::string path,
+ PhyTransmissionStatParameters params)
+{
+ NS_LOG_FUNCTION (params.m_cellId << params.m_imsi << params.m_timestamp << params.m_rnti << params.m_layer << params.m_mcs << params.m_size << params.m_rv << params.m_ndi);
+ if(m_dlMcsStats.node_id==-1)//new element
+ {
+ m_dlMcsStats.node_id=Mcs_stats::Get_node(path);
+ m_dlMcsStats.avgMcs=(double)(params.m_mcs);
+ // m_dlMcsStats.avgThroughput=Mcs_stats::ConnvertMcsToRate (params.m_mcs);
+ m_dlMcsStats.avgThroughput=(double)(params.m_size)/125*2;
+ } else {
+ NS_ASSERT( m_dlMcsStats.node_id==Mcs_stats::Get_node(path));
+ m_dlMcsStats.avgMcs=(double)(params.m_mcs)*(1-ALPHA)+m_dlMcsStats.avgMcs*ALPHA;
+ //m_dlMcsStats.avgThroughput=Mcs_stats::ConnvertMcsToRate (params.m_mcs)*(1-ALPHA)+m_dlMcsStats.avgThroughput;
+ m_dlMcsStats.avgThroughput=(double)(params.m_size)/125*2*(1-ALPHA)+m_dlMcsStats.avgThroughput*ALPHA;
+ }
+}
+
+void
+LteTapHelper::WriteUlPhyTransmissionMcsCallback(std::string path,
+ PhyTransmissionStatParameters params)
+{
+
+
+ NS_LOG_FUNCTION ( params.m_cellId << params.m_imsi << params.m_timestamp << params.m_rnti << params.m_layer << params.m_mcs << params.m_size << params.m_rv << params.m_ndi);
+
+ int nodeId=Mcs_stats::Get_node(path);
+ unsigned i;
+ for(i=0;i<m_ulAllMcsStats.size();i++){
+ if(nodeId==m_ulAllMcsStats.at(i).node_id)
+ break;
+ }
+
+ if(i==m_ulAllMcsStats.size())//new element
+ {
+ Mcs_stats newStats;
+ newStats.node_id=nodeId;
+ newStats.avgMcs=(double)(params.m_mcs);
+ // newStats.avgThroughput=Mcs_stats::ConnvertMcsToRate(params.m_mcs);
+ newStats.avgThroughput=(double)(params.m_size)/125*2; //Mbp/s
+ m_ulAllMcsStats.push_back(newStats);
+ } else {
+ m_ulAllMcsStats.at(i).avgMcs=(double)(params.m_mcs)*(1-ALPHA)+m_ulAllMcsStats.at(i).avgMcs*ALPHA;
+ // m_ulAllMcsStats.at(i).avgThroughput=Mcs_stats::ConnvertMcsToRate (params.m_mcs)*(1-ALPHA)+m_ulAllMcsStats.at(i).avgThroughput;
+ m_ulAllMcsStats.at(i).avgThroughput=(double)(params.m_size)/125*2*(1-ALPHA)+m_ulAllMcsStats.at(i).avgThroughput*ALPHA;
+ }
+
+
+}
+
+double
+LteTapHelper::GetLtePhyTxRate(int nodeId)
+{
+ if(m_dlMcsStats.node_id == nodeId)
+ return m_dlMcsStats.avgThroughput;
+
+ //it is an UE:
+ unsigned i;
+ for(i=0; i< m_ulAllMcsStats.size();i++)
+ {
+ if(m_ulAllMcsStats.at(i).node_id == nodeId)
+ return m_ulAllMcsStats.at(i).avgThroughput;
+ }
+
+ //bad things happened, did not find the station
+ std::cerr<<"LTE EMULATOR: WARNING: not find node with id="<<nodeId<<" either in downlink or uplink\n";
+ return -1;
+}
+
+void
+LteTapHelper::EnableDlRxPhyTraces (void)
+{
+ Config::Connect ("/NodeList/*/DeviceList/*/LteUePhy/DlSpectrumPhy/DlPhyReception",
+ MakeBoundCallback (&PhyRxStatsCalculator::DlPhyReceptionCallback, m_phyRxStats));
+}
+
+void
+LteTapHelper::EnableUlRxPhyTraces (void)
+{
+ Config::Connect ("/NodeList/*/DeviceList/*/LteEnbPhy/UlSpectrumPhy/UlPhyReception",
+ MakeBoundCallback (&PhyRxStatsCalculator::UlPhyReceptionCallback, m_phyRxStats));
+}
+
+
+void
+LteTapHelper::EnableMacTraces (void)
+{
+ EnableDlMacTraces ();
+ EnableUlMacTraces ();
+}
+
+
+void
+LteTapHelper::EnableDlMacTraces (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ Config::Connect ("/NodeList/*/DeviceList/*/LteEnbMac/DlScheduling",
+ MakeBoundCallback (&MacStatsCalculator::DlSchedulingCallback, m_macStats));
+}
+
+void
+LteTapHelper::EnableUlMacTraces (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ Config::Connect ("/NodeList/*/DeviceList/*/LteEnbMac/UlScheduling",
+ MakeBoundCallback (&MacStatsCalculator::UlSchedulingCallback, m_macStats));
+}
+
+void
+LteTapHelper::EnableDlPhyTraces (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ Config::Connect ("/NodeList/*/DeviceList/*/LteUePhy/ReportCurrentCellRsrpSinr",
+ MakeBoundCallback (&PhyStatsCalculator::ReportCurrentCellRsrpSinrCallback, m_phyStats));
+}
+
+void
+LteTapHelper::EnableUlPhyTraces (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ Config::Connect ("/NodeList/*/DeviceList/*/LteEnbPhy/ReportUeSinr",
+ MakeBoundCallback (&PhyStatsCalculator::ReportUeSinr, m_phyStats));
+ Config::Connect ("/NodeList/*/DeviceList/*/LteEnbPhy/ReportInterference",
+ MakeBoundCallback (&PhyStatsCalculator::ReportInterference, m_phyStats));
+
+}
+
+Ptr<RadioBearerStatsCalculator>
+LteTapHelper::GetRlcStats (void)
+{
+ return m_rlcStats;
+}
+
+void
+LteTapHelper::EnablePdcpTraces (void)
+{
+ NS_ASSERT_MSG (m_pdcpStats == 0, "please make sure that LteTapHelper::EnablePdcpTraces is called at most once");
+ m_pdcpStats = CreateObject<RadioBearerStatsCalculator> ("PDCP");
+ m_radioBearerStatsConnector.EnablePdcpStats (m_pdcpStats);
+}
+
+Ptr<RadioBearerStatsCalculator>
+LteTapHelper::GetPdcpStats (void)
+{
+ return m_pdcpStats;
+}
+
+} // namespace ns3