summaryrefslogtreecommitdiffstats
path: root/emu-radio/lte-emulator/extensions
diff options
context:
space:
mode:
authorJordan Augé <jordan.auge+fdio@email.com>2017-02-24 14:58:01 +0100
committerJordan Augé <jordan.auge+fdio@cisco.com>2017-02-24 18:36:29 +0000
commit85a341d645b57b7cd88a26ed2ea0a314704240ea (patch)
treebdda2b35003aae20103a796f86daced160b8a730 /emu-radio/lte-emulator/extensions
parent9b30fc10fb1cbebe651e5a107e8ca5b24de54675 (diff)
Initial commit: vICN
Change-Id: I7ce66c4e84a6a1921c63442f858b49e083adc7a7 Signed-off-by: Jordan Augé <jordan.auge+fdio@cisco.com>
Diffstat (limited to 'emu-radio/lte-emulator/extensions')
-rw-r--r--emu-radio/lte-emulator/extensions/README.md18
-rw-r--r--emu-radio/lte-emulator/extensions/lte-tap-helper.cc1350
-rw-r--r--emu-radio/lte-emulator/extensions/lte-tap-helper.h807
-rw-r--r--emu-radio/lte-emulator/extensions/lte-tap-ue-net-device.cc150
-rw-r--r--emu-radio/lte-emulator/extensions/lte-tap-ue-net-device.h71
-rw-r--r--emu-radio/lte-emulator/extensions/tap-point-to-point-epc-helper.cc360
-rw-r--r--emu-radio/lte-emulator/extensions/tap-point-to-point-epc-helper.h176
7 files changed, 2932 insertions, 0 deletions
diff --git a/emu-radio/lte-emulator/extensions/README.md b/emu-radio/lte-emulator/extensions/README.md
new file mode 100644
index 00000000..7663ba08
--- /dev/null
+++ b/emu-radio/lte-emulator/extensions/README.md
@@ -0,0 +1,18 @@
+The extensions are basically either some rewriting or some inheriting
+of existing classes in ns3 such that the emulation of lte channel in ns3
+can be enabled.
+
+some of the original lte helper and lte network device implementation
+does not support the integration with tap devices defined in ns3. So some
+critical extensions or modifications of those imlementations must be done
+in order to enable lte channel emulation in ns3.
+
+To avoid making changes directly on the ns3 codebase, which may lead to needs
+of recompiling ns3 library and other packages depending on ns3, here all the
+modifications or extensions are implemented by rewriting or inheriting of existing
+ns3 class. These extensions shall be linked with lte emulator program and
+ns3 library such that those critical modifications can take into play when running
+lte emulator program.
+
+Since all those modifications are for purpose of enabling integration lte network
+with tap device in ns3, all the extension files/classes have "tap" in their namings.
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
diff --git a/emu-radio/lte-emulator/extensions/lte-tap-helper.h b/emu-radio/lte-emulator/extensions/lte-tap-helper.h
new file mode 100644
index 00000000..829672c8
--- /dev/null
+++ b/emu-radio/lte-emulator/extensions/lte-tap-helper.h
@@ -0,0 +1,807 @@
+/*
+ * 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.
+ */
+
+#ifndef LTE_TAP_HELPER_H
+#define LTE_TAP_HELPER_H
+
+#include <ns3/config.h>
+#include <ns3/simulator.h>
+#include <ns3/names.h>
+#include <ns3/net-device.h>
+#include <ns3/net-device-container.h>
+#include <ns3/node.h>
+#include <ns3/node-container.h>
+#include <ns3/eps-bearer.h>
+#include <ns3/phy-stats-calculator.h>
+#include <ns3/phy-tx-stats-calculator.h>
+#include <ns3/phy-rx-stats-calculator.h>
+#include <ns3/mac-stats-calculator.h>
+#include <ns3/radio-bearer-stats-calculator.h>
+#include <ns3/radio-bearer-stats-connector.h>
+#include <ns3/epc-tft.h>
+#include <ns3/mobility-model.h>
+
+#include <vector>
+
+/**
+ * \brief this file has been modified from the original one in ns3 lte module to support emulation of LTE channel, more specifically to support tap device functionality
+ */
+
+
+namespace ns3 {
+
+
+class LteUePhy;
+class LteEnbPhy;
+class SpectrumChannel;
+class EpcHelper;
+class PropagationLossModel;
+class SpectrumPropagationLossModel;
+
+/**
+ * \ingroup lte
+ *
+ * Creation and configuration of LTE entities. One LteHelper instance is
+ * typically enough for an LTE simulation. To create it:
+ *
+ * Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
+ *
+ * The general responsibility of the helper is to create various LTE objects
+ * and arrange them together to make the whole LTE system. The overall
+ * arrangement would look like the following:
+ * - Downlink spectrum channel
+ * + Path loss model
+ * + Fading model
+ * - Uplink spectrum channel
+ * + Path loss model
+ * + Fading model
+ * - eNodeB node(s)
+ * + Mobility model
+ * + eNodeB device(s)
+ * * Antenna model
+ * * eNodeB PHY (includes spectrum PHY, interference model, HARQ model)
+ * * eNodeB MAC
+ * * eNodeB RRC (includes RRC protocol)
+ * * Scheduler
+ * * Handover algorithm
+ * * FFR (frequency reuse) algorithm
+ * * ANR (automatic neighbour relation)
+ * + EPC related models (EPC application, Internet stack, X2 interface)
+ * - UE node(s)
+ * + Mobility model
+ * + UE device(s)
+ * * Antenna model
+ * * UE PHY (includes spectrum PHY, interference model, HARQ model)
+ * * UE MAC
+ * * UE RRC (includes RRC protocol)
+ * * NAS
+ * - EPC helper
+ * - Various statistics calculator objects
+ *
+ * Spetrum channels are created automatically: one for DL, and one for UL.
+ * eNodeB devices are created by calling InstallEnbDevice(), while UE devices
+ * are created by calling InstallUeDevice(). EPC helper can be set by using
+ * SetEpcHelper().
+ */
+class LteTapHelper : public Object
+{
+public:
+ LteTapHelper (void);
+ virtual ~LteTapHelper (void);
+ //for lurch output
+ double GetLtePhyTxRate (int nodeId);
+
+ /**
+ * Register this type.
+ * \return The object TypeId.
+ */
+ static TypeId GetTypeId (void);
+ virtual void DoDispose (void);
+
+ /**
+ * Set the EpcHelper to be used to setup the EPC network in
+ * conjunction with the setup of the LTE radio access network.
+ *
+ * \note if no EpcHelper is ever set, then LteHelper will default
+ * to creating an LTE-only simulation with no EPC, using LteRlcSm as
+ * the RLC model, and without supporting any IP networking. In other
+ * words, it will be a radio-level simulation involving only LTE PHY
+ * and MAC and the FF Scheduler, with a saturation traffic model for
+ * the RLC.
+ *
+ * \param h a pointer to the EpcHelper to be used
+ */
+ void SetEpcHelper (Ptr<EpcHelper> h);
+
+ /**
+ * Set the type of path loss model to be used for both DL and UL channels.
+ *
+ * \param type type of path loss model, must be a type name of any class
+ * inheriting from ns3::PropagationLossModel, for example:
+ * "ns3::FriisPropagationLossModel"
+ */
+ void SetPathlossModelType (std::string type);
+
+ /**
+ * Set an attribute for the path loss models to be created.
+ *
+ * \param n the name of the attribute
+ * \param v the value of the attribute
+ */
+ void SetPathlossModelAttribute (std::string n, const AttributeValue &v);
+
+ /**
+ * Set the type of scheduler to be used by eNodeB devices.
+ *
+ * \param type type of scheduler, must be a type name of any class
+ * inheriting from ns3::FfMacScheduler, for example:
+ * "ns3::PfFfMacScheduler"
+ *
+ * Equivalent with setting the `Scheduler` attribute.
+ */
+ void SetSchedulerType (std::string type);
+
+ /**
+ *
+ * \return the scheduler type
+ */
+ std::string GetSchedulerType () const;
+
+ /**
+ * Set an attribute for the scheduler to be created.
+ *
+ * \param n the name of the attribute
+ * \param v the value of the attribute
+ */
+ void SetSchedulerAttribute (std::string n, const AttributeValue &v);
+
+ /**
+ * Set the type of FFR algorithm to be used by eNodeB devices.
+ *
+ * \param type type of FFR algorithm, must be a type name of any class
+ * inheriting from ns3::LteFfrAlgorithm, for example:
+ * "ns3::LteFrNoOpAlgorithm"
+ *
+ * Equivalent with setting the `FfrAlgorithm` attribute.
+ */
+ void SetFfrAlgorithmType (std::string type);
+
+ /**
+ *
+ * \return the FFR algorithm type
+ */
+ std::string GetFfrAlgorithmType () const;
+
+ /**
+ * Set an attribute for the FFR algorithm to be created.
+ *
+ * \param n the name of the attribute
+ * \param v the value of the attribute
+ */
+ void SetFfrAlgorithmAttribute (std::string n, const AttributeValue &v);
+
+ /**
+ * Set the type of handover algorithm to be used by eNodeB devices.
+ *
+ * \param type type of handover algorithm, must be a type name of any class
+ * inheriting from ns3::LteHandoverAlgorithm, for example:
+ * "ns3::NoOpHandoverAlgorithm"
+ *
+ * Equivalent with setting the `HandoverAlgorithm` attribute.
+ */
+ void SetHandoverAlgorithmType (std::string type);
+
+ /**
+ *
+ * \return the handover algorithm type
+ */
+ std::string GetHandoverAlgorithmType () const;
+
+ /**
+ * Set an attribute for the handover algorithm to be created.
+ *
+ * \param n the name of the attribute
+ * \param v the value of the attribute
+ */
+ void SetHandoverAlgorithmAttribute (std::string n, const AttributeValue &v);
+
+ /**
+ * Set an attribute for the eNodeB devices (LteEnbNetDevice) to be created.
+ *
+ * \param n the name of the attribute.
+ * \param v the value of the attribute
+ */
+ void SetEnbDeviceAttribute (std::string n, const AttributeValue &v);
+
+ /**
+ * Set the type of antenna model to be used by eNodeB devices.
+ *
+ * \param type type of antenna model, must be a type name of any class
+ * inheriting from ns3::AntennaModel, for example:
+ * "ns3::IsotropicAntennaModel"
+ */
+ void SetEnbAntennaModelType (std::string type);
+
+ /**
+ * Set an attribute for the eNodeB antenna model to be created.
+ *
+ * \param n the name of the attribute.
+ * \param v the value of the attribute
+ */
+ void SetEnbAntennaModelAttribute (std::string n, const AttributeValue &v);
+
+ /**
+ * Set an attribute for the UE devices (LteUeNetDevice) to be created.
+ *
+ * \param n the name of the attribute.
+ * \param v the value of the attribute
+ */
+ void SetUeDeviceAttribute (std::string n, const AttributeValue &v);
+
+ /**
+ * Set the type of antenna model to be used by UE devices.
+ *
+ * \param type type of antenna model, must be a type name of any class
+ * inheriting from ns3::AntennaModel, for example:
+ * "ns3::IsotropicAntennaModel"
+ */
+ void SetUeAntennaModelType (std::string type);
+
+ /**
+ * Set an attribute for the UE antenna model to be created.
+ *
+ * \param n the name of the attribute
+ * \param v the value of the attribute
+ */
+ void SetUeAntennaModelAttribute (std::string n, const AttributeValue &v);
+
+ /**
+ * Set the type of spectrum channel to be used in both DL and UL.
+ *
+ * \param type type of spectrum channel model, must be a type name of any
+ * class inheriting from ns3::SpectrumChannel, for example:
+ * "ns3::MultiModelSpectrumChannel"
+ */
+ void SetSpectrumChannelType (std::string type);
+
+ /**
+ * Set an attribute for the spectrum channel to be created (both DL and UL).
+ *
+ * \param n the name of the attribute
+ * \param v the value of the attribute
+ */
+ void SetSpectrumChannelAttribute (std::string n, const AttributeValue &v);
+
+ /**
+ * Create a set of eNodeB devices.
+ *
+ * \param c the node container where the devices are to be installed
+ * \return the NetDeviceContainer with the newly created devices
+ */
+ NetDeviceContainer InstallEnbDevice (NodeContainer c);
+
+ /**
+ * Create a set of UE devices.
+ *
+ * \param c the node container where the devices are to be installed
+ * \return the NetDeviceContainer with the newly created devices
+ */
+ NetDeviceContainer InstallUeDevice (NodeContainer c);
+
+ /**
+ * \brief Enables automatic attachment of a set of UE devices to a suitable
+ * cell using Idle mode initial cell selection procedure.
+ * \param ueDevices the set of UE devices to be attached
+ *
+ * By calling this, the UE will start the initial cell selection procedure at
+ * the beginning of simulation. In addition, the function also instructs each
+ * UE to immediately enter CONNECTED mode and activates the default EPS
+ * bearer.
+ *
+ * If this function is called when the UE is in a situation where entering
+ * CONNECTED mode is not possible (e.g. before the simulation begin), then the
+ * UE will attempt to connect at the earliest possible time (e.g. after it
+ * camps to a suitable cell).
+ *
+ * Note that this function can only be used in EPC-enabled simulation.
+ */
+ void Attach (NetDeviceContainer ueDevices);
+
+ /**
+ * \brief Enables automatic attachment of a UE device to a suitable cell
+ * using Idle mode initial cell selection procedure.
+ * \param ueDevice the UE device to be attached
+ *
+ * By calling this, the UE will start the initial cell selection procedure at
+ * the beginning of simulation. In addition, the function also instructs the
+ * UE to immediately enter CONNECTED mode and activates the default EPS
+ * bearer.
+ *
+ * If this function is called when the UE is in a situation where entering
+ * CONNECTED mode is not possible (e.g. before the simulation begin), then the
+ * UE will attempt to connect at the earliest possible time (e.g. after it
+ * camps to a suitable cell).
+ *
+ * Note that this function can only be used in EPC-enabled simulation.
+ */
+ void Attach (Ptr<NetDevice> ueDevice);
+
+ /**
+ * \brief Manual attachment of a set of UE devices to the network via a given
+ * eNodeB.
+ * \param ueDevices the set of UE devices to be attached
+ * \param enbDevice the destination eNodeB device
+ *
+ * In addition, the function also instructs each UE to immediately enter
+ * CONNECTED mode and activates the default EPS bearer.
+ *
+ * The function can be used in both LTE-only and EPC-enabled simulations.
+ * Note that this function will disable Idle mode initial cell selection
+ * procedure.
+ */
+ void Attach (NetDeviceContainer ueDevices, Ptr<NetDevice> enbDevice);
+
+ /**
+ * \brief Manual attachment of a UE device to the network via a given eNodeB.
+ * \param ueDevice the UE device to be attached
+ * \param enbDevice the destination eNodeB device
+ *
+ * In addition, the function also instructs the UE to immediately enter
+ * CONNECTED mode and activates the default EPS bearer.
+ *
+ * The function can be used in both LTE-only and EPC-enabled simulations.
+ * Note that this function will disable Idle mode initial cell selection
+ * procedure.
+ */
+ void Attach (Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice);
+
+ /**
+ * \brief Manual attachment of a set of UE devices to the network via the
+ * closest eNodeB (with respect to distance) among those in the set.
+ * \param ueDevices the set of UE devices to be attached
+ * \param enbDevices the set of eNodeB devices to be considered
+ *
+ * This function finds among the eNodeB set the closest eNodeB for each UE,
+ * and then invokes manual attachment between the pair.
+ *
+ * Users are encouraged to use automatic attachment (Idle mode cell selection)
+ * instead of this function.
+ *
+ * \sa LteHelper::Attach(NetDeviceContainer ueDevices);
+ */
+ void AttachToClosestEnb (NetDeviceContainer ueDevices, NetDeviceContainer enbDevices);
+
+ /**
+ * \brief Manual attachment of a UE device to the network via the closest
+ * eNodeB (with respect to distance) among those in the set.
+ * \param ueDevice the UE device to be attached
+ * \param enbDevices the set of eNodeB devices to be considered
+ *
+ * This function finds among the eNodeB set the closest eNodeB for the UE,
+ * and then invokes manual attachment between the pair.
+ *
+ * Users are encouraged to use automatic attachment (Idle mode cell selection)
+ * instead of this function.
+ *
+ * \sa LteHelper::Attach(Ptr<NetDevice> ueDevice);
+ */
+ void AttachToClosestEnb (Ptr<NetDevice> ueDevice, NetDeviceContainer enbDevices);
+
+ /**
+ * Activate a dedicated EPS bearer on a given set of UE devices.
+ *
+ * \param ueDevices the set of UE devices
+ * \param bearer the characteristics of the bearer to be activated
+ * \param tft the Traffic Flow Template that identifies the traffic to go on this bearer
+ */
+ uint8_t ActivateDedicatedEpsBearer (NetDeviceContainer ueDevices, EpsBearer bearer, Ptr<EpcTft> tft);
+
+ /**
+ * Activate a dedicated EPS bearer on a given UE device.
+ *
+ * \param ueDevice the UE device
+ * \param bearer the characteristics of the bearer to be activated
+ * \param tft the Traffic Flow Template that identifies the traffic to go on this bearer.
+ */
+ uint8_t ActivateDedicatedEpsBearer (Ptr<NetDevice> ueDevice, EpsBearer bearer, Ptr<EpcTft> tft);
+
+ /**
+ * \brief Manually trigger dedicated bearer de-activation at specific simulation time
+ * \param ueDevice the UE on which dedicated bearer to be de-activated must be of the type LteUeNetDevice
+ * \param enbDevice eNB, must be of the type LteEnbNetDevice
+ * \param bearerId Bearer Identity which is to be de-activated
+ *
+ * \warning Requires the use of EPC mode. See SetEpcHelper() method.
+ */
+
+ void DeActivateDedicatedEpsBearer (Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice, uint8_t bearerId);
+ /**
+ * Create an X2 interface between all the eNBs in a given set.
+ *
+ * \param enbNodes the set of eNB nodes
+ */
+ void AddX2Interface (NodeContainer enbNodes);
+
+ /**
+ * Create an X2 interface between two eNBs.
+ *
+ * \param enbNode1 one eNB of the X2 interface
+ * \param enbNode2 the other eNB of the X2 interface
+ */
+ void AddX2Interface (Ptr<Node> enbNode1, Ptr<Node> enbNode2);
+
+ /**
+ * Manually trigger an X2-based handover.
+ *
+ * \param hoTime when the handover shall be initiated
+ * \param ueDev the UE that hands off, must be of the type LteUeNetDevice
+ * \param sourceEnbDev source eNB, must be of the type LteEnbNetDevice
+ * (originally the UE is attached to this eNB)
+ * \param targetEnbDev target eNB, must be of the type LteEnbNetDevice
+ * (the UE would be connected to this eNB after the
+ * handover)
+ *
+ * \warning Requires the use of EPC mode. See SetEpcHelper() method
+ */
+ void HandoverRequest (Time hoTime, Ptr<NetDevice> ueDev,
+ Ptr<NetDevice> sourceEnbDev, Ptr<NetDevice> targetEnbDev);
+
+
+ /**
+ * Activate a Data Radio Bearer on a given UE devices (for LTE-only simulation).
+ *
+ * \param ueDevices the set of UE devices
+ * \param bearer the characteristics of the bearer to be activated
+ */
+ void ActivateDataRadioBearer (NetDeviceContainer ueDevices, EpsBearer bearer);
+
+ /**
+ * Activate a Data Radio Bearer on a UE device (for LTE-only simulation).
+ * This method will schedule the actual activation
+ * the bearer so that it happens after the UE got connected.
+ *
+ * \param ueDevice the UE device
+ * \param bearer the characteristics of the bearer to be activated
+ */
+ void ActivateDataRadioBearer (Ptr<NetDevice> ueDevice, EpsBearer bearer);
+
+ /**
+ * Set the type of fading model to be used in both DL and UL.
+ *
+ * \param type type of fading model, must be a type name of any class
+ * inheriting from ns3::SpectrumPropagationLossModel, for
+ * example: "ns3::TraceFadingLossModel"
+ */
+ void SetFadingModel (std::string type);
+
+ /**
+ * Set an attribute for the fading model to be created (both DL and UL).
+ *
+ * \param n the name of the attribute
+ * \param v the value of the attribute
+ */
+ void SetFadingModelAttribute (std::string n, const AttributeValue &v);
+
+ /**
+ * Enables full-blown logging for major components of the LENA architecture.
+ */
+ void EnableLogComponents (void);
+
+ /**
+ * Enables trace sinks for PHY, MAC, RLC and PDCP. To make sure all nodes are
+ * traced, traces should be enabled once all UEs and eNodeBs are in place and
+ * connected, just before starting the simulation.
+ */
+ void EnableTraces (void);
+
+ /**
+ * Enable trace sinks for PHY layer.
+ */
+ void EnablePhyTraces (void);
+
+ /**
+ * NOTE: for lurch, added to only enable physical layer transmission traces only in order to track the mcs used by physical layer.
+ */
+ void EnableTxPhyTraces(void);
+
+ /**
+ * NOTE:for lurch, added to only enable physical layer transmission traces only and making time average
+ */
+ void NewEnableTxPhyTraces(void);
+
+ /**
+ * Enable trace sinks for DL PHY layer.
+ */
+ void EnableDlPhyTraces (void);
+
+ /**
+ * Enable trace sinks for UL PHY layer.
+ */
+ void EnableUlPhyTraces (void);
+
+ /**
+ * Enable trace sinks for DL transmission PHY layer.
+ */
+ void EnableDlTxPhyTraces (void);
+
+ /**
+ * Enable trace sinks for UL transmission PHY layer.
+ */
+ void EnableUlTxPhyTraces (void);
+
+ /**
+ * Enable trace sinks for DL reception PHY layer.
+ */
+ void EnableDlRxPhyTraces (void);
+
+ /**
+ * Enable trace sinks for UL reception PHY layer.
+ */
+ void EnableUlRxPhyTraces (void);
+
+ /**
+ * Enable trace sinks for MAC layer.
+ */
+ void EnableMacTraces (void);
+
+ /**
+ * Enable trace sinks for DL MAC layer.
+ */
+ void EnableDlMacTraces (void);
+
+ /**
+ * Enable trace sinks for UL MAC layer.
+ */
+ void EnableUlMacTraces (void);
+
+ /**
+ * Enable trace sinks for RLC layer.
+ */
+ void EnableRlcTraces (void);
+
+ /**
+ *
+ * \return the RLC stats calculator object
+ */
+ Ptr<RadioBearerStatsCalculator> GetRlcStats (void);
+
+ /**
+ * Enable trace sinks for PDCP layer
+ */
+ void EnablePdcpTraces (void);
+
+ /**
+ *
+ * \return the PDCP stats calculator object
+ */
+ Ptr<RadioBearerStatsCalculator> GetPdcpStats (void);
+
+ /**
+ * Assign a fixed random variable stream number to the random variables used.
+ *
+ * The InstallEnbDevice() or InstallUeDevice method should have previously
+ * been called by the user on the given devices.
+ *
+ * If TraceFadingLossModel has been set as the fading model type, this method
+ * will also assign a stream number to it, if none has been assigned before.
+ *
+ * \param c NetDeviceContainer of the set of net devices for which the
+ * LteNetDevice should be modified to use a fixed stream
+ * \param stream first stream index to use
+ * \return the number of stream indices (possibly zero) that have been assigned
+ */
+ int64_t AssignStreams (NetDeviceContainer c, int64_t stream);
+
+protected:
+ // inherited from Object
+ virtual void DoInitialize (void);
+
+private:
+ /**
+ * Create an eNodeB device (LteEnbNetDevice) on the given node.
+ * \param n the node where the device is to be installed
+ * \return pointer to the created device
+ */
+ Ptr<NetDevice> InstallSingleEnbDevice (Ptr<Node> n);
+
+ /**
+ * Create a UE device (LteUeNetDevice) on the given node
+ * \param n the node where the device is to be installed
+ * \return pointer to the created device
+ */
+ Ptr<NetDevice> InstallSingleUeDevice (Ptr<Node> n);
+
+ /**
+ * The actual function to trigger a manual handover.
+ * \param ueDev the UE that hands off, must be of the type LteUeNetDevice
+ * \param sourceEnbDev source eNB, must be of the type LteEnbNetDevice
+ * (originally the UE is attached to this eNB)
+ * \param targetEnbDev target eNB, must be of the type LteEnbNetDevice
+ * (the UE would be connected to this eNB after the
+ * handover)
+ *
+ * This method is normally scheduled by HandoverRequest() to run at a specific
+ * time where a manual handover is desired by the simulation user.
+ */
+ void DoHandoverRequest (Ptr<NetDevice> ueDev,
+ Ptr<NetDevice> sourceEnbDev,
+ Ptr<NetDevice> targetEnbDev);
+
+
+ /**
+ * \brief The actual function to trigger a manual bearer de-activation
+ * \param ueDevice the UE on which bearer to be de-activated must be of the type LteUeNetDevice
+ * \param enbDevice eNB, must be of the type LteEnbNetDevice
+ * \param bearerId Bearer Identity which is to be de-activated
+ *
+ * This method is normally scheduled by DeActivateDedicatedEpsBearer() to run at a specific
+ * time when a manual bearer de-activation is desired by the simulation user.
+ */
+ void DoDeActivateDedicatedEpsBearer (Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice, uint8_t bearerId);
+
+ /// The downlink LTE channel used in the simulation.
+ Ptr<SpectrumChannel> m_downlinkChannel;
+ /// The uplink LTE channel used in the simulation.
+ Ptr<SpectrumChannel> m_uplinkChannel;
+ /// The path loss model used in the downlink channel.
+ Ptr<Object> m_downlinkPathlossModel;
+ /// The path loss model used in the uplink channel.
+ Ptr<Object> m_uplinkPathlossModel;
+
+ /// Factory of MAC scheduler object.
+ ObjectFactory m_schedulerFactory;
+ /// Factory of FFR (frequency reuse) algorithm object.
+ ObjectFactory m_ffrAlgorithmFactory;
+ /// Factory of handover algorithm object.
+ ObjectFactory m_handoverAlgorithmFactory;
+ /// Factory of LteEnbNetDevice objects.
+ ObjectFactory m_enbNetDeviceFactory;
+ /// Factory of antenna object for eNodeB.
+ ObjectFactory m_enbAntennaModelFactory;
+ /// Factory for LteUeNetDevice objects.
+ ObjectFactory m_ueNetDeviceFactory;
+ /// Factory of antenna object for UE.
+ ObjectFactory m_ueAntennaModelFactory;
+ /// Factory of path loss model object for the downlink channel.
+ ObjectFactory m_dlPathlossModelFactory;
+ /// Factory of path loss model object for the uplink channel.
+ ObjectFactory m_ulPathlossModelFactory;
+ /// Factory of both the downlink and uplink LTE channels.
+ ObjectFactory m_channelFactory;
+
+ /// Name of fading model type, e.g., "ns3::TraceFadingLossModel".
+ std::string m_fadingModelType;
+ /// Factory of fading model object for both the downlink and uplink channels.
+ ObjectFactory m_fadingModelFactory;
+ /// The fading model used in both the downlink and uplink channels.
+ Ptr<SpectrumPropagationLossModel> m_fadingModule;
+ /**
+ * True if a random variable stream number has been assigned for the fading
+ * model. Used to prevent such assignment to be done more than once.
+ */
+ bool m_fadingStreamsAssigned;
+
+ /// Container of PHY layer statistics.
+ Ptr<PhyStatsCalculator> m_phyStats;
+ /// Container of PHY layer statistics related to transmission.
+ Ptr<PhyTxStatsCalculator> m_phyTxStats;
+ /// Container of PHY layer statistics related to reception.
+ Ptr<PhyRxStatsCalculator> m_phyRxStats;
+ /// Container of MAC layer statistics.
+ Ptr<MacStatsCalculator> m_macStats;
+ /// Container of RLC layer statistics.
+ Ptr<RadioBearerStatsCalculator> m_rlcStats;
+ /// Container of PDCP layer statistics.
+ Ptr<RadioBearerStatsCalculator> m_pdcpStats;
+ /// Connects RLC and PDCP statistics containers to appropriate trace sources
+ RadioBearerStatsConnector m_radioBearerStatsConnector;
+
+ /**
+ * Helper which provides implementation of core network. Initially empty
+ * (i.e., LTE-only simulation without any core network) and then might be
+ * set using SetEpcHelper().
+ */
+ Ptr<EpcHelper> m_epcHelper;
+
+ /**
+ * Keep track of the number of IMSI allocated. Increases by one every time a
+ * new UE is installed (by InstallSingleUeDevice()). The first UE will have
+ * an IMSI of 1. The maximum number of UE is 2^64 (~4.2e9).
+ */
+ uint64_t m_imsiCounter;
+ /**
+ * Keep track of the number of cell ID allocated. Increases by one every time
+ * a new eNodeB is installed (by InstallSingleEnbDevice()). The first eNodeB
+ * will have a cell ID of 1. The maximum number of eNodeB is 65535.
+ */
+ uint16_t m_cellIdCounter;
+
+ /**
+ * The `UseIdealRrc` attribute. If true, LteRrcProtocolIdeal will be used for
+ * RRC signaling. If false, LteRrcProtocolReal will be used.
+ */
+ bool m_useIdealRrc;
+ /**
+ * The `AnrEnabled` attribute. Activate or deactivate Automatic Neighbour
+ * Relation function.
+ */
+ bool m_isAnrEnabled;
+ /**
+ * The `UsePdschForCqiGeneration` attribute. 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.
+ */
+ bool m_usePdschForCqiGeneration;
+
+ /////////////////////////////////////////////////////////////////////////////////////////////
+ // for communicating statistics to lurch //
+ /////////////////////////////////////////////////////////////////////////////////////////////
+ void WriteUlPhyTransmissionMcsCallback(std::string path, PhyTransmissionStatParameters params);
+ void WriteDlPhyTransmissionMcsCallback(std::string path, PhyTransmissionStatParameters params);
+
+private:
+
+ //added for lurch
+ void
+ NewEnableUlTxPhyTraces (void);
+
+ void
+ NewEnableDlTxPhyTraces (void);
+ //end
+
+ struct Mcs_stats{
+ Mcs_stats()
+ :avgMcs (0.0)
+ ,avgThroughput (0.0)
+ ,node_id (-1)
+ {}
+
+ static
+ int ConnvertMcsToRate(int mcs)
+ {
+ return 1;
+ }
+
+ /*get node id from the config path*/
+ static
+ int Get_node(std::string path)
+ {
+ size_t pos1=0, pos2=0;
+ pos1 = path.find ("/",pos1);
+ pos1 = path.find ("/",pos1+1);
+ pos2 = path.find ("/",pos1+1);
+ return atoi (path.substr (pos1+1,pos2-(pos1+1)).c_str());
+ }
+
+ double avgMcs;
+ double avgThroughput;
+ int node_id;
+ };
+
+ /// downlink Tx mcs statistics
+ Mcs_stats m_dlMcsStats;
+
+ ///uplink Tx mcs statistics
+ std::vector<Mcs_stats> m_ulAllMcsStats;
+
+
+}; // end of `class LteHelper`
+
+
+} // namespace ns3
+
+
+
+#endif // LTE_HELPER_H
diff --git a/emu-radio/lte-emulator/extensions/lte-tap-ue-net-device.cc b/emu-radio/lte-emulator/extensions/lte-tap-ue-net-device.cc
new file mode 100644
index 00000000..1d858f57
--- /dev/null
+++ b/emu-radio/lte-emulator/extensions/lte-tap-ue-net-device.cc
@@ -0,0 +1,150 @@
+/*
+ * 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-ue-net-device.h"
+
+#include <ns3/llc-snap-header.h>
+#include <ns3/simulator.h>
+#include <ns3/callback.h>
+#include <ns3/node.h>
+#include <ns3/packet.h>
+#include <ns3/lte-net-device.h>
+#include <ns3/packet-burst.h>
+#include <ns3/uinteger.h>
+#include <ns3/trace-source-accessor.h>
+#include <ns3/pointer.h>
+#include <ns3/enum.h>
+#include <ns3/lte-amc.h>
+#include <ns3/ipv4-header.h>
+#include <ns3/lte-radio-bearer-tag.h>
+#include <ns3/ipv4-l3-protocol.h>
+#include <ns3/log.h>
+
+//NOTE: this is used to handle the arp request. actually this is an hack
+#include <ns3/arp-l3-protocol.h>
+#include <ns3/arp-header.h>
+
+#include <ns3/lte-enb-net-device.h>
+
+/**
+ * \brief LteTapUeNetDevice class extends lteUeNetDevice class to support emulation of lte channel
+ */
+
+namespace ns3 {
+NS_LOG_COMPONENT_DEFINE ("LteTapUeNetDevice");
+
+NS_OBJECT_ENSURE_REGISTERED ( LteTapUeNetDevice);
+
+////////////////////////////////
+// LteTapUeNetDevice
+////////////////////////////////
+
+TypeId LteTapUeNetDevice::GetTypeId (void)
+{
+ static TypeId
+ tid =
+ TypeId ("ns3::LteTapUeNetDevice")
+
+ .SetParent<LteUeNetDevice> ()
+ .AddConstructor<LteTapUeNetDevice>()
+ ;
+ return tid;
+}
+
+LteTapUeNetDevice::LteTapUeNetDevice()
+ : m_virtualAddress(Mac48Address::Allocate())
+{
+
+}
+
+
+void
+LteTapUeNetDevice::SetPromiscReceiveCallback (PromiscReceiveCallback cb)
+{
+ NS_LOG_FUNCTION (this);
+// NS_LOG_WARN ("Promisc mode not supported");
+
+ /** NOTE: set the promisc callback to be compatable with tap bridge
+ */
+ m_promiscRx = cb;
+}
+
+
+void
+LteTapUeNetDevice::Receive (Ptr<Packet> p)
+{
+ NS_LOG_FUNCTION (this << p);
+ m_rxCallback (this, p, Ipv4L3Protocol::PROT_NUMBER, Address ());
+
+ /** NOTE: added for comptabability with tapbridge
+ */
+ if (!m_promiscRx.IsNull ())
+ {
+ Mac48Address from = Mac48Address::ConvertFrom (GetAddress());
+ Mac48Address to = m_vmMacAdress;
+
+ enum NetDevice::PacketType type = NetDevice::PACKET_HOST;
+ m_promiscRx (this, p, Ipv4L3Protocol::PROT_NUMBER, from, to, type);
+ }
+}
+
+bool
+LteTapUeNetDevice::Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
+{
+ NS_LOG_FUNCTION (this << dest << protocolNumber);
+ if(protocolNumber== ArpL3Protocol::PROT_NUMBER)
+ {
+ Ptr<Packet> p=packet->Copy();
+ ArpHeader arp;
+ uint32_t size = p->RemoveHeader (arp);
+ if (size == 0)
+ {
+ NS_LOG_LOGIC ("lte ue received ARP: but Cannot remove ARP header");
+ return true;
+ }
+
+ if (!arp.IsRequest ())
+ {
+ NS_LOG_LOGIC ("received arp packet is not arp request, don't react to act it");
+ return true;
+ }
+
+ //check if ip source address of arp request equal to that of this lte device. If NOT, don't send reply
+ Ipv4Address lteDeviceIpAddress = GetNode ()->GetObject<Ipv4> ()
+ ->GetAddress (1, 0)
+ .GetLocal ();
+ if (arp.GetSourceIpv4Address () != lteDeviceIpAddress || arp.GetDestinationIpv4Address () != m_bsIpAddress)
+ return true;
+
+ Ipv4Address myIp = arp.GetDestinationIpv4Address ();
+ Ipv4Address toIp = arp.GetSourceIpv4Address ();
+ Address toMac = arp.GetSourceHardwareAddress ();
+
+ //generate arp reply
+ ArpHeader replyArp;
+ replyArp.SetReply (m_virtualAddress, myIp, toMac, toIp);
+ Ptr <Packet> replyPacket = Create<Packet> ();
+ replyPacket->AddHeader (replyArp);
+ enum NetDevice::PacketType type = NetDevice::PACKET_HOST;
+
+ m_promiscRx (this, replyPacket, ArpL3Protocol::PROT_NUMBER, m_virtualAddress, m_vmMacAdress, type);
+
+ return true;
+ }
+
+ return LteUeNetDevice::Send (packet, dest, protocolNumber);
+}
+
+}
diff --git a/emu-radio/lte-emulator/extensions/lte-tap-ue-net-device.h b/emu-radio/lte-emulator/extensions/lte-tap-ue-net-device.h
new file mode 100644
index 00000000..7e09e4c1
--- /dev/null
+++ b/emu-radio/lte-emulator/extensions/lte-tap-ue-net-device.h
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+#ifndef LTE_TAP_UE_NET_DEVICE_H
+#define LTE_TAP_UE_NET_DEVICE_H
+
+#include <ns3/lte-ue-net-device.h>
+
+/**
+ * \brief LteTapUeNetDevice class extends lteUeNetDevice class to support emulation of lte channel
+ */
+
+namespace ns3 {
+
+
+/**
+ * \defgroup lte LTE Models
+ *
+ */
+
+/**
+ * \ingroup lte
+ *
+ * LteTapUeNetDevice overides the receive logic and overides SetPromiscReceiveCallback of class lteUeNetDevice,
+ * to make it compatable with tapbridge emulation
+ */
+class LteTapUeNetDevice : public LteUeNetDevice
+{
+public:
+ static TypeId GetTypeId (void);
+ virtual void Receive (Ptr <Packet> p);
+ virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
+ LteTapUeNetDevice (void);
+
+ //overwrite the implementation in LteUeNetDevice in order to deal with arp request
+ virtual bool Send (Ptr <Packet> packet, const Address &dest, uint16_t protocolNumber);
+
+ //TODO optional? if related tap device resides on Container
+ void setMacAdressOnVM (Mac48Address vmMacAddress)
+ {
+ m_vmMacAdress = vmMacAddress;
+ }
+
+ void setBsIpAddress (Ipv4Address bsIp)
+ {
+ m_bsIpAddress = bsIp;
+ }
+
+ protected:
+ NetDevice::PromiscReceiveCallback m_promiscRx;
+ Mac48Address m_vmMacAdress;
+ //used for generating arp reply only
+ Mac48Address m_virtualAddress;
+ Ipv4Address m_bsIpAddress;
+};
+
+} // namespace ns3
+
+#endif /* LTE_TAP_UE_NET_DEVICE_H */
diff --git a/emu-radio/lte-emulator/extensions/tap-point-to-point-epc-helper.cc b/emu-radio/lte-emulator/extensions/tap-point-to-point-epc-helper.cc
new file mode 100644
index 00000000..66e86f55
--- /dev/null
+++ b/emu-radio/lte-emulator/extensions/tap-point-to-point-epc-helper.cc
@@ -0,0 +1,360 @@
+/*
+ * 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 "tap-point-to-point-epc-helper.h"
+#include <ns3/log.h>
+#include <ns3/inet-socket-address.h>
+#include <ns3/mac48-address.h>
+#include <ns3/eps-bearer.h>
+#include <ns3/ipv4-address.h>
+#include <ns3/internet-stack-helper.h>
+#include <ns3/point-to-point-helper.h>
+#include <ns3/packet-socket-helper.h>
+#include <ns3/packet-socket-address.h>
+#include <ns3/epc-enb-application.h>
+#include <ns3/epc-sgw-pgw-application.h>
+
+#include <ns3/lte-enb-rrc.h>
+#include <ns3/epc-x2.h>
+#include <ns3/lte-enb-net-device.h>
+#include <ns3/lte-ue-net-device.h>
+#include <ns3/epc-mme.h>
+#include <ns3/epc-ue-nas.h>
+
+/**
+ * NOTE: TapPointToPointEpcHelper is modified from PointToPointEpcHelper in ns3 lte module to support
+ * tap device used with lte device and configuration of UE IP address
+ */
+
+namespace ns3 {
+
+NS_LOG_COMPONENT_DEFINE ("TapPointToPointEpcHelper");
+
+NS_OBJECT_ENSURE_REGISTERED (TapPointToPointEpcHelper);
+
+TapPointToPointEpcHelper::TapPointToPointEpcHelper (std::string ueSubnetAddr,std::string ueSubnetMask, uint32_t id)
+ : m_gtpuUdpPort (2152) // fixed by the standard
+{
+ NS_LOG_FUNCTION (this);
+
+ // since we use point-to-point links for all S1-U links,
+ // we use a /30 subnet which can hold exactly two addresses
+ // (remember that net broadcast and null address are not valid)
+ m_s1uIpv4AddressHelper.SetBase ("10.0.0.0", "255.255.255.252");
+
+ m_x2Ipv4AddressHelper.SetBase ("12.0.0.0", "255.255.255.252");
+
+ // we use a /8 net for all UEs
+ m_ueAddressHelper.SetBase (ueSubnetAddr.c_str (), ueSubnetMask.c_str (), Ipv4Address (id));
+
+ // create SgwPgwNode
+ m_sgwPgw = CreateObject<Node> ();
+ InternetStackHelper internet;
+ internet.Install (m_sgwPgw);
+
+ // create S1-U socket
+ Ptr<Socket> sgwPgwS1uSocket = Socket::CreateSocket (m_sgwPgw, TypeId::LookupByName ("ns3::UdpSocketFactory"));
+ int retval = sgwPgwS1uSocket->Bind (InetSocketAddress (Ipv4Address::GetAny (), m_gtpuUdpPort));
+ NS_ASSERT (retval == 0);
+
+ // create TUN device implementing tunneling of user data over GTP-U/UDP/IP
+ m_tunDevice = CreateObject<VirtualNetDevice> ();
+ // allow jumbo packets
+ m_tunDevice->SetAttribute ("Mtu", UintegerValue (30000));
+
+ // yes we need this
+ m_tunDevice->SetAddress (Mac48Address::Allocate ());
+
+ m_sgwPgw->AddDevice (m_tunDevice);
+ NetDeviceContainer tunDeviceContainer;
+ tunDeviceContainer.Add (m_tunDevice);
+
+ // the TUN device is on the same subnet as the UEs, so when a packet
+ // addressed to an UE arrives at the intenet to the WAN interface of
+ // the PGW it will be forwarded to the TUN device.
+ Ipv4InterfaceContainer tunDeviceIpv4IfContainer = m_ueAddressHelper.Assign (tunDeviceContainer);
+
+ // create EpcSgwPgwApplication
+ m_sgwPgwApp = CreateObject<EpcSgwPgwApplication> (m_tunDevice, sgwPgwS1uSocket);
+ m_sgwPgw->AddApplication (m_sgwPgwApp);
+
+ // connect SgwPgwApplication and virtual net device for tunneling
+ m_tunDevice->SetSendCallback (MakeCallback (&EpcSgwPgwApplication::RecvFromTunDevice, m_sgwPgwApp));
+
+ // Create MME and connect with SGW via S11 interface
+ m_mme = CreateObject<EpcMme> ();
+ m_mme->SetS11SapSgw (m_sgwPgwApp->GetS11SapSgw ());
+ m_sgwPgwApp->SetS11SapMme (m_mme->GetS11SapMme ());
+}
+
+TapPointToPointEpcHelper::~TapPointToPointEpcHelper ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+TypeId
+TapPointToPointEpcHelper::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::TapPointToPointEpcHelper")
+ .SetParent<EpcHelper> ()
+ .SetGroupName("Lte")
+ .AddConstructor<TapPointToPointEpcHelper> ()
+ .AddAttribute ("S1uLinkDataRate",
+ "The data rate to be used for the next S1-U link to be created",
+ DataRateValue (DataRate ("1Gb/s")),
+ MakeDataRateAccessor (&TapPointToPointEpcHelper::m_s1uLinkDataRate),
+ MakeDataRateChecker ())
+ .AddAttribute ("S1uLinkDelay",
+ "The delay to be used for the next S1-U link to be created",
+ TimeValue (Seconds (0)),
+ MakeTimeAccessor (&TapPointToPointEpcHelper::m_s1uLinkDelay),
+ MakeTimeChecker ())
+ .AddAttribute ("S1uLinkMtu",
+ "The MTU of the next S1-U link to be created. Note that, because of the additional GTP/UDP/IP tunneling overhead, you need a MTU larger than the end-to-end MTU that you want to support.",
+ UintegerValue (2000),
+ MakeUintegerAccessor (&TapPointToPointEpcHelper::m_s1uLinkMtu),
+ MakeUintegerChecker<uint16_t> ())
+ .AddAttribute ("X2LinkDataRate",
+ "The data rate to be used for the next X2 link to be created",
+ DataRateValue (DataRate ("1Gb/s")),
+ MakeDataRateAccessor (&TapPointToPointEpcHelper::m_x2LinkDataRate),
+ MakeDataRateChecker ())
+ .AddAttribute ("X2LinkDelay",
+ "The delay to be used for the next X2 link to be created",
+ TimeValue (Seconds (0)),
+ MakeTimeAccessor (&TapPointToPointEpcHelper::m_x2LinkDelay),
+ MakeTimeChecker ())
+ .AddAttribute ("X2LinkMtu",
+ "The MTU of the next X2 link to be created. Note that, because of some big X2 messages, you need a big MTU.",
+ UintegerValue (3000),
+ MakeUintegerAccessor (&TapPointToPointEpcHelper::m_x2LinkMtu),
+ MakeUintegerChecker<uint16_t> ())
+ ;
+ return tid;
+}
+
+void
+TapPointToPointEpcHelper::DoDispose ()
+{
+ NS_LOG_FUNCTION (this);
+ m_tunDevice->SetSendCallback (MakeNullCallback<bool, Ptr<Packet>, const Address&, const Address&, uint16_t> ());
+ m_tunDevice = 0;
+ m_sgwPgwApp = 0;
+ m_sgwPgw->Dispose ();
+}
+
+
+void
+TapPointToPointEpcHelper::AddEnb (Ptr<Node> enb, Ptr<NetDevice> lteEnbNetDevice, uint16_t cellId)
+{
+ NS_LOG_FUNCTION (this << enb << lteEnbNetDevice << cellId);
+
+ NS_ASSERT (enb == lteEnbNetDevice->GetNode ());
+
+ // add an IPv4 stack to the previously created eNB
+ InternetStackHelper internet;
+ internet.Install (enb);
+ NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB after node creation: " << enb->GetObject<Ipv4> ()
+ ->GetNInterfaces ());
+
+ // create a point to point link between the new eNB and the SGW with
+ // the corresponding new NetDevices on each side
+ NodeContainer enbSgwNodes;
+ enbSgwNodes.Add (m_sgwPgw);
+ enbSgwNodes.Add (enb);
+ PointToPointHelper p2ph;
+ p2ph.SetDeviceAttribute ("DataRate", DataRateValue (m_s1uLinkDataRate));
+ p2ph.SetDeviceAttribute ("Mtu", UintegerValue (m_s1uLinkMtu));
+ p2ph.SetChannelAttribute ("Delay", TimeValue (m_s1uLinkDelay));
+ NetDeviceContainer enbSgwDevices = p2ph.Install (enb, m_sgwPgw);
+
+ //TODO**********
+// AsciiTraceHelper ascii;
+// p2ph.EnableAscii (ascii.CreateFileStream ("p2p-debug.tr"), enbSgwDevices );
+
+ NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB after installing p2p dev: " << enb->GetObject<Ipv4> ()->GetNInterfaces ());
+ Ptr<NetDevice> enbDev = enbSgwDevices.Get (0);
+ Ptr<NetDevice> sgwDev = enbSgwDevices.Get (1);
+ m_s1uIpv4AddressHelper.NewNetwork ();
+ Ipv4InterfaceContainer enbSgwIpIfaces = m_s1uIpv4AddressHelper.Assign (enbSgwDevices);
+ NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB after assigning Ipv4 addr to S1 dev: " << enb->GetObject<Ipv4> ()->GetNInterfaces ());
+
+ Ipv4Address enbAddress = enbSgwIpIfaces.GetAddress (0);
+ Ipv4Address sgwAddress = enbSgwIpIfaces.GetAddress (1);
+
+ // create S1-U socket for the ENB
+ Ptr<Socket> enbS1uSocket = Socket::CreateSocket (enb, TypeId::LookupByName ("ns3::UdpSocketFactory"));
+ int retval = enbS1uSocket->Bind (InetSocketAddress (enbAddress, m_gtpuUdpPort));
+ NS_ASSERT (retval == 0);
+
+
+ // give PacketSocket powers to the eNB
+ //PacketSocketHelper packetSocket;
+ //packetSocket.Install (enb);
+
+ // create LTE socket for the ENB
+ Ptr<Socket> enbLteSocket = Socket::CreateSocket (enb, TypeId::LookupByName ("ns3::PacketSocketFactory"));
+ PacketSocketAddress enbLteSocketBindAddress;
+ enbLteSocketBindAddress.SetSingleDevice (lteEnbNetDevice->GetIfIndex ());
+ enbLteSocketBindAddress.SetProtocol (Ipv4L3Protocol::PROT_NUMBER);
+ retval = enbLteSocket->Bind (enbLteSocketBindAddress);
+ NS_ASSERT (retval == 0);
+ PacketSocketAddress enbLteSocketConnectAddress;
+ enbLteSocketConnectAddress.SetPhysicalAddress (Mac48Address::GetBroadcast ());
+ enbLteSocketConnectAddress.SetSingleDevice (lteEnbNetDevice->GetIfIndex ());
+ enbLteSocketConnectAddress.SetProtocol (Ipv4L3Protocol::PROT_NUMBER);
+ retval = enbLteSocket->Connect (enbLteSocketConnectAddress);
+ NS_ASSERT (retval == 0);
+
+ NS_LOG_INFO ("create EpcEnbApplication");
+ Ptr<EpcEnbApplication> enbApp = CreateObject<EpcEnbApplication> (enbLteSocket, enbS1uSocket, enbAddress, sgwAddress, cellId);
+ enb->AddApplication (enbApp);
+ NS_ASSERT (enb->GetNApplications () == 1);
+ NS_ASSERT_MSG (enb->GetApplication (0)->GetObject<EpcEnbApplication> () != 0, "cannot retrieve EpcEnbApplication");
+ NS_LOG_LOGIC ("enb: " << enb << ", enb->GetApplication (0): " << enb->GetApplication (0));
+
+ NS_LOG_INFO ("Create EpcX2 entity");
+ Ptr<EpcX2> x2 = CreateObject<EpcX2> ();
+ enb->AggregateObject (x2);
+
+ NS_LOG_INFO ("connect S1-AP interface");
+ m_mme->AddEnb (cellId, enbAddress, enbApp->GetS1apSapEnb ());
+ m_sgwPgwApp->AddEnb (cellId, enbAddress, sgwAddress);
+ enbApp->SetS1apSapMme (m_mme->GetS1apSapMme ());
+}
+
+
+void
+TapPointToPointEpcHelper::AddX2Interface (Ptr<Node> enb1, Ptr<Node> enb2)
+{
+ NS_LOG_FUNCTION (this << enb1 << enb2);
+
+ // Create a point to point link between the two eNBs with
+ // the corresponding new NetDevices on each side
+ NodeContainer enbNodes;
+ enbNodes.Add (enb1);
+ enbNodes.Add (enb2);
+ PointToPointHelper p2ph;
+ p2ph.SetDeviceAttribute ("DataRate", DataRateValue (m_x2LinkDataRate));
+ p2ph.SetDeviceAttribute ("Mtu", UintegerValue (m_x2LinkMtu));
+ p2ph.SetChannelAttribute ("Delay", TimeValue (m_x2LinkDelay));
+ NetDeviceContainer enbDevices = p2ph.Install (enb1, enb2);
+ NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB #1 after installing p2p dev: " << enb1->GetObject<Ipv4> ()->GetNInterfaces ());
+ NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB #2 after installing p2p dev: " << enb2->GetObject<Ipv4> ()->GetNInterfaces ());
+ Ptr<NetDevice> enb1Dev = enbDevices.Get (0);
+ Ptr<NetDevice> enb2Dev = enbDevices.Get (1);
+
+ m_x2Ipv4AddressHelper.NewNetwork ();
+ Ipv4InterfaceContainer enbIpIfaces = m_x2Ipv4AddressHelper.Assign (enbDevices);
+ NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB #1 after assigning Ipv4 addr to X2 dev: " << enb1->GetObject<Ipv4> ()->GetNInterfaces ());
+ NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB #2 after assigning Ipv4 addr to X2 dev: " << enb2->GetObject<Ipv4> ()->GetNInterfaces ());
+
+ Ipv4Address enb1X2Address = enbIpIfaces.GetAddress (0);
+ Ipv4Address enb2X2Address = enbIpIfaces.GetAddress (1);
+
+ // Add X2 interface to both eNBs' X2 entities
+ Ptr<EpcX2> enb1X2 = enb1->GetObject<EpcX2> ();
+ Ptr<LteEnbNetDevice> enb1LteDev = enb1->GetDevice (0)->GetObject<LteEnbNetDevice> ();
+ uint16_t enb1CellId = enb1LteDev->GetCellId ();
+ NS_LOG_LOGIC ("LteEnbNetDevice #1 = " << enb1LteDev << " - CellId = " << enb1CellId);
+
+ Ptr<EpcX2> enb2X2 = enb2->GetObject<EpcX2> ();
+ Ptr<LteEnbNetDevice> enb2LteDev = enb2->GetDevice (0)->GetObject<LteEnbNetDevice> ();
+ uint16_t enb2CellId = enb2LteDev->GetCellId ();
+ NS_LOG_LOGIC ("LteEnbNetDevice #2 = " << enb2LteDev << " - CellId = " << enb2CellId);
+
+ enb1X2->AddX2Interface (enb1CellId, enb1X2Address, enb2CellId, enb2X2Address);
+ enb2X2->AddX2Interface (enb2CellId, enb2X2Address, enb1CellId, enb1X2Address);
+
+ enb1LteDev->GetRrc ()->AddX2Neighbour (enb2LteDev->GetCellId ());
+ enb2LteDev->GetRrc ()->AddX2Neighbour (enb1LteDev->GetCellId ());
+}
+
+
+void
+TapPointToPointEpcHelper::AddUe (Ptr<NetDevice> ueDevice, uint64_t imsi)
+{
+ NS_LOG_FUNCTION (this << imsi << ueDevice );
+
+ m_mme->AddUe (imsi);
+ m_sgwPgwApp->AddUe (imsi);
+
+}
+
+uint8_t
+TapPointToPointEpcHelper::ActivateEpsBearer (Ptr<NetDevice> ueDevice, uint64_t imsi, Ptr<EpcTft> tft, EpsBearer bearer)
+{
+ NS_LOG_FUNCTION (this << ueDevice << imsi);
+
+ // we now retrieve the IPv4 address of the UE and notify it to the SGW;
+ // we couldn't do it before since address assignment is triggered by
+ // the user simulation program, rather than done by the EPC
+ Ptr<Node> ueNode = ueDevice->GetNode ();
+ Ptr<Ipv4> ueIpv4 = ueNode->GetObject<Ipv4> ();
+ NS_ASSERT_MSG (ueIpv4 != 0, "UEs need to have IPv4 installed before EPS bearers can be activated");
+ int32_t interface = ueIpv4->GetInterfaceForDevice (ueDevice);
+ NS_ASSERT (interface >= 0);
+ NS_ASSERT (ueIpv4->GetNAddresses (interface) == 1);
+ Ipv4Address ueAddr = ueIpv4->GetAddress (interface, 0).GetLocal ();
+ NS_LOG_LOGIC (" UE IP address: " << ueAddr); m_sgwPgwApp->SetUeAddress (imsi, ueAddr);
+
+ uint8_t bearerId = m_mme->AddBearer (imsi, tft, bearer);
+ Ptr<LteUeNetDevice> ueLteDevice = ueDevice->GetObject<LteUeNetDevice> ();
+ if (ueLteDevice)
+ {
+ ueLteDevice->GetNas ()->ActivateEpsBearer (bearer, tft);
+ }
+ return bearerId;
+}
+
+
+Ptr<Node>
+TapPointToPointEpcHelper::GetPgwNode ()
+{
+ return m_sgwPgw;
+}
+
+
+Ipv4InterfaceContainer
+TapPointToPointEpcHelper::AssignUeIpv4Address (NetDeviceContainer ueDevices)
+{
+ return m_ueAddressHelper.Assign (ueDevices);
+}
+
+Ipv4InterfaceContainer
+TapPointToPointEpcHelper::AssignUeIpv4Address (Ptr<NetDevice> ueLteDevice, Ipv4Address ueIpAddress)
+{
+ Ipv4AddressHelper ueAddrHelper;
+ Ipv4Mask fakemask("255.255.255.0");//the mask is irrelevant here.
+ Ipv4Mask fakemask2(ueIpAddress.Get() & fakemask.Get());
+ Ipv4Address id=Ipv4Address(ueIpAddress.Get() ^ fakemask2.Get());
+ if(id.Get()<2)
+ std::cout<<"WARNING: id part of UE's IP="<<ueIpAddress<<" might be too small and have collisions\n";
+
+ ueAddrHelper.SetBase (ueIpAddress, fakemask2, id);
+ return ueAddrHelper.Assign (NetDeviceContainer (ueLteDevice));
+
+}
+
+
+Ipv4Address
+TapPointToPointEpcHelper::GetUeDefaultGatewayAddress ()
+{
+ // return the address of the tun device
+ return m_sgwPgw->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal ();
+}
+
+} // namespace ns3
diff --git a/emu-radio/lte-emulator/extensions/tap-point-to-point-epc-helper.h b/emu-radio/lte-emulator/extensions/tap-point-to-point-epc-helper.h
new file mode 100644
index 00000000..2fd79763
--- /dev/null
+++ b/emu-radio/lte-emulator/extensions/tap-point-to-point-epc-helper.h
@@ -0,0 +1,176 @@
+/*
+ * 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.
+ */
+
+#ifndef TAP_POINT_TO_POINT_EPC_HELPER_H
+#define TAP_POINT_TO_POINT_EPC_HELPER_H
+
+#include <ns3/object.h>
+#include <ns3/ipv4-address-helper.h>
+#include <ns3/data-rate.h>
+#include <ns3/epc-tft.h>
+#include <ns3/eps-bearer.h>
+#include <ns3/epc-helper.h>
+
+namespace ns3 {
+
+class Node;
+class NetDevice;
+class VirtualNetDevice;
+class EpcSgwPgwApplication;
+class EpcX2;
+class EpcMme;
+
+/**
+ * \ingroup lte
+ * \brief Create an EPC network with PointToPoint links
+ *
+ * This Helper will create an EPC network topology comprising of a
+ * single node that implements both the SGW and PGW functionality, and
+ * an MME node. The S1-U, X2-U and X2-C interfaces are realized over
+ * PointToPoint links.
+ */
+
+/**
+ * NOTE: TapPointToPointEpcHelper is modified from PointToPointEpcHelper in ns3 lte module to support
+ * tap device used with lte device and configuration of UE IP address
+ */
+class TapPointToPointEpcHelper : public EpcHelper
+{
+public:
+
+ /**
+ * Constructor
+ * \param ueSubnetAddr the ue subent ip prefix to be used for configuration, default value is "7.0.0.0"
+ * \param ueSubnetMask UesubnetMask is by default "255.0.0.0"
+ */
+ TapPointToPointEpcHelper (std::string ueSubnetAddr="7.0.0.0", std::string ueSubnetMask="255.0.0.0", uint32_t id=1);
+
+ /**
+ * Destructor
+ */
+ virtual ~TapPointToPointEpcHelper ();
+
+ // inherited from Object
+ /**
+ * Register this type.
+ * \return The object TypeId.
+ */
+ static TypeId GetTypeId (void);
+ virtual void DoDispose ();
+
+ // inherited from EpcHelper
+ virtual void AddEnb (Ptr<Node> enbNode, Ptr<NetDevice> lteEnbNetDevice, uint16_t cellId);
+ virtual void AddUe (Ptr<NetDevice> ueLteDevice, uint64_t imsi);
+ virtual void AddX2Interface (Ptr<Node> enbNode1, Ptr<Node> enbNode2);
+ virtual uint8_t ActivateEpsBearer (Ptr<NetDevice> ueLteDevice, uint64_t imsi, Ptr<EpcTft> tft, EpsBearer bearer);
+ virtual Ptr<Node> GetPgwNode ();
+ virtual Ipv4InterfaceContainer AssignUeIpv4Address (NetDeviceContainer ueDevices);
+ virtual Ipv4Address GetUeDefaultGatewayAddress ();
+
+ /** \brief explicity assign IP address to an UE device
+ *
+ */
+ Ipv4InterfaceContainer AssignUeIpv4Address (Ptr<NetDevice> ueLteDevice, Ipv4Address ueIpAddress);
+
+ private:
+
+ /**
+ * helper to assign addresses to UE devices as well as to the TUN device of the SGW/PGW
+ */
+ Ipv4AddressHelper m_ueAddressHelper;
+
+ /**
+ * SGW-PGW network element
+ */
+ Ptr<Node> m_sgwPgw;
+
+ /**
+ * SGW-PGW application
+ */
+ Ptr<EpcSgwPgwApplication> m_sgwPgwApp;
+
+ /**
+ * TUN device implementing tunneling of user data over GTP-U/UDP/IP
+ */
+ Ptr<VirtualNetDevice> m_tunDevice;
+
+ /**
+ * MME network element
+ */
+ Ptr<EpcMme> m_mme;
+
+ /**
+ * S1-U interfaces
+ */
+
+ /**
+ * helper to assign addresses to S1-U NetDevices
+ */
+ Ipv4AddressHelper m_s1uIpv4AddressHelper;
+
+ /**
+ * The data rate to be used for the next S1-U link to be created
+ */
+ DataRate m_s1uLinkDataRate;
+
+ /**
+ * The delay to be used for the next S1-U link to be created
+ */
+ Time m_s1uLinkDelay;
+
+ /**
+ * The MTU of the next S1-U link to be created. Note that,
+ * because of the additional GTP/UDP/IP tunneling overhead,
+ * you need a MTU larger than the end-to-end MTU that you
+ * want to support.
+ */
+ uint16_t m_s1uLinkMtu;
+
+ /**
+ * UDP port where the GTP-U Socket is bound, fixed by the standard as 2152
+ */
+ uint16_t m_gtpuUdpPort;
+
+ /**
+ * Map storing for each IMSI the corresponding eNB NetDevice
+ */
+ std::map<uint64_t, Ptr<NetDevice> > m_imsiEnbDeviceMap;
+
+ /**
+ * helper to assign addresses to X2 NetDevices
+ */
+ Ipv4AddressHelper m_x2Ipv4AddressHelper;
+
+ /**
+ * The data rate to be used for the next X2 link to be created
+ */
+ DataRate m_x2LinkDataRate;
+
+ /**
+ * The delay to be used for the next X2 link to be created
+ */
+ Time m_x2LinkDelay;
+
+ /**
+ * The MTU of the next X2 link to be created. Note that,
+ * because of some big X2 messages, you need a big MTU.
+ */
+ uint16_t m_x2LinkMtu;
+
+};
+
+} // namespace ns3
+
+#endif // TAP_POINT_TO_POINT_EPC_HELPER_H