diff options
Diffstat (limited to 'emu-radio/lte-emulator/extensions/lte-tap-helper.cc')
-rw-r--r-- | emu-radio/lte-emulator/extensions/lte-tap-helper.cc | 1350 |
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 |