From 46cd08db25111f999dbbb417dd51417ccae80501 Mon Sep 17 00:00:00 2001 From: Nicola Baldo Date: Fri, 4 Nov 2011 13:29:20 +0000 Subject: [PATCH] LTE-EPC end-to-end data plane imlemented and partially working --- src/lte/helper/lena-helper.cc | 130 +++++++++--- src/lte/helper/lena-helper.h | 89 ++++++--- src/lte/model/lte-enb-net-device.cc | 37 +--- src/lte/model/lte-enb-net-device.h | 9 +- src/lte/model/lte-enb-rrc.cc | 170 ++++++++++------ src/lte/model/lte-enb-rrc.h | 48 ++++- src/lte/model/lte-mac-tag.cc | 6 + src/lte/model/lte-net-device.cc | 71 +------ src/lte/model/lte-net-device.h | 59 +----- src/lte/model/lte-pdcp-sap.h | 24 ++- src/lte/model/lte-pdcp.cc | 7 +- src/lte/model/lte-radio-bearer-info.cc | 64 ++++++ src/lte/model/lte-radio-bearer-info.h | 48 +++++ src/lte/model/lte-rlc.h | 2 + src/lte/model/lte-ue-net-device.cc | 32 +-- src/lte/model/lte-ue-net-device.h | 21 +- src/lte/model/lte-ue-rrc.cc | 118 +++++++++-- src/lte/model/lte-ue-rrc.h | 43 +++- src/lte/test/lte-test-entities.cc | 3 +- src/lte/test/lte-test-entities.h | 4 +- src/lte/test/test-lte-epc-e2e-data.cc | 267 +++++++++++++++++++++++++ src/lte/wscript | 3 + 22 files changed, 913 insertions(+), 342 deletions(-) create mode 100644 src/lte/model/lte-radio-bearer-info.cc create mode 100644 src/lte/model/lte-radio-bearer-info.h create mode 100644 src/lte/test/test-lte-epc-e2e-data.cc diff --git a/src/lte/helper/lena-helper.cc b/src/lte/helper/lena-helper.cc index 579d042f2..8604af5cb 100644 --- a/src/lte/helper/lena-helper.cc +++ b/src/lte/helper/lena-helper.cc @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -42,6 +43,10 @@ #include #include +#include +#include + +#include #include @@ -55,6 +60,7 @@ NS_OBJECT_ENSURE_REGISTERED (LenaHelper); LenaHelper::LenaHelper (void) { NS_LOG_FUNCTION (this); + m_enbNetDeviceFactory.SetTypeId (LteEnbNetDevice::GetTypeId ()); } void @@ -77,16 +83,6 @@ LenaHelper::~LenaHelper (void) NS_LOG_FUNCTION (this); } - -void -LenaHelper::DoDispose () -{ - NS_LOG_FUNCTION (this); - m_downlinkChannel = 0; - m_uplinkChannel = 0; - Object::DoDispose (); -} - TypeId LenaHelper::GetTypeId (void) { static TypeId @@ -104,10 +100,40 @@ TypeId LenaHelper::GetTypeId (void) StringValue ("ns3::FriisSpectrumPropagationLossModel"), MakeStringAccessor (&LenaHelper::SetPropagationModelType), MakeStringChecker ()) + .AddAttribute ("EpsBearerToRlcMapping", + "Specify which type of RLC will be used for each type of EPS bearer. ", + EnumValue (RLC_SM_ALWAYS), + MakeEnumAccessor (&LenaHelper::m_epsBearerToRlcMapping), + MakeEnumChecker (RLC_SM_ALWAYS, "RlcSmAlways", + RLC_UM_ALWAYS, "RlcUmAlways", + RLC_AM_ALWAYS, "RlcAmAlways", + PER_BASED, "PacketErrorRateBased")) ; return tid; } +void +LenaHelper::DoDispose () +{ + NS_LOG_FUNCTION (this); + m_downlinkChannel = 0; + m_uplinkChannel = 0; + Object::DoDispose (); +} + + +void +LenaHelper::SetEpcHelper (Ptr h) +{ + NS_LOG_FUNCTION (this << h); + m_epcHelper = h; + // it does not make sense to use RLC/SM when also using the EPC + if (m_epsBearerToRlcMapping == RLC_SM_ALWAYS) + { + m_epsBearerToRlcMapping = RLC_UM_ALWAYS; + } +} + void LenaHelper::SetSchedulerType (std::string type) { @@ -139,6 +165,12 @@ LenaHelper::SetPropagationModelAttribute (std::string n, const AttributeValue &v m_propagationModelFactory.Set (n, v); } +void +LenaHelper::SetEnbDeviceAttribute (std::string n, const AttributeValue &v) +{ + NS_LOG_FUNCTION (this); + m_enbNetDeviceFactory.Set (n, v); +} NetDeviceContainer LenaHelper::InstallEnbDevice (NodeContainer c) @@ -169,22 +201,6 @@ LenaHelper::InstallUeDevice (NodeContainer c) return devices; } - -void -LenaHelper::SetEnbDeviceAttribute (std::string name, const AttributeValue &value) -{ - NS_LOG_FUNCTION (this); - NS_FATAL_ERROR ("not implemented yet"); -} - -void -LenaHelper::SetUeDeviceAttribute (std::string name, const AttributeValue &value) -{ - NS_LOG_FUNCTION (this); - NS_FATAL_ERROR ("not implemented yet"); -} - - Ptr LenaHelper::InstallSingleEnbDevice (Ptr n) { @@ -232,8 +248,16 @@ LenaHelper::InstallSingleEnbDevice (Ptr n) n->AddDevice (dev); ulPhy->SetGenericPhyRxEndOkCallback (MakeCallback (&LteEnbPhy::PhyPduReceived, phy)); - + rrc->SetForwardUpCallback (MakeCallback (&LteEnbNetDevice::Receive, dev)); + dev->Start (); + + if (m_epcHelper != 0) + { + NS_LOG_INFO ("adding this eNB to the EPC"); + m_epcHelper->AddEnb (n, dev); + } + return dev; } @@ -265,6 +289,7 @@ LenaHelper::InstallSingleUeDevice (Ptr n) rrc->SetLteUeCmacSapProvider (mac->GetLteUeCmacSapProvider ()); mac->SetLteUeCmacSapUser (rrc->GetLteUeCmacSapUser ()); rrc->SetLteMacSapProvider (mac->GetLteMacSapProvider ()); + phy->SetLteUePhySapUser (mac->GetLteUePhySapUser ()); mac->SetLteUePhySapProvider (phy->GetLteUePhySapProvider ()); @@ -275,6 +300,7 @@ LenaHelper::InstallSingleUeDevice (Ptr n) n->AddDevice (dev); dlPhy->SetGenericPhyRxEndOkCallback (MakeCallback (&LteUePhy::PhyPduReceived, phy)); + rrc->SetForwardUpCallback (MakeCallback (&LteUeNetDevice::Receive, dev)); return dev; } @@ -332,18 +358,58 @@ LenaHelper::ActivateEpsBearer (NetDeviceContainer ueDevices, EpsBearer bearer, P void LenaHelper::ActivateEpsBearer (Ptr ueDevice, EpsBearer bearer, Ptr tft) { - // setup RadioBearer first + NS_LOG_INFO (" setting up Radio Bearer"); Ptr enbDevice = ueDevice->GetObject ()->GetTargetEnb (); Ptr enbRrc = enbDevice->GetObject ()->GetRrc (); Ptr ueRrc = ueDevice->GetObject ()->GetRrc (); uint16_t rnti = ueRrc->GetRnti (); - uint8_t lcid = enbRrc->SetupRadioBearer (rnti, bearer); - ueRrc->SetupRadioBearer (rnti, bearer, lcid); + TypeId rlcTypeId = GetRlcType (bearer); + uint8_t lcid = enbRrc->SetupRadioBearer (rnti, bearer, rlcTypeId); + ueRrc->SetupRadioBearer (rnti, bearer, rlcTypeId, lcid, tft); - // then setup S1 Bearer + if (m_epcHelper != 0) + { + NS_LOG_INFO (" setting up S1 Bearer"); + m_epcHelper->ActivateEpsBearer (ueDevice, enbDevice, tft, rnti, lcid); + + } } - +TypeId +LenaHelper::GetRlcType (EpsBearer bearer) +{ + switch (m_epsBearerToRlcMapping) + { + case RLC_SM_ALWAYS: + return LteRlcSm::GetTypeId (); + break; + + case RLC_UM_ALWAYS: + return LteRlcUm::GetTypeId (); + break; + + case RLC_AM_ALWAYS: + NS_ABORT_MSG ("RLC/AM not supported yet"); + //return LteRlcAm::GetTypeId (); + break; + + case PER_BASED: + if (bearer.GetPacketErrorLossRate () > 1.0e-5) + { + return LteRlcUm::GetTypeId (); + } + else + { + NS_ABORT_MSG ("RLC/AM not supported yet"); + //return LteRlcAm::GetTypeId (); + } + break; + + default: + return LteRlcSm::GetTypeId (); + break; + } +} void LenaHelper::EnableLogComponents (void) diff --git a/src/lte/helper/lena-helper.h b/src/lte/helper/lena-helper.h index 9db2aea61..c69143cde 100644 --- a/src/lte/helper/lena-helper.h +++ b/src/lte/helper/lena-helper.h @@ -40,6 +40,7 @@ namespace ns3 { class LteUePhy; class LteEnbPhy; class SpectrumChannel; +class EpcHelper; /** @@ -55,22 +56,58 @@ public: static TypeId GetTypeId (void); virtual void DoDispose (void); - /** - * \todo to be implemented + + /** + * Set the EpcHelper to be used to setup the EPC network in + * conjunction with the setup of the LTE radio access network * - * \param name - * \param value + * \note if no EpcHelper is ever set, then LenaHelper 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 SetEnbDeviceAttribute (std::string name, const AttributeValue &value); + void SetEpcHelper (Ptr h); + + /** + * + * + * \param type the type of propagation model to be used for the eNBs + */ + void SetPropagationModelType (std::string type); /** - * \todo to be implemented - * - * \param name - * \param value + * set an attribute for the propagation model to be created + * + * \param n the name of the attribute + * \param v the value of the attribute */ - void SetUeDeviceAttribute (std::string name, const AttributeValue &value); + void SetPropagationModelAttribute (std::string n, const AttributeValue &v); + /** + * + * \param type the type of scheduler to be used for the eNBs + */ + void SetSchedulerType (std::string type); + + /** + * 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 an attribute for the 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); /** * create a set of eNB devices @@ -126,28 +163,11 @@ public: /** * + * \param bearer the specification of an EPS bearer * - * \param type the type of scheduler to be used for the eNBs + * \return the type of RLC that is to be created for the given EPS bearer */ - void SetSchedulerType (std::string type); - - /** - * set an attribute for the scheduler to be created - */ - void SetSchedulerAttribute (std::string n, const AttributeValue &v); - - /** - * - * - * \param type the type of propagation model to be used for the eNBs - */ - void SetPropagationModelType (std::string type); - - /** - * set an attribute for the propagation model to be created - */ - void SetPropagationModelAttribute (std::string n, const AttributeValue &v); - + TypeId GetRlcType (EpsBearer bearer); /** * Enables logging for all components of the LENA architecture @@ -202,10 +222,19 @@ private: ObjectFactory m_schedulerFactory; ObjectFactory m_propagationModelFactory; + ObjectFactory m_enbNetDeviceFactory; + Ptr m_macStats; Ptr m_rlcStats; + enum LteEpsBearerToRlcMapping_t {RLC_SM_ALWAYS = 1, + RLC_UM_ALWAYS = 2, + RLC_AM_ALWAYS = 3, + PER_BASED = 4} m_epsBearerToRlcMapping; + + Ptr m_epcHelper; + }; diff --git a/src/lte/model/lte-enb-net-device.cc b/src/lte/model/lte-enb-net-device.cc index 4988bd3e4..9c69cda66 100644 --- a/src/lte/model/lte-enb-net-device.cc +++ b/src/lte/model/lte-enb-net-device.cc @@ -38,7 +38,7 @@ #include #include #include - +#include NS_LOG_COMPONENT_DEFINE ("LteEnbNetDevice"); @@ -270,41 +270,14 @@ LteEnbNetDevice::DoStart (void) bool -LteEnbNetDevice::DoSend (Ptr packet, const Mac48Address& source, - const Mac48Address& dest, uint16_t protocolNumber) +LteEnbNetDevice::Send (Ptr packet, const Address& dest, uint16_t protocolNumber) { - NS_LOG_FUNCTION (this << source << dest << protocolNumber); - - NS_FATAL_ERROR ("IP connectivity not implemented yet"); - - /* - * The classification of traffic in DL is done by the PGW (not - * by the eNB). - * Hovever, the core network is not implemented yet. - * For now the classification is managed by the eNB. - */ - - // if (protocolNumber == 2048) - // { - // // it is an IP packet - // } - - // if (protocolNumber != 2048 || bearer == 0) - // { - - // } - - - return true; + NS_LOG_FUNCTION (this << packet << dest << protocolNumber); + NS_ASSERT_MSG (protocolNumber == Ipv4L3Protocol::PROT_NUMBER, "unsupported protocol " << protocolNumber << ", only IPv4 is supported"); + return m_rrc->Send (packet); } -void -LteEnbNetDevice::DoReceive (Ptr p) -{ - NS_LOG_FUNCTION (this << p); - ForwardUp (p->Copy ()); -} void diff --git a/src/lte/model/lte-enb-net-device.h b/src/lte/model/lte-enb-net-device.h index 42cf2e463..62466a624 100644 --- a/src/lte/model/lte-enb-net-device.h +++ b/src/lte/model/lte-enb-net-device.h @@ -67,6 +67,9 @@ public: virtual ~LteEnbNetDevice (void); virtual void DoDispose (void); + // inherited from NetDevice + virtual bool Send (Ptr packet, const Address& dest, uint16_t protocolNumber); + /** * \return a pointer to the MAC */ @@ -134,12 +137,6 @@ protected: private: - bool DoSend (Ptr packet, - const Mac48Address& source, - const Mac48Address& dest, - uint16_t protocolNumber); - - void DoReceive (Ptr p); /** * Several attributes (e.g., the bandwidth) are exported as diff --git a/src/lte/model/lte-enb-rrc.cc b/src/lte/model/lte-enb-rrc.cc index 14b6f84f4..114eb0920 100644 --- a/src/lte/model/lte-enb-rrc.cc +++ b/src/lte/model/lte-enb-rrc.cc @@ -20,12 +20,17 @@ #include #include +#include #include "ns3/pointer.h" +#include "ns3/object-map.h" +#include "ns3/object-factory.h" #include "lte-enb-rrc.h" #include "lte-rlc.h" -#include "ns3/object-map.h" - +#include "lte-pdcp.h" +#include "lte-pdcp-sap.h" +#include "lte-radio-bearer-info.h" +#include "lte-mac-tag.h" NS_LOG_COMPONENT_DEFINE ("LteEnbRrc"); @@ -62,57 +67,38 @@ EnbRrcMemberLteEnbCmacSapUser::NotifyLcConfigResult (uint16_t rnti, uint8_t lcid } +//////////////////////////////// +// PDCP SAP Forwarder +//////////////////////////////// -// ///////////////////////////////////////// -// per-UE radio bearer info management -// ///////////////////////////////////////// +// not needed any more if the template works -class EnbRadioBearerInfo : public Object -{ +// class EnbRrcMemberLtePdcpSapUser : public LtePdcpSapUser +// { +// public: +// MemberLtePdcpSapUser (LteEnbRrc* rrc); +// virtual void ReceiveRrcPdu (Ptr p); +// private: +// LteEnbRrc* m_rrc; +// }; -public: - EnbRadioBearerInfo (void); - virtual ~EnbRadioBearerInfo (void); - static TypeId GetTypeId (void); - void SetRlc (Ptr rlc); +// EnbRrcMemberLtePdcpSapUser::EnbRrcMemberLtePdcpSapUser (LteEnbRrc* rrc) +// : m_rrc (rrc) +// { +// } -private: - Ptr m_rlc; +// void EnbRrcMemberLtePdcpSapUser::ReceiveRrcPdu (Ptr p) +// { +// m_rrc->DoReceiveRrcPdu (p); +// } -}; -NS_OBJECT_ENSURE_REGISTERED (EnbRadioBearerInfo); -EnbRadioBearerInfo::EnbRadioBearerInfo (void) -{ - // Nothing to do here -} -EnbRadioBearerInfo::~EnbRadioBearerInfo (void) -{ - // Nothing to do here -} - -TypeId EnbRadioBearerInfo::GetTypeId (void) -{ - static TypeId - tid = - TypeId ("ns3::EnbRadioBearerInfo") - .SetParent () - .AddConstructor () - .AddAttribute ("LteRlc", "RLC instance of the radio bearer.", - PointerValue (), - MakePointerAccessor (&EnbRadioBearerInfo::m_rlc), - MakePointerChecker ()) - ; - return tid; -} - -void EnbRadioBearerInfo::SetRlc (Ptr rlc) -{ - m_rlc = rlc; -} +/////////////////////////////////////////// +// UeInfo +/////////////////////////////////////////// NS_OBJECT_ENSURE_REGISTERED (UeInfo); @@ -144,12 +130,7 @@ TypeId UeInfo::GetTypeId (void) .AddAttribute ("RadioBearerMap", "List of UE RadioBearerInfo by LCID.", ObjectMapValue (), MakeObjectMapAccessor (&UeInfo::m_rbMap), - MakeObjectMapChecker ()) -/* .AddAttribute("Imsi", - "International Mobile Subscriber Identity assigned to this UE", - UintegerValue (1), - MakeUintegerAccessor (&UeInfo::m_imsi), - MakeUintegerChecker ())*/ + MakeObjectMapChecker ()) ; return tid; } @@ -161,7 +142,7 @@ UeInfo::GetImsi (void) } uint8_t -UeInfo::AddRadioBearer (Ptr rbi) +UeInfo::AddRadioBearer (Ptr rbi) { NS_LOG_FUNCTION (this); for (uint8_t lcid = m_lastAllocatedId; lcid != m_lastAllocatedId - 1; ++lcid) @@ -170,7 +151,7 @@ UeInfo::AddRadioBearer (Ptr rbi) { if (m_rbMap.find (lcid) == m_rbMap.end ()) { - m_rbMap.insert (std::pair > (lcid, rbi)); + m_rbMap.insert (std::pair > (lcid, rbi)); m_lastAllocatedId = lcid; return lcid; } @@ -180,12 +161,14 @@ UeInfo::AddRadioBearer (Ptr rbi) return 0; } -Ptr +Ptr UeInfo::GetRadioBearer (uint8_t lcid) { NS_LOG_FUNCTION (this << (uint32_t) lcid); NS_ASSERT (0 != lcid); - return m_rbMap.find (lcid)->second; + std::map >::iterator it = m_rbMap.find (lcid); + NS_ABORT_IF (it == m_rbMap.end ()); + return it->second; } @@ -193,7 +176,7 @@ void UeInfo::RemoveRadioBearer (uint8_t lcid) { NS_LOG_FUNCTION (this << (uint32_t) lcid); - std::map >::iterator it = m_rbMap.find (lcid); + std::map >::iterator it = m_rbMap.find (lcid); NS_ASSERT_MSG (it != m_rbMap.end (), "request to remove radio bearer with unknown lcid " << lcid); m_rbMap.erase (it); } @@ -217,6 +200,7 @@ LteEnbRrc::LteEnbRrc () { NS_LOG_FUNCTION (this); m_cmacSapUser = new EnbRrcMemberLteEnbCmacSapUser (this); + m_pdcpSapUser = new LtePdcpSpecificLtePdcpSapUser (this); } @@ -231,6 +215,7 @@ LteEnbRrc::DoDispose () { NS_LOG_FUNCTION (this); delete m_cmacSapUser; + delete m_pdcpSapUser; } TypeId @@ -303,6 +288,11 @@ LteEnbRrc::SetLteMacSapProvider (LteMacSapProvider * s) m_macSapProvider = s; } +LtePdcpSapProvider* +LteEnbRrc::GetLtePdcpSapProvider (uint16_t rnti, uint8_t lcid) +{ + return GetUeInfo (rnti)->GetRadioBearer (lcid)->m_pdcp->GetLtePdcpSapProvider (); +} void LteEnbRrc::ConfigureCell (uint8_t ulBandwidth, uint8_t dlBandwidth) @@ -333,23 +323,37 @@ LteEnbRrc::RemoveUe (uint16_t rnti) } uint8_t -LteEnbRrc::SetupRadioBearer (uint16_t rnti, EpsBearer bearer) +LteEnbRrc::SetupRadioBearer (uint16_t rnti, EpsBearer bearer, TypeId rlcTypeId) { NS_LOG_FUNCTION (this << (uint32_t) rnti); Ptr ueInfo = GetUeInfo (rnti); // create RLC instance - // for now we support RLC SM only - Ptr rlc = CreateObject (); + ObjectFactory rlcObjectFactory; + rlcObjectFactory.SetTypeId (rlcTypeId); + Ptr rlc = rlcObjectFactory.Create ()->GetObject (); rlc->SetLteMacSapProvider (m_macSapProvider); rlc->SetRnti (rnti); - Ptr rbInfo = CreateObject (); - rbInfo->SetRlc (rlc); + Ptr rbInfo = CreateObject (); + rbInfo->m_rlc = rlc; uint8_t lcid = ueInfo->AddRadioBearer (rbInfo); rlc->SetLcId (lcid); + // we need PDCP only for real RLC, i.e., RLC/UM or RLC/AM + // if we are using RLC/SM we don't care of anything above RLC + if (rlcTypeId != LteRlcSm::GetTypeId ()) + { + Ptr pdcp = CreateObject (); + pdcp->SetRnti (rnti); + pdcp->SetLcId (lcid); + pdcp->SetLtePdcpSapUser (m_pdcpSapUser); + pdcp->SetLteRlcSapProvider (rlc->GetLteRlcSapProvider ()); + rlc->SetLteRlcSapUser (pdcp->GetLteRlcSapUser ()); + rbInfo->m_pdcp = pdcp; + } + LteEnbCmacSapProvider::LcInfo lcinfo; lcinfo.rnti = rnti; lcinfo.lcId = lcid; @@ -373,6 +377,48 @@ LteEnbRrc::ReleaseRadioBearer (uint16_t rnti, uint8_t lcId) ueInfo->RemoveRadioBearer (lcId); } + + +bool +LteEnbRrc::Send (Ptr packet) +{ + NS_LOG_FUNCTION (this << packet); + + LteMacTag tag; + bool found = packet->RemovePacketTag (tag); + NS_ASSERT (found); + + LtePdcpSapProvider::TransmitRrcPduParameters params; + params.rrcPdu = packet; + params.rnti = tag.GetRnti (); + params.lcid = tag.GetLcid (); + LtePdcpSapProvider* pdcpSapProvider = GetLtePdcpSapProvider (tag.GetRnti (), tag.GetLcid ()); + pdcpSapProvider->TransmitRrcPdu (params); + + return true; +} + +void +LteEnbRrc::SetForwardUpCallback (Callback > cb) +{ + m_forwardUpCallback = cb; +} + + +void +LteEnbRrc::DoReceiveRrcPdu (LtePdcpSapUser::ReceiveRrcPduParameters params) +{ + NS_LOG_FUNCTION (this); + // this tag is needed by the EpcEnbApplication to determine the S1 bearer that corresponds to this radio bearer + LteMacTag tag; + tag.SetRnti (params.rnti); + tag.SetLcid (params.lcid); + params.rrcPdu->AddPacketTag (tag); + m_forwardUpCallback (params.rrcPdu); +} + + + void LteEnbRrc::DoNotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success) { @@ -411,7 +457,9 @@ LteEnbRrc::GetUeInfo (uint16_t rnti) { NS_LOG_FUNCTION (this << (uint32_t) rnti); NS_ASSERT (0 != rnti); - return m_ueMap.find (rnti)->second; + std::map >::iterator it = m_ueMap.find (rnti); + NS_ABORT_IF (it == m_ueMap.end ()); + return it->second; } void diff --git a/src/lte/model/lte-enb-rrc.h b/src/lte/model/lte-enb-rrc.h index f01ba8f01..cd2a4bb08 100644 --- a/src/lte/model/lte-enb-rrc.h +++ b/src/lte/model/lte-enb-rrc.h @@ -25,6 +25,7 @@ #include #include #include +#include #include @@ -32,7 +33,9 @@ namespace ns3 { class FfMacSchedSapProvider; class LteMacSapProvider; -class EnbRadioBearerInfo; +class LteRadioBearerInfo; +class LtePdcpSapUser; +class LtePdcpSapProvider; /** @@ -46,20 +49,20 @@ public: /** * * - * \param EnbRadioBearerInfo + * \param radioBearerInfo * * \return the allocated logical channel id; 0 is returned if it is not possible to allocate a channel id (e.g., id space exausted). */ - uint8_t AddRadioBearer (Ptr enbRadioBearerInfo); + uint8_t AddRadioBearer (Ptr radioBearerInfo); /** * * * \param uint8_t the logical channel id * - * \return the EnbRadioBearerInfo of the selected radio bearer + * \return the LteRadioBearerInfo of the selected radio bearer */ - Ptr GetRadioBearer (uint8_t lcid); + Ptr GetRadioBearer (uint8_t lcid); /** @@ -78,7 +81,7 @@ public: uint64_t GetImsi (void); private: - std::map > m_rbMap; + std::map > m_rbMap; uint8_t m_lastAllocatedId; uint64_t m_imsi; }; @@ -92,6 +95,7 @@ class LteEnbRrc : public Object { friend class EnbRrcMemberLteEnbCmacSapUser; + friend class LtePdcpSpecificLtePdcpSapUser; public: /** @@ -119,7 +123,7 @@ public: void SetLteEnbCmacSapProvider (LteEnbCmacSapProvider * s); /** - * Get the CMAC SAP this RRC should interact with + * Get the CMAC SAP offered by this RRC * \return s the CMAC SAP User interface offered to the MAC by this RRC */ LteEnbCmacSapUser* GetLteEnbCmacSapUser (); @@ -145,6 +149,7 @@ public: void SetLteMacSapProvider (LteMacSapProvider* s); + /** * configure cell-specific parameters * @@ -179,10 +184,11 @@ public: * * \param rnti the RNTI of the user * \param bearer the characteristics of the bearer to be activated + * \param rlcTypeId the TypeId identifying the type of RLC to be used for this bearer. * * \return the logical channel identifier of the radio bearer for the considered user */ - uint8_t SetupRadioBearer (uint16_t rnti, EpsBearer bearer); + uint8_t SetupRadioBearer (uint16_t rnti, EpsBearer bearer, TypeId rlcTypeId); /** @@ -194,19 +200,45 @@ public: */ void ReleaseRadioBearer (uint16_t rnti, uint8_t lcId); + + /** + * Enqueue an IP packet on the proper bearer for downlink transmission + * + * \param p the packet + * + * \return true if successful, false if an error occurred + */ + bool Send (Ptr p); + + /** + * set the callback used to forward data packets up the stack + * + * \param void + * \param cb + */ + void SetForwardUpCallback (Callback > cb); + + private: + + void DoReceiveRrcPdu (LtePdcpSapUser::ReceiveRrcPduParameters params); + void DoNotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success); + LtePdcpSapProvider* GetLtePdcpSapProvider (uint16_t rnti, uint8_t lcid); // management of multiple UE info instances uint16_t CreateUeInfo (uint64_t imsi); Ptr GetUeInfo (uint16_t rnti); void RemoveUeInfo (uint16_t rnti); + Callback > m_forwardUpCallback; + LteEnbCmacSapUser* m_cmacSapUser; LteEnbCmacSapProvider* m_cmacSapProvider; FfMacSchedSapProvider* m_ffMacSchedSapProvider; LteMacSapProvider* m_macSapProvider; + LtePdcpSapUser* m_pdcpSapUser; bool m_configured; uint16_t m_lastAllocatedRnti; diff --git a/src/lte/model/lte-mac-tag.cc b/src/lte/model/lte-mac-tag.cc index 3eb88ee48..40a147812 100644 --- a/src/lte/model/lte-mac-tag.cc +++ b/src/lte/model/lte-mac-tag.cc @@ -68,6 +68,12 @@ LteMacTag::SetRnti (uint16_t rnti) m_rnti = rnti; } +void +LteMacTag::SetLcid (uint8_t lcid) +{ + m_lcid = lcid; +} + uint32_t LteMacTag::GetSerializedSize (void) const { diff --git a/src/lte/model/lte-net-device.cc b/src/lte/model/lte-net-device.cc index 261f56c0a..5f65136c4 100644 --- a/src/lte/model/lte-net-device.cc +++ b/src/lte/model/lte-net-device.cc @@ -33,6 +33,7 @@ #include "lte-amc.h" #include "ns3/ipv4-header.h" #include +#include NS_LOG_COMPONENT_DEFINE ("LteNetDevice"); @@ -40,6 +41,9 @@ namespace ns3 { NS_OBJECT_ENSURE_REGISTERED ( LteNetDevice); +//////////////////////////////// +// LteNetDevice +//////////////////////////////// TypeId LteNetDevice::GetTypeId (void) { @@ -129,49 +133,11 @@ LteNetDevice::SetReceiveCallback (ReceiveCallback cb) } -void -LteNetDevice::ForwardUp (Ptr packet, const Mac48Address &source, const Mac48Address &dest) -{ - -} - - -void -LteNetDevice::ForwardUp (Ptr packet) -{ - NS_LOG_FUNCTION (this << packet); - - m_macRxTrace (packet); - - LlcSnapHeader llc; - packet->RemoveHeader (llc); - - m_rxCallback (this, packet, llc.GetType (), Address ()); -} - - - -bool -LteNetDevice::Send (Ptr packet, const Address& dest, uint16_t protocolNumber) -{ - NS_LOG_FUNCTION (packet << dest << protocolNumber); - return SendFrom (packet, m_address, dest, protocolNumber); -} - - bool LteNetDevice::SendFrom (Ptr packet, const Address& source, const Address& dest, uint16_t protocolNumber) { - NS_LOG_FUNCTION (packet << source << dest << protocolNumber); - - - LlcSnapHeader llcHdr; - llcHdr.SetType (protocolNumber); - packet->AddHeader (llcHdr); - - NS_FATAL_ERROR ("IP connectivity not implemented yet"); - - return true; + NS_FATAL_ERROR ("SendFrom () not supported"); + return false; } @@ -183,15 +149,6 @@ LteNetDevice::SupportsSendFrom (void) const } -void -LteNetDevice::Receive (Ptr p) -{ - NS_LOG_FUNCTION (this << p); - Ptr packet = p->Copy (); - DoReceive (packet); -} - - bool LteNetDevice::SetMtu (const uint16_t mtu) @@ -321,23 +278,17 @@ void LteNetDevice::SetPromiscReceiveCallback (PromiscReceiveCallback cb) { NS_LOG_FUNCTION (this); - m_promiscRxCallback = cb; + NS_LOG_WARN ("Promisc mode not supported"); } + void -LteNetDevice::SetPacketToSend (Ptr p) +LteNetDevice::Receive (Ptr p) { - m_packetToSend = p; + NS_LOG_FUNCTION (this << p); + m_rxCallback (this, p, Ipv4L3Protocol::PROT_NUMBER, Address ()); } -Ptr -LteNetDevice::GetPacketToSend (void) -{ - return m_packetToSend; -} - - - } diff --git a/src/lte/model/lte-net-device.h b/src/lte/model/lte-net-device.h index 74f3de8db..b08bad091 100644 --- a/src/lte/model/lte-net-device.h +++ b/src/lte/model/lte-net-device.h @@ -35,8 +35,6 @@ namespace ns3 { class Node; class Packet; -class PacketBurst; - /** * \defgroup lte LTE Models @@ -80,66 +78,29 @@ public: virtual Address GetMulticast (Ipv4Address addr) const; virtual Address GetMulticast (Ipv6Address addr) const; virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb); - - virtual bool Send (Ptr packet, const Address& dest, uint16_t protocolNumber); virtual bool SendFrom (Ptr packet, const Address& source, const Address& dest, uint16_t protocolNumber); virtual bool SupportsSendFrom (void) const; - /** - * \brief Receive the packet from the phy layer - * \param p the received packet + /** + * receive a packet from the lower layers in order to forward it to the upper layers + * + * \param p the packet */ void Receive (Ptr p); - /** - * \brief Forward packet to the uppar layer. - * If is called by DoReceive method - * \param packet packet sent from Network Device to the upper layer - * \param source source mac address - * \param dest mac address of the destination - */ - void ForwardUp (Ptr packet, const Mac48Address &source, const Mac48Address &dest); - /** - * \brief Forward packet to the uppar layer. - * If is called by DoReceive method - * \param packet packet sent from Network Device to the upper layer - */ - void ForwardUp (Ptr packet); - - /** - * \brief Set packets to send - * \param p the burst of packets to send - */ - void SetPacketToSend (Ptr p); - /** - * \brief Get packets to send - * \return the pointer to the burst of packets to send - */ - Ptr GetPacketToSend (void); - - + +protected: + + NetDevice::ReceiveCallback m_rxCallback; + private: LteNetDevice (const LteNetDevice &); LteNetDevice & operator= (const LteNetDevice &); static const uint16_t MAX_MSDU_SIZE = 1500; - virtual bool DoSend (Ptr packet, - const Mac48Address& source, - const Mac48Address& dest, - uint16_t protocolNumber) = 0; - virtual void DoReceive (Ptr p) = 0; - Ptr m_node; - TracedCallback > m_macTxTrace; - TracedCallback > m_macTxDropTrace; - TracedCallback > m_macPromiscRxTrace; - TracedCallback > m_macRxTrace; - - NetDevice::ReceiveCallback m_rxCallback; - NetDevice::PromiscReceiveCallback m_promiscRxCallback; - TracedCallback<> m_linkChangeCallbacks; uint32_t m_ifIndex; @@ -147,8 +108,6 @@ private: mutable uint16_t m_mtu; Mac48Address m_address; - - Ptr m_packetToSend; }; diff --git a/src/lte/model/lte-pdcp-sap.h b/src/lte/model/lte-pdcp-sap.h index 8fefe88f8..f7dc9e3ea 100644 --- a/src/lte/model/lte-pdcp-sap.h +++ b/src/lte/model/lte-pdcp-sap.h @@ -50,7 +50,9 @@ public: /** * Send a RRC PDU to the RDCP for transmission * This method is to be called - * when upper RRC entity has a RRC PDU ready to send + * when upper RRC entity has a RRC PDU ready to send + * + * \param params */ virtual void TransmitRrcPdu (TransmitRrcPduParameters params) = 0; }; @@ -68,12 +70,22 @@ class LtePdcpSapUser public: virtual ~LtePdcpSapUser (); + /** + * Parameters for LtePdcpSapUser::ReceiveRrcPdu + */ + struct ReceiveRrcPduParameters + { + Ptr rrcPdu; /**< the RRC PDU */ + uint16_t rnti; /**< the C-RNTI identifying the UE */ + uint8_t lcid; /**< the logical channel id corresponding to the sending RLC instance */ + }; + /** * Called by the PDCP entity to notify the RRC entity of the reception of a new RRC PDU * - * \param p the RRC PDU + * \param params */ - virtual void ReceiveRrcPdu (Ptr p) = 0; + virtual void ReceiveRrcPdu (ReceiveRrcPduParameters params) = 0; }; /////////////////////////////////////// @@ -118,7 +130,7 @@ public: LtePdcpSpecificLtePdcpSapUser (C* rrc); // Interface implemented from LtePdcpSapUser - virtual void ReceiveRrcPdu (Ptr p); + virtual void ReceiveRrcPdu (ReceiveRrcPduParameters params); private: LtePdcpSpecificLtePdcpSapUser (); @@ -137,9 +149,9 @@ LtePdcpSpecificLtePdcpSapUser::LtePdcpSpecificLtePdcpSapUser () } template -void LtePdcpSpecificLtePdcpSapUser::ReceiveRrcPdu (Ptr p) +void LtePdcpSpecificLtePdcpSapUser::ReceiveRrcPdu (ReceiveRrcPduParameters params) { - m_rrc->DoReceiveRrcPdu (p); + m_rrc->DoReceiveRrcPdu (params); } diff --git a/src/lte/model/lte-pdcp.cc b/src/lte/model/lte-pdcp.cc index 1d1f2080c..b7e03a33b 100644 --- a/src/lte/model/lte-pdcp.cc +++ b/src/lte/model/lte-pdcp.cc @@ -184,8 +184,11 @@ LtePdcp::DoReceivePdu (Ptr p) { m_rxSequenceNumber = 0; } - - m_pdcpSapUser->ReceiveRrcPdu (p); + LtePdcpSapUser::ReceiveRrcPduParameters params; + params.rrcPdu = p; + params.rnti = m_rnti; + params.lcid = m_lcid; + m_pdcpSapUser->ReceiveRrcPdu (params); } diff --git a/src/lte/model/lte-radio-bearer-info.cc b/src/lte/model/lte-radio-bearer-info.cc new file mode 100644 index 000000000..8fbac0b94 --- /dev/null +++ b/src/lte/model/lte-radio-bearer-info.cc @@ -0,0 +1,64 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Nicola Baldo + */ + +#include "lte-radio-bearer-info.h" +#include "lte-ue-rrc.h" +#include "lte-rlc.h" +#include "lte-pdcp.h" + +#include + + + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (LteRadioBearerInfo); + +LteRadioBearerInfo::LteRadioBearerInfo (void) +{ +} + +LteRadioBearerInfo::~LteRadioBearerInfo (void) +{ +} + +TypeId LteRadioBearerInfo::GetTypeId (void) +{ + static TypeId + tid = + TypeId ("ns3::LteRadioBearerInfo") + .SetParent () + .AddConstructor () + .AddAttribute ("LteRlc", "RLC instance of the radio bearer.", + PointerValue (), + MakePointerAccessor (&LteRadioBearerInfo::m_rlc), + MakePointerChecker ()) + .AddAttribute ("LtePdcp", "PDCP instance of the radio bearer.", + PointerValue (), + MakePointerAccessor (&LteRadioBearerInfo::m_pdcp), + MakePointerChecker ()) + ; + return tid; +} + + + + +} // namespace ns3 diff --git a/src/lte/model/lte-radio-bearer-info.h b/src/lte/model/lte-radio-bearer-info.h new file mode 100644 index 000000000..4555174e9 --- /dev/null +++ b/src/lte/model/lte-radio-bearer-info.h @@ -0,0 +1,48 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Nicola Baldo + */ + + +#include +#include + +namespace ns3 { + +class LteRlc; +class LtePdcp; + +/** + * store information on active radio bearer instance + * + */ +class LteRadioBearerInfo : public Object +{ + +public: + LteRadioBearerInfo (void); + virtual ~LteRadioBearerInfo (void); + static TypeId GetTypeId (void); + + Ptr m_rlc; + Ptr m_pdcp; + +}; + + +} // namespace ns3 diff --git a/src/lte/model/lte-rlc.h b/src/lte/model/lte-rlc.h index 8f59c30d5..b515920bd 100644 --- a/src/lte/model/lte-rlc.h +++ b/src/lte/model/lte-rlc.h @@ -101,6 +101,8 @@ public: // TODO MRE What is the sense to duplicate all the interfaces here??? + // NB to avoid the use of multiple inheritance + protected: // Interface forwarded by LteRlcSapProvider virtual void DoTransmitPdcpPdu (Ptr p) = 0; diff --git a/src/lte/model/lte-ue-net-device.cc b/src/lte/model/lte-ue-net-device.cc index 7b2f89ab0..c6322f544 100644 --- a/src/lte/model/lte-ue-net-device.cc +++ b/src/lte/model/lte-ue-net-device.cc @@ -38,8 +38,8 @@ #include "ns3/ipv4-header.h" #include "ns3/ipv4.h" #include "lte-amc.h" -// #include "ideal-control-messages.h" #include +#include NS_LOG_COMPONENT_DEFINE ("LteUeNetDevice"); @@ -176,33 +176,13 @@ LteUeNetDevice::DoStart (void) m_rrc->Start (); } - bool -LteUeNetDevice::DoSend (Ptr packet, const Mac48Address& source, - const Mac48Address& dest, uint16_t protocolNumber) +LteUeNetDevice::Send (Ptr packet, const Address& dest, uint16_t protocolNumber) { - NS_LOG_FUNCTION (this); - - NS_FATAL_ERROR ("IP connectivity not implemented yet"); - - return (true); -} - - -void -LteUeNetDevice::DoReceive (Ptr p) -{ - NS_LOG_FUNCTION (this << p); - - NS_FATAL_ERROR ("IP connectivity not implemented yet"); - - Ptr packet = p->Copy (); - - LlcSnapHeader llcHdr; - packet->RemoveHeader (llcHdr); - NS_LOG_FUNCTION (this << llcHdr); - - ForwardUp (packet); + NS_LOG_FUNCTION (this << dest << protocolNumber); + NS_ASSERT_MSG (protocolNumber == Ipv4L3Protocol::PROT_NUMBER, "unsupported protocol " << protocolNumber << ", only IPv4 is supported"); + + return m_rrc->Send (packet); } diff --git a/src/lte/model/lte-ue-net-device.h b/src/lte/model/lte-ue-net-device.h index 664dd3a6e..2f4970b04 100644 --- a/src/lte/model/lte-ue-net-device.h +++ b/src/lte/model/lte-ue-net-device.h @@ -49,6 +49,7 @@ class LteUeRrc; */ class LteUeNetDevice : public LteNetDevice { + public: static TypeId GetTypeId (void); @@ -64,6 +65,10 @@ public: virtual void DoDispose (); + // inherited from NetDevice + virtual bool Send (Ptr packet, const Address& dest, uint16_t protocolNumber); + + Ptr GetMac (void); Ptr GetRrc (); @@ -90,13 +95,15 @@ protected: private: - bool DoSend (Ptr packet, - const Mac48Address& source, - const Mac48Address& dest, - uint16_t protocolNumber); - - void DoReceive (Ptr p); + /** + * Some attributes are exported as + * attributes of the LteUeNetDevice from a user perspective, but + * are actually used also in other modules as well (the RRC, the + * PHY...). This methods takes care of updating the + * configuration of all modules so that their copy of the attribute + * values is in sync with the one in the LteUeNetDevice. + */ void UpdateConfig (void); Ptr m_targetEnb; @@ -108,7 +115,7 @@ private: uint64_t m_imsi; static uint64_t m_imsiCounter; - + }; } // namespace ns3 diff --git a/src/lte/model/lte-ue-rrc.cc b/src/lte/model/lte-ue-rrc.cc index 40447ec7c..899102a3c 100644 --- a/src/lte/model/lte-ue-rrc.cc +++ b/src/lte/model/lte-ue-rrc.cc @@ -21,9 +21,13 @@ #include #include #include "ns3/object-map.h" +#include "ns3/object-factory.h" #include "lte-ue-rrc.h" #include "lte-rlc.h" +#include "lte-pdcp.h" +#include "lte-pdcp-sap.h" +#include "lte-radio-bearer-info.h" NS_LOG_COMPONENT_DEFINE ("LteUeRrc"); @@ -59,7 +63,29 @@ UeMemberLteUeCmacSapUser::LcConfigCompleted () } +//////////////////////////////// +// PDCP SAP Forwarder +//////////////////////////////// +// class UeRrcMemberLtePdcpSapUser : public LtePdcpSapUser +// { +// public: +// MemberLtePdcpSapUser (LteUeRrc* rrc); +// virtual void ReceiveRrcPdu (Ptr p); +// private: +// LteUeRrc* m_rrc;EnbRrc +// }; + + +// UeRrcMemberLtePdcpSapUser::UeRrcMemberLtePdcpSapUser (LteUeRrc* rrc) +// : m_rrc (rrc) +// { +// } + +// void UeRrcMemberLtePdcpSapUser::ReceiveRrcPdu (Ptr p) +// { +// m_rrc->DoReceiveRrcPdu (p); +// } @@ -77,6 +103,7 @@ LteUeRrc::LteUeRrc () { NS_LOG_FUNCTION (this); m_cmacSapUser = new UeMemberLteUeCmacSapUser (this); + m_pdcpSapUser = new LtePdcpSpecificLtePdcpSapUser (this); } @@ -90,7 +117,8 @@ LteUeRrc::DoDispose () { NS_LOG_FUNCTION (this); delete m_cmacSapUser; - m_rlcMap.clear (); + delete m_pdcpSapUser; + m_rbMap.clear (); } TypeId @@ -99,10 +127,10 @@ LteUeRrc::GetTypeId (void) static TypeId tid = TypeId ("ns3::LteUeRrc") .SetParent () .AddConstructor () - .AddAttribute ("RlcMap", "List of UE RadioBearerInfo by LCID.", + .AddAttribute ("RadioBearerMap", "List of UE RadioBearerInfo by LCID.", ObjectMapValue (), - MakeObjectMapAccessor (&LteUeRrc::m_rlcMap), - MakeObjectMapChecker ()) + MakeObjectMapAccessor (&LteUeRrc::m_rbMap), + MakeObjectMapChecker ()) .AddAttribute ("CellId", "Serving cell identifier", UintegerValue (1), @@ -150,21 +178,39 @@ LteUeRrc::ConfigureUe (uint16_t rnti, uint16_t cellId) } void -LteUeRrc::SetupRadioBearer (uint16_t rnti, EpsBearer bearer, uint8_t lcid) +LteUeRrc::SetupRadioBearer (uint16_t rnti, EpsBearer bearer, TypeId rlcTypeId, uint8_t lcid, Ptr tft) { NS_LOG_FUNCTION (this << (uint32_t) rnti << (uint32_t) lcid); - // create RLC instance - // for now we support RLC SM only - Ptr rlc = CreateObject (); + ObjectFactory rlcObjectFactory; + rlcObjectFactory.SetTypeId (rlcTypeId); + Ptr rlc = rlcObjectFactory.Create ()->GetObject (); rlc->SetLteMacSapProvider (m_macSapProvider); rlc->SetRnti (rnti); rlc->SetLcId (lcid); - std::map >::iterator it = m_rlcMap.find (lcid); - NS_ASSERT_MSG (it == m_rlcMap.end (), "bearer with same lcid already existing"); - m_rlcMap.insert (std::pair > (lcid, rlc)); + Ptr rbInfo = CreateObject (); + rbInfo->m_rlc = rlc; + // we need PDCP only for real RLC, i.e., RLC/UM or RLC/AM + // if we are using RLC/SM we don't care of anything above RLC + if (rlcTypeId != LteRlcSm::GetTypeId ()) + { + Ptr pdcp = CreateObject (); + pdcp->SetRnti (rnti); + pdcp->SetLcId (lcid); + pdcp->SetLtePdcpSapUser (m_pdcpSapUser); + pdcp->SetLteRlcSapProvider (rlc->GetLteRlcSapProvider ()); + rlc->SetLteRlcSapUser (pdcp->GetLteRlcSapUser ()); + rbInfo->m_pdcp = pdcp; + } + + NS_ASSERT_MSG (m_rbMap.find (lcid) == m_rbMap.end (), "bearer with same lcid already existing"); + m_rbMap.insert (std::pair > (lcid, rbInfo)); + + + m_tftClassifier.Add (tft, lcid); + m_cmacSapProvider->AddLc (lcid, rlc->GetLteMacSapUser ()); } @@ -172,11 +218,53 @@ void LteUeRrc::ReleaseRadioBearer (uint16_t rnti, uint8_t lcid) { NS_LOG_FUNCTION (this << (uint32_t) rnti << (uint32_t) lcid); - std::map >::iterator it = m_rlcMap.find (lcid); - NS_ASSERT_MSG (it != m_rlcMap.end (), "could not find bearer with given lcid"); - m_rlcMap.erase (it); + std::map >::iterator it = m_rbMap.find (lcid); + NS_ASSERT_MSG (it != m_rbMap.end (), "could not find bearer with given lcid"); + m_rbMap.erase (it); + NS_FATAL_ERROR ("need to remove entry from TFT classifier, but this is not implemented yet"); } + +bool +LteUeRrc::Send (Ptr packet) +{ + NS_LOG_FUNCTION (this << packet); + uint8_t lcid = m_tftClassifier.Classify (packet, LteTft::UPLINK); + LtePdcpSapProvider::TransmitRrcPduParameters params; + params.rrcPdu = packet; + params.rnti = m_rnti; + params.lcid = lcid; + std::map >::iterator it = m_rbMap.find (lcid); + if (it == m_rbMap.end ()) + { + NS_LOG_WARN ("could not find bearer with lcid == " << lcid); + return false; + } + else + { + it->second->m_pdcp->GetLtePdcpSapProvider ()->TransmitRrcPdu (params); + return true; + } +} + + +void +LteUeRrc::SetForwardUpCallback (Callback > cb) +{ + m_forwardUpCallback = cb; +} + + +void +LteUeRrc::DoReceiveRrcPdu (LtePdcpSapUser::ReceiveRrcPduParameters params) +{ + NS_LOG_FUNCTION (this); + m_forwardUpCallback (params.rrcPdu); +} + + + + void LteUeRrc::DoLcConfigCompleted () { @@ -202,7 +290,7 @@ std::vector LteUeRrc::GetLcIdVector () { std::vector v; - for (std::map >::iterator it = m_rlcMap.begin (); it != m_rlcMap.end (); ++it) + for (std::map >::iterator it = m_rbMap.begin (); it != m_rbMap.end (); ++it) { v.push_back (it->first); } diff --git a/src/lte/model/lte-ue-rrc.h b/src/lte/model/lte-ue-rrc.h index 74bd0c2cf..fd2582947 100644 --- a/src/lte/model/lte-ue-rrc.h +++ b/src/lte/model/lte-ue-rrc.h @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include @@ -33,7 +35,10 @@ class LteRlc; class LteMacSapProvider; class LteUeCmacSapUser; class LteUeCmacSapProvider; -class UeInfo; +class LteRadioBearerInfo; +class LtePdcpSapUser; +class LtePdcpSapProvider; + /** * @@ -43,6 +48,8 @@ class LteUeRrc : public Object { friend class UeMemberLteUeCmacSapUser; + friend class UeRrcMemberLteEnbCmacSapUser; + friend class LtePdcpSpecificLtePdcpSapUser; public: /** @@ -100,10 +107,12 @@ public: * * \param rnti the RNTI of the user * \param bearer the characteristics of the bearer to be activated + * \param rlcTypeId the TypeId identifying the type of RLC to be used for this bearer. * \param lcid the logical channel id allocated for this bearer by the eNB + * \param tft the Traffic Flow Template identifying this bearer * */ - void SetupRadioBearer (uint16_t rnti, EpsBearer bearer, uint8_t lcid); + void SetupRadioBearer (uint16_t rnti, EpsBearer bearer, TypeId rlcTypeId, uint8_t lcid, Ptr tft); /** @@ -135,20 +144,46 @@ public: */ std::vector GetLcIdVector (); + + /** + * Enqueue an IP packet on the proper bearer for uplink transmission + * + * \param p the packet + * + * \return true if successful, false if an error occurred + */ + bool Send (Ptr p); + + /** + * set the callback used to forward data packets up the stack + * + * \param void + * \param cb + */ + void SetForwardUpCallback (Callback > cb); + private: + + void DoReceiveRrcPdu (LtePdcpSapUser::ReceiveRrcPduParameters params); + // forwarded from CMAC SAP user void DoLcConfigCompleted (); + Callback > m_forwardUpCallback; + LteUeCmacSapUser* m_cmacSapUser; LteUeCmacSapProvider* m_cmacSapProvider; LteMacSapProvider* m_macSapProvider; + LtePdcpSapUser* m_pdcpSapUser; uint16_t m_rnti; uint16_t m_cellId; - std::map > m_rlcMap; - + std::map > m_rbMap; + + EpsTftClassifier m_tftClassifier; + }; diff --git a/src/lte/test/lte-test-entities.cc b/src/lte/test/lte-test-entities.cc index 63d8ec04e..2440406fc 100644 --- a/src/lte/test/lte-test-entities.cc +++ b/src/lte/test/lte-test-entities.cc @@ -90,9 +90,10 @@ LteTestRrc::GetDataReceived (void) */ void -LteTestRrc::DoReceiveRrcPdu (Ptr p) +LteTestRrc::DoReceiveRrcPdu (LtePdcpSapUser::ReceiveRrcPduParameters params) { NS_LOG_FUNCTION (this); + Ptr p = params.rrcPdu; NS_LOG_LOGIC ("PDU received = " << (*p)); uint32_t dataLen = p->GetSize (); diff --git a/src/lte/test/lte-test-entities.h b/src/lte/test/lte-test-entities.h index 9f03c2bd1..193879e72 100644 --- a/src/lte/test/lte-test-entities.h +++ b/src/lte/test/lte-test-entities.h @@ -70,7 +70,7 @@ class LteTestRrc : public Object private: // Interface forwarded by LtePdcpSapUser - virtual void DoReceiveRrcPdu (Ptr p); + virtual void DoReceiveRrcPdu (LtePdcpSapUser::ReceiveRrcPduParameters params); LtePdcpSapUser* m_pdcpSapUser; LtePdcpSapProvider* m_pdcpSapProvider; @@ -119,7 +119,7 @@ class LteTestPdcp : public Object private: // Interface forwarded by LteRlcSapUser - virtual void DoReceivePdcpPdu (Ptr p); + virtual void DoReceivePdcpPdu (Ptr p); LteRlcSapUser* m_rlcSapUser; LteRlcSapProvider* m_rlcSapProvider; diff --git a/src/lte/test/test-lte-epc-e2e-data.cc b/src/lte/test/test-lte-epc-e2e-data.cc new file mode 100644 index 000000000..f3f66f0fb --- /dev/null +++ b/src/lte/test/test-lte-epc-e2e-data.cc @@ -0,0 +1,267 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Nicola Baldo + */ + + + +#include "ns3/simulator.h" +#include "ns3/log.h" +#include "ns3/test.h" +#include "ns3/lena-helper.h" +#include "ns3/epc-helper.h" +#include "ns3/packet-sink-helper.h" +#include "ns3/udp-client-server-helper.h" +#include "ns3/point-to-point-helper.h" +#include "ns3/internet-stack-helper.h" +#include "ns3/ipv4-address-helper.h" +#include "ns3/inet-socket-address.h" +#include "ns3/packet-sink.h" +#include +#include +#include "ns3/boolean.h" +#include "ns3/uinteger.h" +#include "ns3/abort.h" +#include "ns3/mobility-helper.h" + + + + +namespace ns3 { + + +NS_LOG_COMPONENT_DEFINE ("LteEpcE2eData"); + + + +struct UeTestData +{ + UeTestData (uint32_t n, uint32_t s); + + uint32_t numPkts; + uint32_t pktSize; + EpsBearer epsBearer; + + Ptr serverApp; + Ptr clientApp; +}; + +UeTestData::UeTestData (uint32_t n, uint32_t s) + : numPkts (n), + pktSize (s), + epsBearer (EpsBearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT)) +{ +} + +struct EnbTestData +{ + std::vector ues; +}; + + +class LteEpcE2eDataTestCase : public TestCase +{ +public: + LteEpcE2eDataTestCase (std::string name, std::vector v); + virtual ~LteEpcE2eDataTestCase (); + +private: + virtual void DoRun (void); + std::vector m_enbTestData; +}; + + +LteEpcE2eDataTestCase::LteEpcE2eDataTestCase (std::string name, std::vector v) + : TestCase (name), + m_enbTestData (v) +{ +} + +LteEpcE2eDataTestCase::~LteEpcE2eDataTestCase () +{ +} + +void +LteEpcE2eDataTestCase::DoRun () +{ + + Ptr lteHelper = CreateObject (); + Ptr epcHelper = CreateObject (); + lteHelper->SetEpcHelper (epcHelper); + + Ptr pgw = epcHelper->GetPgwNode (); + + // Create a single RemoteHost + NodeContainer remoteHostContainer; + remoteHostContainer.Create (1); + Ptr remoteHost = remoteHostContainer.Get (0); + InternetStackHelper internet; + internet.Install (remoteHostContainer); + + // Create the internet + PointToPointHelper p2ph; + NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost); + Ipv4AddressHelper ipv4h; + ipv4h.SetBase ("1.0.0.0", "255.0.0.0"); + ipv4h.Assign (internetDevices); + + // setup default gateway for the remote hosts + Ipv4StaticRoutingHelper ipv4RoutingHelper; + Ptr remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject ()); + + // hardcoded UE addresses for now + remoteHostStaticRouting->AddNetworkRouteTo (Ipv4Address ("7.0.0.0"), Ipv4Mask ("255.255.255.0"), 1); + + + + NodeContainer enbs; + enbs.Create (m_enbTestData.size ()); + MobilityHelper mobility; + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + mobility.Install (enbs); + NetDeviceContainer enbLteDevs = lteHelper->InstallEnbDevice (enbs); + NetDeviceContainer::Iterator enbLteDevIt = enbLteDevs.Begin (); + + for (std::vector::iterator enbit = m_enbTestData.begin (); + enbit < m_enbTestData.end (); + ++enbit, ++enbLteDevIt) + { + NS_ABORT_IF (enbLteDevIt == enbLteDevs.End ()); + + NodeContainer ues; + ues.Create (enbit->ues.size ()); + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + mobility.Install (ues); + NetDeviceContainer ueLteDevs = lteHelper->InstallUeDevice (ues); + lteHelper->Attach (ueLteDevs, *enbLteDevIt); + + // we install the IP stack on the UEs + InternetStackHelper internet; + internet.Install (ues); + + + // assign IP address to UEs, and install applications + for (uint32_t u = 0; u < ues.GetN (); ++u) + { + Ptr ueLteDevice = ueLteDevs.Get (u); + Ipv4InterfaceContainer ueIpIface = epcHelper->AssignUeIpv4Address (NetDeviceContainer (ueLteDevice)); + + Ptr ue = ues.Get (u); + + uint16_t port = 1234; + PacketSinkHelper packetSinkHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), port)); + ApplicationContainer apps = packetSinkHelper.Install (ue); + apps.Start (Seconds (0.1)); + apps.Stop (Seconds (10.0)); + enbit->ues[u].serverApp = apps.Get (0)->GetObject (); + + Time interPacketInterval = Seconds (0.01); + UdpClientHelper client (ueIpIface.GetAddress (0), port); + client.SetAttribute ("MaxPackets", UintegerValue (enbit->ues[u].numPkts)); + client.SetAttribute ("Interval", TimeValue (interPacketInterval)); + client.SetAttribute ("PacketSize", UintegerValue (enbit->ues[u].pktSize)); + apps = client.Install (remoteHost); + apps.Start (Seconds (0.1)); + apps.Stop (Seconds (10.0)); + enbit->ues[u].clientApp = apps.Get (0); + + lteHelper->ActivateEpsBearer (ueLteDevice, enbit->ues[u].epsBearer, LteTft::Default ()); + + } + + } + + Simulator::Stop (Seconds (3.0)); + Simulator::Run (); + + for (std::vector::iterator enbit = m_enbTestData.begin (); + enbit < m_enbTestData.end (); + ++enbit) + { + for (std::vector::iterator ueit = enbit->ues.begin (); + ueit < enbit->ues.end (); + ++ueit) + { + NS_TEST_ASSERT_MSG_EQ (ueit->serverApp->GetTotalRx (), (ueit->numPkts) * (ueit->pktSize), "wrong total received bytes"); + } + } + + Simulator::Destroy (); +} + + + + + +/** + * Test that the S1-U interface implementation works correctly + */ +class LteEpcE2eDataTestSuite : public TestSuite +{ +public: + LteEpcE2eDataTestSuite (); + +} g_lteEpcE2eDataTestSuite; + +LteEpcE2eDataTestSuite::LteEpcE2eDataTestSuite () + : TestSuite ("lte-epc-e2e-data", SYSTEM) +{ + std::vector v1; + EnbTestData e1; + UeTestData f1 (1, 100); + e1.ues.push_back (f1); + v1.push_back (e1); + AddTestCase (new LteEpcE2eDataTestCase ("1 eNB, 1UE", v1)); + + + std::vector v2; + EnbTestData e2; + UeTestData f2_1 (1, 100); + e2.ues.push_back (f2_1); + UeTestData f2_2 (2, 200); + e2.ues.push_back (f2_2); + v2.push_back (e2); + AddTestCase (new LteEpcE2eDataTestCase ("1 eNB, 2UEs", v2)); + + + std::vector v3; + v3.push_back (e1); + v3.push_back (e2); + AddTestCase (new LteEpcE2eDataTestCase ("2 eNBs", v3)); + + + EnbTestData e3; + UeTestData f3_1 (3, 50); + e3.ues.push_back (f3_1); + UeTestData f3_2 (5, 1472); + e3.ues.push_back (f3_2); + UeTestData f3_3 (1, 1); + e3.ues.push_back (f3_2); + std::vector v4; + v4.push_back (e3); + v4.push_back (e1); + v4.push_back (e2); + AddTestCase (new LteEpcE2eDataTestCase ("3 eNBs with big packet", v4)); + + +} + + + +} // namespace ns3 + diff --git a/src/lte/wscript b/src/lte/wscript index 650e1a052..e9e118643 100644 --- a/src/lte/wscript +++ b/src/lte/wscript @@ -30,6 +30,7 @@ def build(bld): 'model/lte-pdcp.cc', 'model/lte-pdcp-header.cc', 'model/eps-bearer.cc', + 'model/lte-radio-bearer-info.cc', 'model/lte-net-device.cc', 'model/lte-enb-net-device.cc', 'model/lte-ue-net-device.cc', @@ -82,6 +83,7 @@ def build(bld): 'test/test-eps-tft-classifier.cc', 'test/epc-test-s1u-downlink.cc', 'test/epc-test-s1u-uplink.cc', + 'test/test-lte-epc-e2e-data.cc', ] headers = bld.new_task_gen('ns3header') @@ -113,6 +115,7 @@ def build(bld): 'model/lte-pdcp.h', 'model/lte-pdcp-header.h', 'model/eps-bearer.h', + 'model/lte-radio-bearer-info.h', 'model/lte-net-device.h', 'model/lte-enb-net-device.h', 'model/lte-ue-net-device.h',