diff --git a/src/lte/doc/source/lte-design.rst b/src/lte/doc/source/lte-design.rst index 0e336ed4d..68a65f41b 100644 --- a/src/lte/doc/source/lte-design.rst +++ b/src/lte/doc/source/lte-design.rst @@ -121,6 +121,7 @@ Architecture For the sake of an easier explanation, we further divide the LTE model in two separate parts, which are described in the following. +The overall architecture of the LTE module is represented in the following figures. The first part is the lower LTE radio protocol stack, which is represented in the figures @@ -649,6 +650,7 @@ where :math:`|\cdot|` indicates the cardinality of the set; finally, \widehat{T}_{j}(t) = \frac{S\left( \widehat{M}_j(t), \widehat{B}_j(t) \right)}{\tau} + Transport Blocks @@ -1277,10 +1279,26 @@ The model can be disabled for working with a zero-losses channel by setting the +MIMO Model +---------- + +The use of multiple antennas both at transmitter and receiver side, known as multiple-input and multiple-output (MIMO), is a problem well studied in literature during the past years. Most of the work concentrate on evaluating analytically the gain that the different MIMO schemes might have in term of capacity; however someones provide also information of the gain in terms of received power _[CatreuxMIMO]. + +According to the considerations above, a model more flexible can be obtained considering the gain that MIMO schemes bring in the system from a statistical point of view. As highlighted before, _[CatreuxMIMO] presents the statistical gain of several MIMO solutions respect to the SISO one. In the work the gain is presented as the cumulative distribution function (CDF) of the output SINR for what concern SISO, MIMO-Alamouti, MIMO-MMSE, MIMO-OSIC-MMSE and MIMO-ZF schemes. Elaborating the results, the output SINR distribution can be approximated with a log-normal one with different mean and variance as function of the scheme considered. However, the variances are not so different and they are approximatively equal to the one of the SISO mode already included in the shadowing component of the ``BuildingsPropagationLossModel``, in detail: + + * SISO: :math:`\mu = 13.5` and :math:`\sigma = 20` [dB]. + * MIMO-Alamouti: :math:`\mu = 17.7` and :math:`\sigma = 11.1` [dB]. + * MIMO-MMSE: :math:`\mu = 10.7` and :math:`\sigma = 16.6` [dB]. + * MIMO-OSIC-MMSE: :math:`\mu = 12.6` and :math:`\sigma = 15.5` [dB]. + * MIMO-ZF: :math:`\mu = 10.3` and :math:`\sigma = 12.6` [dB]. +Therefore the PHY layer implements the MIMO model as the gain perceived by the receiver when using a MIMO scheme respect to the one obtained using SISO one. This allows to reuse the SISO PHY error model and the fading tracing scheme and apply the MIMO model in a transparent way. Moreover, new MIMO schemes can be integrated by updating the gain considered according to their statistical behavior. On this matter, considering the MIMO model defined in the standard (i.e., spatial multiplexing and transmit diversity _[TS36.211]), the gains included are: + * MIMO-Alamouti: :math:`+4.2` [dB]. + * MIMO-MMSE: :math:`-2.8` [dB]. +where MIMO-Alamouti is a transmit diversity scheme, while MIMO-MMSE is an implementation of spatial multiplexity. diff --git a/src/lte/doc/source/lte-references.rst b/src/lte/doc/source/lte-references.rst index a20c2cb69..d3a1b64ab 100644 --- a/src/lte/doc/source/lte-references.rst +++ b/src/lte/doc/source/lte-references.rst @@ -72,3 +72,15 @@ .. [mathworks] Matlab R2011b Documentation Communications System Toolbox, `Methodology for Simulating Multipath Fading Channels `_ +.. [PaduaPEM] http://mailman.isi.edu/pipermail/ns-developers/2011-November/009559.html + +.. [Vienna] The Vienna LTE Simulators http://www.nt.tuwien.ac.at/about-us/staff/josep-colom-ikuno/lte-simulators/ + +.. [LozanoCost] Joan Olmos, Silvia Ruiz, Mario García-Lozano and David Martín-Sacristán, "Link Abstraction Models Based on Mutual Information for LTE Downlink", COST 2100 TD(10)11052 Report + +.. [CatreuxMIMO] S. Catreux, L.J. Greenstein, V. Erceg, "Some results and insights on the performance gains of MIMO systems," Selected Areas in Communications, IEEE Journal on , vol.21, no.5, pp. 839- 847, June 2003 + +.. [ViennaPaper] J.C. Ikuno, M. Wrulich, M. Rupp, "System Level Simulation of LTE Networks," Vehicular Technology Conference (VTC 2010-Spring), 2010 IEEE 71st , vol., no., pp.1-5, 16-19 May 2010 + +.. [TS36.211] 3GPP TS 36.211 "E-UTRA Physical Channels and Modulation" + diff --git a/src/lte/doc/source/lte-testing.rst b/src/lte/doc/source/lte-testing.rst index b68d57e17..80e6e3d8c 100644 --- a/src/lte/doc/source/lte-testing.rst +++ b/src/lte/doc/source/lte-testing.rst @@ -404,10 +404,18 @@ The parameters of the nine test cases are reported in the following: BLER for test 8. + The test verifies that in each case the expected number of packets received correct corresponds to a Bernoulli distribution with a confidence interval of 95%, where the probability of success in each trail is :math:`1-BER` and :math:`n` is the total number of packet sent. +MIMO Model +---------- +The test suite ``lte-mimo`` aims at verifying both the effect of the gain considered for each Transmission Mode on the system performance and the Transmission Mode switching through the scheduler interface. The test consists on checking whether the amount of bytes received during a certain window of time (0.1 seconds in our case) corresponds to the expected ones according to the values of transport block +size reported in table 7.1.7.2.1-1 of [TS36.213]_, similarly to what done for the tests of the schedulers. + +The test is performed both for Round Robin and Proportional Fair schedulers. The test passes if the measured throughput matches with the reference throughput within a relative tolerance of 0.1. This tolerance is needed to account for the +transient behavior at the beginning of the simulation and the transition phase between the Transmission Modes. Antenna Model integration diff --git a/src/lte/doc/source/lte-user.rst b/src/lte/doc/source/lte-user.rst index b38d11f28..6365e4eb1 100644 --- a/src/lte/doc/source/lte-user.rst +++ b/src/lte/doc/source/lte-user.rst @@ -439,6 +439,41 @@ This positions the node on the scenario. Note that, in this example, node 0 will This command will go through the lists of all nodes and of all buildings, determine for each user if it is indoor or outdoor, and if indoor it will also determine the building in which the user is located and the corresponding floor and number inside the building. +MIMO Model +---------- + +Is this subsection we illustrate how to configure the MIMO parameters. LTE defines 7 types of transmission modes: + + * Transmission Mode 1: SISO. + * Transmission Mode 2: MIMO Tx Diversity. + * Transmission Mode 3: MIMO Spatial Multiplexity Open Loop. + * Transmission Mode 4: MIMO Spatial Multiplexity Closed Loop. + * Transmission Mode 5: MIMO Multi-User. + * Transmission Mode 6: Closer loop single layer precoding. + * Transmission Mode 7: Single antenna port 5. + +According to model implemented, the simulator includes the first three transmission modes types. The default one is the Transmission Mode 1 (SISO). In order to change the default Transmission Mode to be used, the attribute ``DefaultTransmissionMode`` of the ``LteEnbRrc`` can be used, as shown in the following:: + + Config::SetDefault ("ns3::LteEnbRrc::DefaultTransmissionMode", UintegerValue (0)); // SISO + Config::SetDefault ("ns3::LteEnbRrc::DefaultTransmissionMode", UintegerValue (1)); // MIMO Tx diversity (1 layer) + Config::SetDefault ("ns3::LteEnbRrc::DefaultTransmissionMode", UintegerValue (2)); // MIMO Spatial Multiplexity (2 layers) + +For changing the transmission mode of a certain user during the simulation a specific interface has been implemented in both standard schedulers:: + + void TransmissionModeConfigurationUpdate (uint16_t rnti, uint8_t txMode); + +This method can be used both for developing transmission mode decision engine (i.e., for optimizing the transmission mode according to channel condition and/or user's requirements) and for manual switching from simulation script. In the latter case, the switching can be done as shown in the following:: + + Ptr lteEnbDev = enbDevs.Get (0)->GetObject (); + PointerValue ptrval; + enbNetDev->GetAttribute ("FfMacScheduler", ptrval); + Ptr rrsched = ptrval.Get (); + Simulator::Schedule (Seconds (0.2), &RrFfMacScheduler::TransmissionModeConfigurationUpdate, rrsched, rnti, 1); + +Finally, the model implemented can be reconfigured according to different MIMO models by updating the gain values (the only constraints is that the gain has to be constant during simulation run-time and common for the layers). The gain of each Transmission Mode can be changed according to the standard ns3 attribute system, where the attributes are: ``TxMode1Gain``, ``TxMode2Gain``, ``TxMode3Gain``, ``TxMode4Gain``, ``TxMode5Gain``, ``TxMode6Gain`` and ``TxMode7Gain``. By default only ``TxMode1Gain``, ``TxMode2Gain`` and ``TxMode3Gain`` have a meaningful value, that are the ones derived by _[CatreuxMIMO] (i.e., respectively 0.0, 4.2 and -2.8 dB). + + + diff --git a/src/lte/model/lte-common.cc b/src/lte/model/lte-common.cc index f98a073e4..77d32807c 100644 --- a/src/lte/model/lte-common.cc +++ b/src/lte/model/lte-common.cc @@ -74,6 +74,25 @@ operator < (const ImsiLcidPair_t& a, const ImsiLcidPair_t& b) } +LteUeConfig_t::LteUeConfig_t () +{ +} + + + +bool +operator == (const LteUeConfig_t &a, const LteUeConfig_t &b) +{ + return (a.m_rnti == b.m_rnti); +} + +bool +operator < (const LteUeConfig_t& a, const LteUeConfig_t& b) +{ + return (a.m_rnti < b.m_rnti); +} + + uint16_t LteFfConverter::double2fpS11dot3 (double val) { @@ -147,5 +166,37 @@ BufferSizeLevelBsr::BufferSize2BsrId (uint32_t val) } +uint8_t +TransmissionModesLayers::TxMode2LayerNum (uint8_t txMode) +{ + uint8_t nLayer = 0; + switch (txMode) + { + case 0: // Tx MODE 1: SISO + nLayer = 1; + break; + case 1: // Tx MODE 2: MIMO Tx Diversity + nLayer = 1; + break; + case 2: // Tx MODE 3: MIMO Spatial Multiplexity Open Loop + nLayer = 2; + break; + case 3: // Tx MODE 4: MIMO Spatial Multiplexity Closed Loop + nLayer = 2; + break; + case 4: // Tx MODE 5: MIMO Multi-User + nLayer = 2; + break; + case 5: // Tx MODE 6: Closer loop single layer percoding + nLayer = 1; + break; + case 6: // Tx MODE 7: Single antenna port 5 + nLayer = 1; + break; + } + return (nLayer); +} + + }; // namespace ns3 diff --git a/src/lte/model/lte-common.h b/src/lte/model/lte-common.h index 1911102e9..de0751451 100644 --- a/src/lte/model/lte-common.h +++ b/src/lte/model/lte-common.h @@ -53,6 +53,19 @@ public: friend bool operator < (const ImsiLcidPair_t &a, const ImsiLcidPair_t &b); }; +struct LteUeConfig_t +{ + uint16_t m_rnti; + uint8_t m_transmissionMode; + + public: + LteUeConfig_t (); + + friend bool operator == (const LteUeConfig_t &a, const LteUeConfig_t &b); + friend bool operator < (const LteUeConfig_t &a, const LteUeConfig_t &b); +}; + + class LteFfConverter { @@ -78,6 +91,12 @@ class BufferSizeLevelBsr }; +class TransmissionModesLayers +{ + public: + static uint8_t TxMode2LayerNum (uint8_t txMode); +}; + }; // namespace ns3 diff --git a/src/lte/model/lte-enb-cmac-sap.h b/src/lte/model/lte-enb-cmac-sap.h index 5a5059ee4..e6acc9c17 100644 --- a/src/lte/model/lte-enb-cmac-sap.h +++ b/src/lte/model/lte-enb-cmac-sap.h @@ -16,6 +16,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Nicola Baldo + * Marco Miozzo */ #ifndef LTE_ENB_CMAC_SAP_H @@ -24,6 +25,8 @@ #include #include #include +#include +#include namespace ns3 { @@ -94,6 +97,8 @@ public: * \param lcid */ virtual void ReleaseLc (uint16_t rnti, uint8_t lcid) = 0; + + virtual void RrcUpdateConfigurationReq (FfMacCschedSapProvider::CschedUeConfigReqParameters params) = 0; }; @@ -118,6 +123,7 @@ public: * \param success true if the operation was successful, false otherwise */ virtual void NotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success) = 0; + virtual void RrcConfigurationUpdateInd (LteUeConfig_t params) = 0; }; diff --git a/src/lte/model/lte-enb-mac.cc b/src/lte/model/lte-enb-mac.cc index 87ecd6d38..8835cfc5b 100644 --- a/src/lte/model/lte-enb-mac.cc +++ b/src/lte/model/lte-enb-mac.cc @@ -34,6 +34,7 @@ #include #include "ns3/lte-mac-sap.h" +#include NS_LOG_COMPONENT_DEFINE ("LteEnbMac"); @@ -61,6 +62,7 @@ public: virtual void AddLc (LcInfo lcinfo, LteMacSapUser* msu); virtual void ReconfigureLc (LcInfo lcinfo); virtual void ReleaseLc (uint16_t rnti, uint8_t lcid); + virtual void RrcUpdateConfigurationReq (FfMacCschedSapProvider::CschedUeConfigReqParameters params); private: LteEnbMac* m_mac; @@ -102,6 +104,12 @@ EnbMacMemberLteEnbCmacSapProvider::ReleaseLc (uint16_t rnti, uint8_t lcid) m_mac->DoReleaseLc (rnti, lcid); } +void +EnbMacMemberLteEnbCmacSapProvider::RrcUpdateConfigurationReq (FfMacCschedSapProvider::CschedUeConfigReqParameters params) +{ + m_mac->DoRrcUpdateConfigurationReq (params); +} + class EnbMacMemberFfMacSchedSapUser : public FfMacSchedSapUser @@ -660,7 +668,7 @@ void LteEnbMac::DoTransmitPdu (LteMacSapProvider::TransmitPduParameters params) { NS_LOG_FUNCTION (this); - LteRadioBearerTag tag (params.rnti, params.lcid); + LteRadioBearerTag tag (params.rnti, params.lcid, params.layer); params.pdu->AddPacketTag (tag); // Ptr pb = CreateObject (); // pb->AddPacket (params.pdu); @@ -709,7 +717,8 @@ LteEnbMac::DoSchedDlConfigInd (FfMacSchedSapUser::SchedDlConfigIndParameters ind ind.m_buildDataList.at (i).m_rlcPduList.at (j).at (k).m_logicalChannelIdentity); it = m_rlcAttached.find (flow); NS_ASSERT_MSG (it != m_rlcAttached.end (), "rnti=" << flow.m_rnti << " lcid=" << (uint32_t) flow.m_lcId); - (*it).second->NotifyTxOpportunity (ind.m_buildDataList.at (i).m_rlcPduList.at (j).at (k).m_size); + NS_LOG_DEBUG (this << " rnti= " << flow.m_rnti << " lcid= " << (uint32_t) flow.m_lcId << " layer= " << k); + (*it).second->NotifyTxOpportunity (ind.m_buildDataList.at (i).m_rlcPduList.at (j).at (k).m_size, k); } } // send the relative DCI @@ -817,6 +826,24 @@ void LteEnbMac::DoCschedUeConfigUpdateInd (FfMacCschedSapUser::CschedUeConfigUpdateIndParameters params) { NS_LOG_FUNCTION (this); + // propagates to RRC + LteUeConfig_t ueConfigUpdate; + ueConfigUpdate.m_rnti = params.m_rnti; + ueConfigUpdate.m_transmissionMode = params.m_transmissionMode; + m_cmacSapUser->RrcConfigurationUpdateInd (ueConfigUpdate); +} + +void +LteEnbMac::DoRrcUpdateConfigurationReq (FfMacCschedSapProvider::CschedUeConfigReqParameters params) +{ + NS_LOG_FUNCTION (this); + // propagates to PHY layer + m_enbPhySapProvider->SetTransmissionMode (params.m_rnti, params.m_transmissionMode); + // propagates to scheduler + FfMacCschedSapProvider::CschedUeConfigReqParameters req; + req.m_rnti = params.m_rnti; + req.m_transmissionMode = params.m_transmissionMode; + m_cschedSapProvider->CschedUeConfigReq (req); } void diff --git a/src/lte/model/lte-enb-mac.h b/src/lte/model/lte-enb-mac.h index f0d75d345..8d3a45ddb 100644 --- a/src/lte/model/lte-enb-mac.h +++ b/src/lte/model/lte-enb-mac.h @@ -162,6 +162,8 @@ private: // forwarded from FfMacSchedSapUser void DoSchedDlConfigInd (FfMacSchedSapUser::SchedDlConfigIndParameters ind); void DoSchedUlConfigInd (FfMacSchedSapUser::SchedUlConfigIndParameters params); + + void DoRrcUpdateConfigurationReq (FfMacCschedSapProvider::CschedUeConfigReqParameters params); /** * \brief Forwarded from LteEnbPhySapUser: trigger the start from a new frame diff --git a/src/lte/model/lte-enb-phy-sap.h b/src/lte/model/lte-enb-phy-sap.h index 1759e75fe..72a6e87f7 100644 --- a/src/lte/model/lte-enb-phy-sap.h +++ b/src/lte/model/lte-enb-phy-sap.h @@ -53,6 +53,12 @@ public: * \param dlBandwidth the DL bandwidth in RB */ virtual void SetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth) = 0; + + /** + * \param rnti the RNTI of the user + * \param txMode the transmissionMode of the user + */ + virtual void SetTransmissionMode (uint16_t rnti, uint8_t txMode) = 0; /** * diff --git a/src/lte/model/lte-enb-phy.cc b/src/lte/model/lte-enb-phy.cc index 3a8270685..8f82b8338 100644 --- a/src/lte/model/lte-enb-phy.cc +++ b/src/lte/model/lte-enb-phy.cc @@ -56,6 +56,8 @@ public: virtual void SetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth); virtual void SetCellId (uint16_t cellId); virtual void SendIdealControlMessage (Ptr msg); + virtual void SetTransmissionMode (uint16_t rnti, uint8_t txMode); + private: LteEnbPhy* m_phy; @@ -91,6 +93,12 @@ EnbMemberLteEnbPhySapProvider::SendIdealControlMessage (Ptr m_phy->DoSendIdealControlMessage (msg); } +void +EnbMemberLteEnbPhySapProvider::SetTransmissionMode (uint16_t rnti, uint8_t txMode) +{ + m_phy->DoSetTransmissionMode (rnti, txMode); +} + //////////////////////////////////////// // generic LteEnbPhy methods @@ -407,7 +415,7 @@ LteEnbPhy::StartSubFrame (void) { rbMap.push_back (i); } - m_uplinkSpectrumPhy->AddExpectedTb (dci->GetDci ().m_rnti, dci->GetDci ().m_tbSize, dci->GetDci ().m_mcs, rbMap); + m_uplinkSpectrumPhy->AddExpectedTb (dci->GetDci ().m_rnti, dci->GetDci ().m_tbSize, dci->GetDci ().m_mcs, rbMap, 0 /* always SISO*/); } } ctrlMsg.pop_front (); @@ -493,4 +501,12 @@ LteEnbPhy::CreateUlCqiReport (const SpectrumValue& sinr) } +void +LteEnbPhy::DoSetTransmissionMode (uint16_t rnti, uint8_t txMode) +{ + NS_LOG_FUNCTION (this << rnti << (uint16_t)txMode); + // UL supports only SISO MODE +} + + }; diff --git a/src/lte/model/lte-enb-phy.h b/src/lte/model/lte-enb-phy.h index 380fc2cb2..cd94de1a9 100644 --- a/src/lte/model/lte-enb-phy.h +++ b/src/lte/model/lte-enb-phy.h @@ -151,6 +151,8 @@ public: bool AddUePhy (uint16_t rnti, Ptr phy); bool DeleteUePhy (uint16_t rnti); + + virtual void DoSetTransmissionMode (uint16_t rnti, uint8_t txMode); /** @@ -187,6 +189,7 @@ private: uint32_t m_nrFrames; uint32_t m_nrSubFrames; + }; diff --git a/src/lte/model/lte-enb-rrc.cc b/src/lte/model/lte-enb-rrc.cc index b3ad11f6b..9252cd434 100644 --- a/src/lte/model/lte-enb-rrc.cc +++ b/src/lte/model/lte-enb-rrc.cc @@ -16,6 +16,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Nicola Baldo + * Marco Miozzo */ #include @@ -32,6 +33,13 @@ #include "lte-radio-bearer-info.h" #include "lte-radio-bearer-tag.h" #include "ns3/object-map.h" +#include + +// WILD HACK for UE-RRC direct communications +#include +#include +#include +#include NS_LOG_COMPONENT_DEFINE ("LteEnbRrc"); @@ -52,6 +60,7 @@ public: EnbRrcMemberLteEnbCmacSapUser (LteEnbRrc* rrc); virtual void NotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success); + virtual void RrcConfigurationUpdateInd (LteUeConfig_t params); private: LteEnbRrc* m_rrc; @@ -68,6 +77,12 @@ EnbRrcMemberLteEnbCmacSapUser::NotifyLcConfigResult (uint16_t rnti, uint8_t lcid m_rrc->DoNotifyLcConfigResult (rnti, lcid, success); } +void +EnbRrcMemberLteEnbCmacSapUser::RrcConfigurationUpdateInd (LteUeConfig_t params) +{ + m_rrc->DoRrcConfigurationUpdateInd (params); +} + //////////////////////////////// // PDCP SAP Forwarder @@ -231,6 +246,12 @@ LteEnbRrc::GetTypeId (void) ObjectMapValue (), MakeObjectMapAccessor (&LteEnbRrc::m_ueMap), MakeObjectMapChecker ()) + .AddAttribute ("DefaultTransmissionMode", + "The default UEs' transmission mode (0: SISO)", + UintegerValue (0), // default tx-mode + MakeUintegerAccessor (&LteEnbRrc::m_defaultTransmissionMode), + MakeUintegerChecker ()) + ; return tid; } @@ -367,6 +388,12 @@ LteEnbRrc::SetupRadioBearer (uint16_t rnti, EpsBearer bearer, TypeId rlcTypeId) lcinfo.gbrUl = bearer.gbrQosInfo.gbrUl; lcinfo.gbrDl = bearer.gbrQosInfo.gbrDl; m_cmacSapProvider->AddLc (lcinfo, rlc->GetLteMacSapUser ()); + + // Transmission mode settings + LteUeConfig_t ueConfig; + ueConfig.m_rnti = rnti; + ueConfig.m_transmissionMode = m_defaultTransmissionMode; + DoRrcConfigurationUpdateInd (ueConfig); return lcid; } @@ -474,6 +501,49 @@ LteEnbRrc::RemoveUeInfo (uint16_t rnti) } +void +LteEnbRrc::DoRrcConfigurationUpdateInd (LteUeConfig_t params) +{ + NS_LOG_FUNCTION (this); + // up tp now only for TxMode change + // update the peer UE-RRC on the change + NodeList::Iterator listEnd = NodeList::End (); + bool done = false; + for (NodeList::Iterator i = NodeList::Begin (); i != listEnd; i++) + { + Ptr node = *i; + int nDevs = node->GetNDevices (); + for (int j = 0; j < nDevs; j++) + { + Ptr uedev = node->GetDevice (j)->GetObject (); + if (!uedev) + { + continue; + } + else + { + Ptr ueRrc = uedev->GetRrc (); + if (ueRrc->GetRnti () == params.m_rnti) + { + ueRrc->DoRrcConfigurationUpdateInd (params); + done = true; + } + else + { + continue; + } + } + } + } + NS_ASSERT_MSG (done , " Unable to find peer UE-RRC, RNTI " << params.m_rnti); + // answer to MAC (and scheduler) + FfMacCschedSapProvider::CschedUeConfigReqParameters req; + req.m_rnti = params.m_rnti; + req.m_transmissionMode = params.m_transmissionMode; + m_cmacSapProvider->RrcUpdateConfigurationReq (req); + +} + diff --git a/src/lte/model/lte-enb-rrc.h b/src/lte/model/lte-enb-rrc.h index cd2a4bb08..39bce0380 100644 --- a/src/lte/model/lte-enb-rrc.h +++ b/src/lte/model/lte-enb-rrc.h @@ -222,7 +222,8 @@ public: private: void DoReceiveRrcPdu (LtePdcpSapUser::ReceiveRrcPduParameters params); - + void DoRrcConfigurationUpdateInd (LteUeConfig_t params); + void DoNotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success); LtePdcpSapProvider* GetLtePdcpSapProvider (uint16_t rnti, uint8_t lcid); @@ -244,6 +245,8 @@ private: uint16_t m_lastAllocatedRnti; std::map > m_ueMap; + + uint8_t m_defaultTransmissionMode; }; diff --git a/src/lte/model/lte-mac-sap.h b/src/lte/model/lte-mac-sap.h index 0fb620e01..b77b37339 100644 --- a/src/lte/model/lte-mac-sap.h +++ b/src/lte/model/lte-mac-sap.h @@ -47,6 +47,7 @@ public: Ptr pdu; /**< the RLC PDU */ uint16_t rnti; /**< the C-RNTI identifying the UE */ uint8_t lcid; /**< the logical channel id corresponding to the sending RLC instance */ + uint8_t layer; /**< the layer value that was passed by the MAC in the call to NotifyTxOpportunity that generated this PDU */ }; /** @@ -98,8 +99,9 @@ public: * transmission opportunity to this RLC instance. * * \param bytes the number of bytes to transmit + * \param layer the layer of transmission (MIMO) */ - virtual void NotifyTxOpportunity (uint32_t bytes) = 0; + virtual void NotifyTxOpportunity (uint32_t bytes, uint8_t layer) = 0; /** * Called by the MAC to notify the RLC that an HARQ process related diff --git a/src/lte/model/lte-radio-bearer-tag.cc b/src/lte/model/lte-radio-bearer-tag.cc index d0ac726fe..bebf7e58a 100644 --- a/src/lte/model/lte-radio-bearer-tag.cc +++ b/src/lte/model/lte-radio-bearer-tag.cc @@ -53,7 +53,8 @@ LteRadioBearerTag::GetInstanceTypeId (void) const LteRadioBearerTag::LteRadioBearerTag () : m_rnti (0), - m_lcid (0) + m_lcid (0), + m_layer (0) { } LteRadioBearerTag::LteRadioBearerTag (uint16_t rnti, uint8_t lcid) @@ -62,6 +63,13 @@ LteRadioBearerTag::LteRadioBearerTag (uint16_t rnti, uint8_t lcid) { } +LteRadioBearerTag::LteRadioBearerTag (uint16_t rnti, uint8_t lcid, uint8_t layer) +: m_rnti (rnti), + m_lcid (lcid), + m_layer (layer) +{ +} + void LteRadioBearerTag::SetRnti (uint16_t rnti) { @@ -74,6 +82,12 @@ LteRadioBearerTag::SetLcid (uint8_t lcid) m_lcid = lcid; } +void +LteRadioBearerTag::SetLayer (uint8_t layer) +{ + m_layer = layer; +} + uint32_t LteRadioBearerTag::GetSerializedSize (void) const { @@ -106,6 +120,12 @@ LteRadioBearerTag::GetLcid () const return m_lcid; } +uint8_t +LteRadioBearerTag::GetLayer () const +{ + return m_layer; +} + void LteRadioBearerTag::Print (std::ostream &os) const { diff --git a/src/lte/model/lte-radio-bearer-tag.h b/src/lte/model/lte-radio-bearer-tag.h index 9a42e0f27..61383fb57 100644 --- a/src/lte/model/lte-radio-bearer-tag.h +++ b/src/lte/model/lte-radio-bearer-tag.h @@ -46,6 +46,11 @@ public: * Create a LteRadioBearerTag with the given RNTI and LC id */ LteRadioBearerTag (uint16_t rnti, uint8_t lcId); + + /** + * Create a LteRadioBearerTag with the given RNTI, LC id and layer + */ + LteRadioBearerTag (uint16_t rnti, uint8_t lcId, uint8_t layer); /** * Set the RNTI to the given value. @@ -60,6 +65,13 @@ public: * @param lcid the value of the RNTI to set */ void SetLcid (uint8_t lcid); + + /** + * Set the layer id to the given value. + * + * @param layer the value of the layer to set + */ + void SetLayer (uint8_t lcid); virtual void Serialize (TagBuffer i) const; @@ -69,10 +81,12 @@ public: uint16_t GetRnti (void) const; uint8_t GetLcid (void) const; + uint8_t GetLayer (void) const; private: uint16_t m_rnti; uint8_t m_lcid; + uint8_t m_layer; }; diff --git a/src/lte/model/lte-rlc-am.cc b/src/lte/model/lte-rlc-am.cc index 812fb3132..be1fb4f0b 100644 --- a/src/lte/model/lte-rlc-am.cc +++ b/src/lte/model/lte-rlc-am.cc @@ -162,7 +162,7 @@ LteRlcAm::DoTransmitPdcpPdu (Ptr p) */ void -LteRlcAm::DoNotifyTxOpportunity (uint32_t bytes) +LteRlcAm::DoNotifyTxOpportunity (uint32_t bytes, uint8_t layer) { NS_LOG_FUNCTION (this << bytes); NS_ASSERT_MSG (bytes > 2, "Tx opportunity too small = " << bytes); @@ -500,6 +500,7 @@ LteRlcAm::DoNotifyTxOpportunity (uint32_t bytes) params.pdu = packet; params.rnti = m_rnti; params.lcid = m_lcid; + params.layer = layer; m_macSapProvider->TransmitPdu (params); } diff --git a/src/lte/model/lte-rlc-am.h b/src/lte/model/lte-rlc-am.h index 587daf4c9..1686cf867 100644 --- a/src/lte/model/lte-rlc-am.h +++ b/src/lte/model/lte-rlc-am.h @@ -48,7 +48,7 @@ public: /** * MAC SAP */ - virtual void DoNotifyTxOpportunity (uint32_t bytes); + virtual void DoNotifyTxOpportunity (uint32_t bytes, uint8_t layer); virtual void DoNotifyHarqDeliveryFailure (); virtual void DoReceivePdu (Ptr p); diff --git a/src/lte/model/lte-rlc-um.cc b/src/lte/model/lte-rlc-um.cc index 511973203..f16dedaf8 100644 --- a/src/lte/model/lte-rlc-um.cc +++ b/src/lte/model/lte-rlc-um.cc @@ -98,7 +98,7 @@ LteRlcUm::DoTransmitPdcpPdu (Ptr p) */ void -LteRlcUm::DoNotifyTxOpportunity (uint32_t bytes) +LteRlcUm::DoNotifyTxOpportunity (uint32_t bytes, uint8_t layer) { NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << bytes); @@ -354,6 +354,7 @@ LteRlcUm::DoNotifyTxOpportunity (uint32_t bytes) params.pdu = packet; params.rnti = m_rnti; params.lcid = m_lcid; + params.layer = layer; m_macSapProvider->TransmitPdu (params); diff --git a/src/lte/model/lte-rlc-um.h b/src/lte/model/lte-rlc-um.h index 6d151726e..11a53e4b1 100644 --- a/src/lte/model/lte-rlc-um.h +++ b/src/lte/model/lte-rlc-um.h @@ -47,7 +47,7 @@ public: /** * MAC SAP */ - virtual void DoNotifyTxOpportunity (uint32_t bytes); + virtual void DoNotifyTxOpportunity (uint32_t bytes, uint8_t layer); virtual void DoNotifyHarqDeliveryFailure (); virtual void DoReceivePdu (Ptr p); diff --git a/src/lte/model/lte-rlc.cc b/src/lte/model/lte-rlc.cc index ee27277d2..a499fa137 100644 --- a/src/lte/model/lte-rlc.cc +++ b/src/lte/model/lte-rlc.cc @@ -42,7 +42,7 @@ public: LteRlcSpecificLteMacSapUser (LteRlc* rlc); // Interface implemented from LteMacSapUser - virtual void NotifyTxOpportunity (uint32_t bytes); + virtual void NotifyTxOpportunity (uint32_t bytes, uint8_t layer); virtual void NotifyHarqDeliveryFailure (); virtual void ReceivePdu (Ptr p); @@ -61,9 +61,9 @@ LteRlcSpecificLteMacSapUser::LteRlcSpecificLteMacSapUser () } void -LteRlcSpecificLteMacSapUser::NotifyTxOpportunity (uint32_t bytes) +LteRlcSpecificLteMacSapUser::NotifyTxOpportunity (uint32_t bytes, uint8_t layer) { - m_rlc->DoNotifyTxOpportunity (bytes); + m_rlc->DoNotifyTxOpportunity (bytes, layer); } void @@ -210,13 +210,14 @@ LteRlcSm::DoReceivePdu (Ptr p) } void -LteRlcSm::DoNotifyTxOpportunity (uint32_t bytes) +LteRlcSm::DoNotifyTxOpportunity (uint32_t bytes, uint8_t layer) { NS_LOG_FUNCTION (this << bytes); LteMacSapProvider::TransmitPduParameters params; params.pdu = Create (bytes); params.rnti = m_rnti; params.lcid = m_lcid; + params.layer = layer; // RLC Performance evaluation RlcTag tag (Simulator::Now()); diff --git a/src/lte/model/lte-rlc.h b/src/lte/model/lte-rlc.h index 3cd531084..2e0c0d49e 100644 --- a/src/lte/model/lte-rlc.h +++ b/src/lte/model/lte-rlc.h @@ -111,7 +111,7 @@ protected: LteRlcSapProvider* m_rlcSapProvider; // Interface forwarded by LteMacSapUser - virtual void DoNotifyTxOpportunity (uint32_t bytes) = 0; + virtual void DoNotifyTxOpportunity (uint32_t bytes, uint8_t layer) = 0; virtual void DoNotifyHarqDeliveryFailure () = 0; virtual void DoReceivePdu (Ptr p) = 0; @@ -150,7 +150,7 @@ public: static TypeId GetTypeId (void); virtual void DoTransmitPdcpPdu (Ptr p); - virtual void DoNotifyTxOpportunity (uint32_t bytes); + virtual void DoNotifyTxOpportunity (uint32_t bytes, uint8_t layer); virtual void DoNotifyHarqDeliveryFailure (); virtual void DoReceivePdu (Ptr p); diff --git a/src/lte/model/lte-spectrum-phy.cc b/src/lte/model/lte-spectrum-phy.cc index 3c55176d9..21527fd18 100644 --- a/src/lte/model/lte-spectrum-phy.cc +++ b/src/lte/model/lte-spectrum-phy.cc @@ -36,20 +36,48 @@ #include #include #include +#include NS_LOG_COMPONENT_DEFINE ("LteSpectrumPhy"); namespace ns3 { + + +TbId_t::TbId_t () +{ +} +TbId_t::TbId_t (const uint16_t a, const uint8_t b) +: m_rnti (a), + m_layer (b) +{ +} + +bool +operator == (const TbId_t &a, const TbId_t &b) +{ + return ( (a.m_rnti == b.m_rnti) && (a.m_layer == b.m_layer) ); +} + +bool +operator < (const TbId_t& a, const TbId_t& b) +{ + return ( (a.m_rnti < b.m_rnti) || ( (a.m_rnti == b.m_rnti) && (a.m_layer < b.m_layer) ) ); +} NS_OBJECT_ENSURE_REGISTERED (LteSpectrumPhy); LteSpectrumPhy::LteSpectrumPhy () : m_state (IDLE), - m_random (0.0, 1.0) + m_random (0.0, 1.0), + m_transmissionMode (0) { NS_LOG_FUNCTION (this); m_interference = CreateObject (); + for (uint8_t i = 0; i < 7; i++) + { + m_txModeGain.push_back (1.0); + } } @@ -57,6 +85,7 @@ LteSpectrumPhy::~LteSpectrumPhy () { NS_LOG_FUNCTION (this); m_expectedTbs.clear (); + m_txModeGain.clear (); } void LteSpectrumPhy::DoDispose () @@ -118,7 +147,7 @@ LteSpectrumPhy::GetTypeId (void) "Activate/Deactivate the error model (by default is active).", BooleanValue (true), MakeBooleanAccessor (&LteSpectrumPhy::m_pemEnabled), - MakeBooleanChecker ()); + MakeBooleanChecker ()) ; return tid; } @@ -421,11 +450,14 @@ LteSpectrumPhy::UpdateSinrPerceived (const SpectrumValue& sinr) void -LteSpectrumPhy::AddExpectedTb (uint16_t rnti, uint16_t size, uint8_t mcs, std::vector map) +LteSpectrumPhy::AddExpectedTb (uint16_t rnti, uint16_t size, uint8_t mcs, std::vector map, uint8_t layer) { - NS_LOG_LOGIC (this << " rnti: " << rnti << " size " << size << " mcs " << (uint16_t)mcs); + NS_LOG_LOGIC (this << " rnti: " << rnti << " size " << size << " mcs " << (uint16_t)mcs << " layer " << (uint8_t)layer); + TbId_t tbId; + tbId.m_rnti = rnti; + tbId.m_layer = layer; expectedTbs_t::iterator it; - it = m_expectedTbs.find (rnti); + it = m_expectedTbs.find (tbId); if (it != m_expectedTbs.end ()) { // migth be a TB of an unreceived packet (due to high progpalosses) @@ -433,7 +465,7 @@ LteSpectrumPhy::AddExpectedTb (uint16_t rnti, uint16_t size, uint8_t mcs, std:: } // insert new entry tbInfo_t tbInfo = {size, mcs, map, false}; - m_expectedTbs.insert (std::pair (rnti,tbInfo )); + m_expectedTbs.insert (std::pair (tbId,tbInfo )); } @@ -448,16 +480,22 @@ LteSpectrumPhy::EndRx () // this will trigger CQI calculation and Error Model evaluation // as a side effect, the error model should update the error status of all TBs m_interference->EndRx (); - NS_LOG_INFO (this << " No. of burts " << m_rxPacketBurstList.size ()); + NS_LOG_DEBUG (this << " No. of burts " << m_rxPacketBurstList.size ()); NS_LOG_DEBUG (this << " Expected TBs " << m_expectedTbs.size ()); expectedTbs_t::iterator itTb = m_expectedTbs.begin (); + + // apply transmission mode gain + NS_LOG_DEBUG (this << " txMode " << (uint16_t)m_transmissionMode << " gain " << m_txModeGain.at (m_transmissionMode)); + NS_ASSERT (m_transmissionMode < m_txModeGain.size ()); + m_sinrPerceived *= m_txModeGain.at (m_transmissionMode); + while (itTb!=m_expectedTbs.end ()) { if (m_pemEnabled) { double errorRate = LteMiErrorModel::GetTbError (m_sinrPerceived, (*itTb).second.rbBitmap, (*itTb).second.size, (*itTb).second.mcs); (*itTb).second.corrupt = m_random.GetValue () > errorRate ? false : true; - NS_LOG_DEBUG (this << "RNTI " << (*itTb).first << " size " << (*itTb).second.size << " mcs " << (uint32_t)(*itTb).second.mcs << " bitmap " << (*itTb).second.rbBitmap.size () << " ErrorRate " << errorRate << " corrupted " << (*itTb).second.corrupt); + NS_LOG_DEBUG (this << "RNTI " << (*itTb).first.m_rnti << " size " << (*itTb).second.size << " mcs " << (uint32_t)(*itTb).second.mcs << " bitmap " << (*itTb).second.rbBitmap.size () << " layer " << (uint16_t)(*itTb).first.m_layer << " ErrorRate " << errorRate << " corrupted " << (*itTb).second.corrupt); } // for (uint16_t i = 0; i < (*itTb).second.rbBitmap.size (); i++) @@ -475,9 +513,11 @@ LteSpectrumPhy::EndRx () // retrieve TB info of this packet LteRadioBearerTag tag; (*j)->PeekPacketTag (tag); - itTb = m_expectedTbs.find (tag.GetRnti ()); - //(*j)->AddPacketTag (tag); - NS_LOG_INFO (this << " Packet of " << tag.GetRnti ()); + TbId_t tbId; + tbId.m_rnti = tag.GetRnti (); + tbId.m_layer = tag.GetLayer (); + itTb = m_expectedTbs.find (tbId); + NS_LOG_INFO (this << " Packet of " << tbId.m_rnti << " layer " << (uint8_t) tbId.m_layer); if (itTb!=m_expectedTbs.end ()) { if (!(*itTb).second.corrupt) @@ -514,5 +554,41 @@ LteSpectrumPhy::AddSinrChunkProcessor (Ptr p) m_interference->AddSinrChunkProcessor (p); } +void +LteSpectrumPhy::SetTransmissionMode (uint8_t txMode) +{ + NS_LOG_FUNCTION (this << (uint16_t) txMode); + NS_ASSERT_MSG (txMode < m_txModeGain.size (), "TransmissionMode not available: 1.." << m_txModeGain.size ()); + m_transmissionMode = txMode; +} + + +void +LteSpectrumPhy::SetTxModeGain (uint8_t txMode, double gain) +{ + NS_LOG_FUNCTION (this << " txmode " << (uint16_t)txMode << " gain " << gain); + // convert to linear + gain = pow (10.0, (gain / 10.0)); + if (m_txModeGain.size () < txMode) + { + m_txModeGain.resize (txMode); + } + std::vector temp; + temp = m_txModeGain; + m_txModeGain.clear (); + for (uint8_t i = 0; i < temp.size (); i++) + { + if (i==txMode-1) + { + m_txModeGain.push_back (gain); + } + else + { + m_txModeGain.push_back (temp.at (i)); + } + } +} + + } // namespace ns3 diff --git a/src/lte/model/lte-spectrum-phy.h b/src/lte/model/lte-spectrum-phy.h index a2a94a1a5..14433fa4c 100644 --- a/src/lte/model/lte-spectrum-phy.h +++ b/src/lte/model/lte-spectrum-phy.h @@ -41,7 +41,20 @@ namespace ns3 { +struct TbId_t +{ + uint16_t m_rnti; + uint8_t m_layer; + + public: + TbId_t (); + TbId_t (const uint16_t a, const uint8_t b); + + friend bool operator == (const TbId_t &a, const TbId_t &b); + friend bool operator < (const TbId_t &a, const TbId_t &b); +}; + struct tbInfo_t { uint16_t size; @@ -50,7 +63,7 @@ struct tbInfo_t bool corrupt; }; -typedef std::map expectedTbs_t; +typedef std::map expectedTbs_t; class LteNetDevice; @@ -176,8 +189,9 @@ public: * \param size the size of the TB * \param mcs the MCS of the TB * \param map the map of RB(s) used + * \param layer the layer (in case of MIMO tx) */ - void AddExpectedTb (uint16_t rnti, uint16_t size, uint8_t mcs, std::vector map); + void AddExpectedTb (uint16_t rnti, uint16_t size, uint8_t mcs, std::vector map, uint8_t layer); /** * @@ -185,11 +199,24 @@ public: * \param sinr vector of sinr perceived per each RB */ void UpdateSinrPerceived (const SpectrumValue& sinr); + + /** + * + * + * \param txMode UE transmission mode (SISO, MIMO tx diversity, ...) + */ + void SetTransmissionMode (uint8_t txMode); + + friend class LteUePhy; + private: void ChangeState (State newState); void EndTx (); void EndRx (); + + void SetTxModeGain (uint8_t txMode, double gain); + Ptr m_mobility; Ptr m_antenna; @@ -225,6 +252,10 @@ private: UniformVariable m_random; bool m_pemEnabled; // when true (default) the phy error model is enabled + + uint8_t m_transmissionMode; // for UEs: store the transmission mode + std::vector m_txModeGain; // duplicate value of LteUePhy + }; diff --git a/src/lte/model/lte-ue-cmac-sap.h b/src/lte/model/lte-ue-cmac-sap.h index f563ff329..95e131fdd 100644 --- a/src/lte/model/lte-ue-cmac-sap.h +++ b/src/lte/model/lte-ue-cmac-sap.h @@ -24,6 +24,7 @@ #include #include #include +#include namespace ns3 { @@ -50,6 +51,8 @@ public: virtual void AddLc (uint8_t lcId, LteMacSapUser* msu) = 0; virtual void RemoveLc (uint8_t lcId) = 0; + + virtual void RrcUpdateConfigurationReq (LteUeConfig_t params) = 0; }; diff --git a/src/lte/model/lte-ue-mac.cc b/src/lte/model/lte-ue-mac.cc index a457ff3ed..73e748841 100644 --- a/src/lte/model/lte-ue-mac.cc +++ b/src/lte/model/lte-ue-mac.cc @@ -56,6 +56,7 @@ public: virtual void ConfigureUe (uint16_t rnti); virtual void AddLc (uint8_t lcId, LteMacSapUser* msu); virtual void RemoveLc (uint8_t lcId); + virtual void RrcUpdateConfigurationReq (LteUeConfig_t params); private: LteUeMac* m_mac; @@ -85,6 +86,11 @@ UeMemberLteUeCmacSapProvider::RemoveLc (uint8_t lcid) m_mac->DoRemoveLc (lcid); } +void +UeMemberLteUeCmacSapProvider::RrcUpdateConfigurationReq (LteUeConfig_t params) +{ + m_mac->DoRrcUpdateConfigurationReq (params); +} class UeMemberLteMacSapProvider : public LteMacSapProvider @@ -244,7 +250,7 @@ LteUeMac::DoTransmitPdu (LteMacSapProvider::TransmitPduParameters params) { NS_LOG_FUNCTION (this); NS_ASSERT_MSG (m_rnti == params.rnti, "RNTI mismatch between RLC and MAC"); - LteRadioBearerTag tag (params.rnti, params.lcid); + LteRadioBearerTag tag (params.rnti, params.lcid, 0 /* UE works in SISO mode*/); params.pdu->AddPacketTag (tag); // Ptr pb = CreateObject (); // pb->AddPacket (params.pdu); @@ -327,6 +333,14 @@ LteUeMac::DoRemoveLc (uint8_t lcId) m_macSapUserMap.erase (lcId); } +void +LteUeMac::DoRrcUpdateConfigurationReq (LteUeConfig_t params) +{ + NS_LOG_FUNCTION (this << " txMode " << (uint8_t) params.m_transmissionMode); + // forward info to PHY layer + m_uePhySapProvider->SetTransmissionMode (params.m_transmissionMode); +} + void LteUeMac::DoReceivePhyPdu (Ptr p) @@ -374,15 +388,8 @@ LteUeMac::DoReceiveIdealControlMessage (Ptr msg) if (itBsr!=m_ulBsrReceived.end ()) { NS_LOG_FUNCTION (this << "\t" << dci.m_tbSize / m_macSapUserMap.size () << " bytes to LC " << (uint16_t)(*it).first << " queue " << (*itBsr).second); - (*it).second->NotifyTxOpportunity (dci.m_tbSize / activeLcs); - if ((*itBsr).second >= dci.m_tbSize / activeLcs) - { - (*itBsr).second -= dci.m_tbSize / activeLcs; - } - else - { - (*itBsr).second = 0; - } + (*it).second->NotifyTxOpportunity (dci.m_tbSize / activeLcs, 0); // UE works only in SISO mode + (*itBsr).second -= dci.m_tbSize / activeLcs; } } diff --git a/src/lte/model/lte-ue-mac.h b/src/lte/model/lte-ue-mac.h index f6ee7d392..6a1917301 100644 --- a/src/lte/model/lte-ue-mac.h +++ b/src/lte/model/lte-ue-mac.h @@ -81,6 +81,7 @@ private: void DoConfigureUe (uint16_t rnti); void DoAddLc (uint8_t lcId, LteMacSapUser* msu); void DoRemoveLc (uint8_t lcId); + void DoRrcUpdateConfigurationReq (LteUeConfig_t params); // forwarded from PHY SAP void DoReceivePhyPdu (Ptr p); diff --git a/src/lte/model/lte-ue-phy-sap.h b/src/lte/model/lte-ue-phy-sap.h index 0f6a1ddbd..d191d3529 100644 --- a/src/lte/model/lte-ue-phy-sap.h +++ b/src/lte/model/lte-ue-phy-sap.h @@ -52,6 +52,11 @@ public: * \param dlBandwidth the DL bandwidth in RB */ virtual void SetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth) = 0; + + /** + * \param txMode the transmissionMode of the user + */ + virtual void SetTransmissionMode (uint8_t txMode) = 0; /** * \brief Send SendIdealControlMessage (PDCCH map, CQI feedbacks) using the ideal control channel diff --git a/src/lte/model/lte-ue-phy.cc b/src/lte/model/lte-ue-phy.cc index 269eb694e..1609fac1c 100644 --- a/src/lte/model/lte-ue-phy.cc +++ b/src/lte/model/lte-ue-phy.cc @@ -55,6 +55,7 @@ public: virtual void SendMacPdu (Ptr p); virtual void SetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth); virtual void SendIdealControlMessage (Ptr msg); + virtual void SetTransmissionMode (uint8_t txMode); private: LteUePhy* m_phy; @@ -84,6 +85,12 @@ UeMemberLteUePhySapProvider::SendIdealControlMessage (Ptr m m_phy->DoSendIdealControlMessage (msg); } +void +UeMemberLteUePhySapProvider::SetTransmissionMode (uint8_t txMode) +{ + m_phy->DoSetTransmissionMode (txMode); +} + //////////////////////////////////////// @@ -116,6 +123,7 @@ LteUePhy::LteUePhy (Ptr dlPhy, Ptr ulPhy) LteUePhy::~LteUePhy () { + m_txModeGain.clear (); } void @@ -152,12 +160,41 @@ LteUePhy::GetTypeId (void) MakeDoubleAccessor (&LteUePhy::SetNoiseFigure, &LteUePhy::GetNoiseFigure), MakeDoubleChecker ()) - .AddAttribute ("MacToChannelDelay", - "The delay in TTI units that occurs between a scheduling decision in the MAC and the actual start of the transmission by the PHY. This is intended to be used to model the latency of real PHY and MAC implementations.", - UintegerValue (1), - MakeUintegerAccessor (&LteUePhy::SetMacChDelay, - &LteUePhy::GetMacChDelay), - MakeUintegerChecker ()) + .AddAttribute ("TxMode1Gain", + "Transmission mode 1 gain in dBm", + DoubleValue (0.0), + MakeDoubleAccessor (&LteUePhy::SetTxMode1Gain ), + MakeDoubleChecker ()) + .AddAttribute ("TxMode2Gain", + "Transmission mode 2 gain in dBm", + DoubleValue (4.2), + MakeDoubleAccessor (&LteUePhy::SetTxMode2Gain ), + MakeDoubleChecker ()) + .AddAttribute ("TxMode3Gain", + "Transmission mode 3 gain in dBm", + DoubleValue (-2.8), + MakeDoubleAccessor (&LteUePhy::SetTxMode3Gain ), + MakeDoubleChecker ()) + .AddAttribute ("TxMode4Gain", + "Transmission mode 4 gain in dBm", + DoubleValue (0.0), + MakeDoubleAccessor (&LteUePhy::SetTxMode4Gain ), + MakeDoubleChecker ()) + .AddAttribute ("TxMode5Gain", + "Transmission mode 5 gain in dBm", + DoubleValue (0.0), + MakeDoubleAccessor (&LteUePhy::SetTxMode5Gain ), + MakeDoubleChecker ()) + .AddAttribute ("TxMode6Gain", + "Transmission mode 6 gain in dBm", + DoubleValue (0.0), + MakeDoubleAccessor (&LteUePhy::SetTxMode6Gain ), + MakeDoubleChecker ()) + .AddAttribute ("TxMode7Gain", + "Transmission mode 7 gain in dBm", + DoubleValue (0.0), + MakeDoubleAccessor (&LteUePhy::SetTxMode7Gain ), + MakeDoubleChecker ()) ; return tid; } @@ -328,6 +365,14 @@ Ptr LteUePhy::CreateDlCqiFeedbackMessage (const SpectrumValue& sinr) { NS_LOG_FUNCTION (this); + + // apply transmission mode gain + NS_ASSERT (m_transmissionMode < m_txModeGain.size ()); + SpectrumValue newSinr = sinr; + newSinr *= m_txModeGain.at (m_transmissionMode); +// std::vector cqi = m_amc->CreateCqiFeedbacks (newSinr); + + // CREATE DlCqiIdealControlMessage Ptr msg = Create (); @@ -335,8 +380,9 @@ LteUePhy::CreateDlCqiFeedbackMessage (const SpectrumValue& sinr) std::vector cqi; if (Simulator::Now () > m_p10CqiLast + m_p10CqiPeriocity) { - cqi = m_amc->CreateCqiFeedbacks (sinr, m_dlBandwidth); - + cqi = m_amc->CreateCqiFeedbacks (newSinr, m_dlBandwidth); + + int nLayer = TransmissionModesLayers::TxMode2LayerNum (m_transmissionMode); int nbSubChannels = cqi.size (); double cqiSum = 0.0; int activeSubChannels = 0; @@ -353,14 +399,19 @@ LteUePhy::CreateDlCqiFeedbackMessage (const SpectrumValue& sinr) dlcqi.m_rnti = m_rnti; dlcqi.m_ri = 1; // not yet used dlcqi.m_cqiType = CqiListElement_s::P10; // Peridic CQI using PUCCH wideband - if (activeSubChannels > 0) + NS_ASSERT_MSG (nLayer > 0, " nLayer negative"); + NS_ASSERT_MSG (nLayer < 3, " nLayer limit is 2s"); + for (int i = 0; i < nLayer; i++) { - dlcqi.m_wbCqi.push_back ((uint16_t) cqiSum / activeSubChannels); - } - else - { - // approximate with the worst case -> CQI = 1 - dlcqi.m_wbCqi.push_back (1); + if (activeSubChannels > 0) + { + dlcqi.m_wbCqi.push_back ((uint16_t) cqiSum / activeSubChannels); + } + else + { + // approximate with the worst case -> CQI = 1 + dlcqi.m_wbCqi.push_back (1); + } } //NS_LOG_DEBUG (this << " Generate P10 CQI feedback " << (uint16_t) cqiSum / activeSubChannels); dlcqi.m_wbPmi = 0; // not yet used @@ -368,8 +419,9 @@ LteUePhy::CreateDlCqiFeedbackMessage (const SpectrumValue& sinr) } else if (Simulator::Now () > m_a30CqiLast + m_a30CqiPeriocity) { - cqi = m_amc->CreateCqiFeedbacks (sinr, GetRbgSize ()); - int nbSubChannels = m_dlBandwidth; + cqi = m_amc->CreateCqiFeedbacks (newSinr, GetRbgSize ()); + int nLayer = TransmissionModesLayers::TxMode2LayerNum (m_transmissionMode); + int nbSubChannels = cqi.size (); int rbgSize = GetRbgSize (); double cqiSum = 0.0; int cqiNum = 0; @@ -389,7 +441,10 @@ LteUePhy::CreateDlCqiFeedbackMessage (const SpectrumValue& sinr) //NS_LOG_DEBUG (this << " RBG CQI " << (uint16_t) cqiSum / rbgSize); HigherLayerSelected_s hlCqi; hlCqi.m_sbPmi = 0; // not yet used - hlCqi.m_sbCqi.push_back ((uint16_t) cqiSum / rbgSize); // only CW0 (SISO mode) + for (int i = 0; i < nLayer; i++) + { + hlCqi.m_sbCqi.push_back ((uint16_t) cqiSum / rbgSize); + } rbgMeas.m_higherLayerSelected.push_back (hlCqi); cqiSum = 0.0; cqiNum = 0; @@ -455,8 +510,11 @@ LteUePhy::ReceiveIdealControlMessage (Ptr msg) } // send TB info to LteSpectrumPhy - NS_LOG_DEBUG (this << " UE " << m_rnti << " DCI " << dci.m_rnti << " bimap " << dci.m_rbBitmap); - m_downlinkSpectrumPhy->AddExpectedTb (dci.m_rnti, dci.m_tbsSize.at (0), dci.m_mcs.at (0), dlRb); // SISO mode + NS_LOG_DEBUG (this << " UE " << m_rnti << " DCI " << dci.m_rnti << " bitmap " << dci.m_rbBitmap); + for (uint8_t i = 0; i < dci.m_tbsSize.size (); i++) + { + m_downlinkSpectrumPhy->AddExpectedTb (dci.m_rnti, dci.m_tbsSize.at (i), dci.m_mcs.at (i), dlRb, i); + } SetSubChannelsForReception (dlRb); @@ -541,5 +599,87 @@ LteUePhy::SetRnti (uint16_t rnti) } +void +LteUePhy::DoSetTransmissionMode (uint8_t txMode) +{ + NS_LOG_FUNCTION (this << (uint16_t)txMode); + m_transmissionMode = txMode; + m_downlinkSpectrumPhy->SetTransmissionMode (txMode); +} + + +void +LteUePhy::SetTxMode1Gain (double gain) +{ + SetTxModeGain (1, gain); +} + +void +LteUePhy::SetTxMode2Gain (double gain) +{ + SetTxModeGain (2, gain); +} + +void +LteUePhy::SetTxMode3Gain (double gain) +{ + SetTxModeGain (3, gain); +} + +void +LteUePhy::SetTxMode4Gain (double gain) +{ + SetTxModeGain (4, gain); +} + +void +LteUePhy::SetTxMode5Gain (double gain) +{ + SetTxModeGain (5, gain); +} + +void +LteUePhy::SetTxMode6Gain (double gain) +{ + SetTxModeGain (6, gain); +} + +void +LteUePhy::SetTxMode7Gain (double gain) +{ + SetTxModeGain (7, gain); +} + + +void +LteUePhy::SetTxModeGain (uint8_t txMode, double gain) +{ + NS_LOG_FUNCTION (this << gain); + // convert to linear + double gainLin = pow (10.0, (gain / 10.0)); + if (m_txModeGain.size () < txMode) + { + m_txModeGain.resize (txMode); + } + std::vector temp; + temp = m_txModeGain; + m_txModeGain.clear (); + for (uint8_t i = 0; i < temp.size (); i++) + { + if (i==txMode-1) + { + m_txModeGain.push_back (gainLin); + } + else + { + m_txModeGain.push_back (temp.at (i)); + } + } + // forward the info to DL LteSpectrumPhy + m_downlinkSpectrumPhy->SetTxModeGain (txMode, gain); +} + + + } // namespace ns3 diff --git a/src/lte/model/lte-ue-phy.h b/src/lte/model/lte-ue-phy.h index a8be19087..f42d4ea2b 100644 --- a/src/lte/model/lte-ue-phy.h +++ b/src/lte/model/lte-ue-phy.h @@ -165,6 +165,10 @@ public: virtual void DoSendIdealControlMessage (Ptr msg); virtual void ReceiveIdealControlMessage (Ptr msg); + + virtual void DoSetTransmissionMode (uint8_t txMode); + + @@ -195,9 +199,20 @@ public: * \param cellId the cell identifier of the eNB */ void SetEnbCellId (uint16_t cellId); + private: + + void SetTxMode1Gain (double gain); + void SetTxMode2Gain (double gain); + void SetTxMode3Gain (double gain); + void SetTxMode4Gain (double gain); + void SetTxMode5Gain (double gain); + void SetTxMode6Gain (double gain); + void SetTxMode7Gain (double gain); + void SetTxModeGain (uint8_t txMode, double gain); + std::vector m_subChannelsForTransmission; std::vector m_subChannelsForReception; @@ -217,6 +232,9 @@ private: uint16_t m_rnti; uint16_t m_enbCellId; + + uint8_t m_transmissionMode; + std::vector m_txModeGain; }; diff --git a/src/lte/model/lte-ue-rrc.cc b/src/lte/model/lte-ue-rrc.cc index b0c78d1cc..fac51e84b 100644 --- a/src/lte/model/lte-ue-rrc.cc +++ b/src/lte/model/lte-ue-rrc.cc @@ -298,6 +298,15 @@ LteUeRrc::GetLcIdVector () return v; } +void +LteUeRrc::DoRrcConfigurationUpdateInd (LteUeConfig_t params) +{ + NS_LOG_FUNCTION (this << " RNTI " << params.m_rnti << " txMode " << (uint16_t)params.m_transmissionMode); + + // propagate the information to MAC layer + m_cmacSapProvider->RrcUpdateConfigurationReq (params); +} + } // namespace ns3 diff --git a/src/lte/model/lte-ue-rrc.h b/src/lte/model/lte-ue-rrc.h index ef9995b06..350909789 100644 --- a/src/lte/model/lte-ue-rrc.h +++ b/src/lte/model/lte-ue-rrc.h @@ -162,6 +162,13 @@ public: */ void SetForwardUpCallback (Callback > cb); + /** + * message from eNB-RRC for changing UE's configuration + * (up to now TxMode) + * + */ + void DoRrcConfigurationUpdateInd (LteUeConfig_t params); + private: void DoReceiveRrcPdu (LtePdcpSapUser::ReceiveRrcPduParameters params); diff --git a/src/lte/model/pf-ff-mac-scheduler.cc b/src/lte/model/pf-ff-mac-scheduler.cc index c811be4b5..12870dbcc 100644 --- a/src/lte/model/pf-ff-mac-scheduler.cc +++ b/src/lte/model/pf-ff-mac-scheduler.cc @@ -212,7 +212,7 @@ PfFfMacScheduler::PfFfMacScheduler () m_schedSapUser (0), m_timeWindow (99.0), m_schedTtiDelay (2), - // WILD ACK: based on a m_macChTtiDelay = 1 + // WILD HACK: based on a m_macChTtiDelay = 1 m_nextRntiUl (0) { m_amc = CreateObject (); @@ -289,8 +289,17 @@ PfFfMacScheduler::DoCschedCellConfigReq (const struct FfMacCschedSapProvider::Cs void PfFfMacScheduler::DoCschedUeConfigReq (const struct FfMacCschedSapProvider::CschedUeConfigReqParameters& params) { - NS_LOG_FUNCTION (this); - // Not used at this stage + NS_LOG_FUNCTION (this << " RNTI " << params.m_rnti << " txMode " << (uint16_t)params.m_transmissionMode); + std::map ::iterator it = m_uesTxMode.find (params.m_rnti); + if (it==m_uesTxMode.end ()) + { + m_uesTxMode.insert (std::pair (params.m_rnti, params.m_transmissionMode)); + } + else + { + (*it).second = params.m_transmissionMode; + } + return; return; } @@ -438,7 +447,6 @@ PfFfMacScheduler::DoSchedDlTriggerReq (const struct FfMacSchedSapProvider::Sched int rbgSize = GetRbgSize (m_cschedCellConfig.m_dlBandwidth); int rbgNum = m_cschedCellConfig.m_dlBandwidth / rbgSize; - //std::vector rbgAllocationMap; std::map > allocationMap; for (int i = 0; i < rbgNum; i++) { @@ -450,25 +458,56 @@ PfFfMacScheduler::DoSchedDlTriggerReq (const struct FfMacSchedSapProvider::Sched { std::map ::iterator itCqi; itCqi = m_a30CqiRxed.find ((*it).first); - uint8_t cqi = 0; + std::map ::iterator itTxMode; + itTxMode = m_uesTxMode.find ((*it).first); + if (itTxMode == m_uesTxMode.end()) + { + NS_FATAL_ERROR ("No Transmission Mode info on user " << (*it).first); + } + int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second); + std::vector sbCqi; if (itCqi == m_a30CqiRxed.end ()) { // NS_LOG_DEBUG (this << " No DL-CQI for this UE " << (*it).first); - cqi = 1; // start with lowest value + for (uint8_t k = 0; k < nLayer; k++) + { + sbCqi.push_back (1); // start with lowest value + } } else { - cqi = (*itCqi).second.m_higherLayerSelected.at (i).m_sbCqi.at (0); + sbCqi = (*itCqi).second.m_higherLayerSelected.at (i).m_sbCqi; // NS_LOG_INFO (this << " CQI " << (uint32_t)cqi); } - if (cqi > 0) // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213) + uint8_t cqi1 = sbCqi.at(0); + uint8_t cqi2 = 1; + if (sbCqi.size () > 1) + { + cqi2 = sbCqi.at(1); + } + + if ((cqi1 > 0)||(cqi2 > 0)) // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213) { // NS_LOG_DEBUG (this << " LC active " << LcActivePerFlow ((*it).first)); if (LcActivePerFlow ((*it).first) > 0) { // this UE has data to transmit - uint8_t mcs = m_amc->GetMcsFromCqi (cqi); - double achievableRate = ((m_amc->GetTbSizeFromMcs (mcs, 1) / 8) / 0.001); // = TB size / TTI + double achievableRate = 0.0; + for (uint8_t k = 0; k < nLayer; k++) + { + uint8_t mcs = 0; + if (sbCqi.size () > k) + { + mcs = m_amc->GetMcsFromCqi (sbCqi.at (k)); + } + else + { + // no info on this subband -> worst MCS + mcs = 0; + } + achievableRate += ((m_amc->GetTbSizeFromMcs (mcs, 1) / 8) / 0.001); // = TB size / TTI + } + double rcqi = achievableRate / (*it).second.lastAveragedThroughput; // NS_LOG_DEBUG (this << " RNTI " << (*it).first << " MCS " << (uint32_t)mcs << " achievableRate " << achievableRate << " avgThr " << (*it).second.lastAveragedThroughput << " RCQI " << rcqi); @@ -531,7 +570,14 @@ PfFfMacScheduler::DoSchedDlTriggerReq (const struct FfMacSchedSapProvider::Sched uint16_t RgbPerRnti = (*itMap).second.size (); std::map ::iterator itCqi; itCqi = m_a30CqiRxed.find ((*itMap).first); - uint8_t worstCqi = 15; + std::map ::iterator itTxMode; + itTxMode = m_uesTxMode.find ((*itMap).first); + if (itTxMode == m_uesTxMode.end()) + { + NS_FATAL_ERROR ("No Transmission Mode info on user " << (*itMap).first); + } + int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second); + std::vector worstCqi (2, 15); if (itCqi != m_a30CqiRxed.end ()) { for (uint16_t k = 0; k < (*itMap).second.size (); k++) @@ -539,25 +585,48 @@ PfFfMacScheduler::DoSchedDlTriggerReq (const struct FfMacSchedSapProvider::Sched if ((*itCqi).second.m_higherLayerSelected.size () > (*itMap).second.at (k)) { // NS_LOG_DEBUG (this << " RBG " << (*itMap).second.at (k) << " CQI " << (uint16_t)((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (0)) ); - if (((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (0)) < worstCqi) + for (uint8_t j = 0; j < nLayer; j++) { - worstCqi = ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (0)); + if ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.size ()> j) + { + if (((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j)) < worstCqi.at (j)) + { + worstCqi.at (j) = ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j)); + } + } + else + { + // no CQI for this layer of this suband -> worst one + worstCqi.at (j) = 1; + } } } else { - worstCqi = 1; // try with lowest MCS in RBG with no info on channel + for (uint8_t j = 0; j < nLayer; j++) + { + worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel + } } } } else { - worstCqi = 1; // try with lowest MCS in RBG with no info on channel + for (uint8_t j = 0; j < nLayer; j++) + { + worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel + } } // NS_LOG_DEBUG (this << " CQI " << (uint16_t)worstCqi); - newDci.m_mcs.push_back (m_amc->GetMcsFromCqi (worstCqi)); - int tbSize = (m_amc->GetTbSizeFromMcs (newDci.m_mcs.at (0), RgbPerRnti * rbgSize) / 8); // (size of TB in bytes according to table 7.1.7.2.1-1 of 36.213) - newDci.m_tbsSize.push_back (tbSize); + uint32_t bytesTxed = 0; + for (uint8_t j = 0; j < nLayer; j++) + { + newDci.m_mcs.push_back (m_amc->GetMcsFromCqi (worstCqi.at (j))); + int tbSize = (m_amc->GetTbSizeFromMcs (newDci.m_mcs.at (j), RgbPerRnti * rbgSize) / 8); // (size of TB in bytes according to table 7.1.7.2.1-1 of 36.213) + newDci.m_tbsSize.push_back (tbSize); + NS_LOG_DEBUG (this << " MCS " << m_amc->GetMcsFromCqi (worstCqi.at (j))); + bytesTxed += tbSize; + } newDci.m_resAlloc = 0; // only allocation type 0 at this stage newDci.m_rbBitmap = 0; // TBD (32 bit bitmap see 7.1.6 of 36.213) @@ -570,20 +639,23 @@ PfFfMacScheduler::DoSchedDlTriggerReq (const struct FfMacSchedSapProvider::Sched newDci.m_rbBitmap = rbgMask; // (32 bit bitmap see 7.1.6 of 36.213) // create the rlc PDUs -> equally divide resources among actives LCs - int rlcPduSize = tbSize / lcActives; std::map ::iterator itBufReq; for (itBufReq = m_rlcBufferReq.begin (); itBufReq != m_rlcBufferReq.end (); itBufReq++) { - if (((*itBufReq).first.m_rnti == (*itMap).first) && (((*itBufReq).second.m_rlcTransmissionQueueSize > 0) - || ((*itBufReq).second.m_rlcRetransmissionQueueSize > 0) - || ((*itBufReq).second.m_rlcStatusPduSize > 0) )) + if (((*itBufReq).first.m_rnti == (*itMap).first) && + (((*itBufReq).second.m_rlcTransmissionQueueSize > 0) + || ((*itBufReq).second.m_rlcRetransmissionQueueSize > 0) + || ((*itBufReq).second.m_rlcStatusPduSize > 0) )) { - RlcPduListElement_s newRlcEl; - newRlcEl.m_logicalChannelIdentity = (*itBufReq).first.m_lcId; -// NS_LOG_DEBUG (this << " LCID " << (uint32_t) newRlcEl.m_logicalChannelIdentity << " size " << rlcPduSize); - newRlcEl.m_size = rlcPduSize; - newRlcPduLe.push_back (newRlcEl); - UpdateDlRlcBufferInfo (newDci.m_rnti, newRlcEl.m_logicalChannelIdentity, rlcPduSize); + for (uint8_t j = 0; j < nLayer; j++) + { + RlcPduListElement_s newRlcEl; + newRlcEl.m_logicalChannelIdentity = (*itBufReq).first.m_lcId; + newRlcEl.m_size = newDci.m_tbsSize.at (j) / lcActives; + NS_LOG_DEBUG (this << " LCID " << (uint32_t) newRlcEl.m_logicalChannelIdentity << " size " << newRlcEl.m_size << " layer " << (uint16_t)j); + newRlcPduLe.push_back (newRlcEl); + UpdateDlRlcBufferInfo (newDci.m_rnti, newRlcEl.m_logicalChannelIdentity, newRlcEl.m_size); + } } if ((*itBufReq).first.m_rnti > (*itMap).first) { @@ -604,7 +676,7 @@ PfFfMacScheduler::DoSchedDlTriggerReq (const struct FfMacSchedSapProvider::Sched it = m_flowStatsDl.find ((*itMap).first); if (it != m_flowStatsDl.end ()) { - (*it).second.lastTtiBytesTrasmitted = tbSize; + (*it).second.lastTtiBytesTrasmitted = bytesTxed; // NS_LOG_DEBUG (this << " UE bytes txed " << (*it).second.lastTtiBytesTrasmitted); @@ -1204,5 +1276,15 @@ PfFfMacScheduler::UpdateUlRlcBufferInfo (uint16_t rnti, uint16_t size) } +void +PfFfMacScheduler::TransmissionModeConfigurationUpdate (uint16_t rnti, uint8_t txMode) +{ + NS_LOG_FUNCTION (this << " RNTI " << rnti << " txMode " << (uint16_t)txMode); + FfMacCschedSapUser::CschedUeConfigUpdateIndParameters params; + params.m_rnti = rnti; + params.m_transmissionMode = txMode; + m_cschedSapUser->CschedUeConfigUpdateInd (params); +} + } diff --git a/src/lte/model/pf-ff-mac-scheduler.h b/src/lte/model/pf-ff-mac-scheduler.h index 89501e602..da6902eae 100644 --- a/src/lte/model/pf-ff-mac-scheduler.h +++ b/src/lte/model/pf-ff-mac-scheduler.h @@ -85,6 +85,8 @@ public: friend class PfSchedulerMemberCschedSapProvider; friend class PfSchedulerMemberSchedSapProvider; + + void TransmissionModeConfigurationUpdate (uint16_t rnti, uint8_t txMode); private: // @@ -216,6 +218,7 @@ private: uint32_t m_cqiTimersThreshold; // # of TTIs for which a CQI canbe considered valid + std::map m_uesTxMode; // txMode of the UEs }; } // namespace ns3 diff --git a/src/lte/model/rr-ff-mac-scheduler.cc b/src/lte/model/rr-ff-mac-scheduler.cc index 171d17dee..f648502ee 100644 --- a/src/lte/model/rr-ff-mac-scheduler.cc +++ b/src/lte/model/rr-ff-mac-scheduler.cc @@ -21,9 +21,10 @@ #include #include -#include "lte-amc.h" -#include "rr-ff-mac-scheduler.h" +#include +#include #include +#include NS_LOG_COMPONENT_DEFINE ("RrFfMacScheduler"); @@ -290,8 +291,16 @@ RrFfMacScheduler::DoCschedCellConfigReq (const struct FfMacCschedSapProvider::Cs void RrFfMacScheduler::DoCschedUeConfigReq (const struct FfMacCschedSapProvider::CschedUeConfigReqParameters& params) { - NS_LOG_FUNCTION (this); - // Not used at this stage + NS_LOG_FUNCTION (this << " RNTI " << params.m_rnti << " txMode " << (uint16_t)params.m_transmissionMode); + std::map ::iterator it = m_uesTxMode.find (params.m_rnti); + if (it==m_uesTxMode.end ()) + { + m_uesTxMode.insert (std::pair (params.m_rnti, params.m_transmissionMode)); + } + else + { + (*it).second = params.m_transmissionMode; + } return; } @@ -481,6 +490,7 @@ RrFfMacScheduler::DoSchedDlTriggerReq (const struct FfMacSchedSapProvider::Sched it = m_rlcBufferReq.begin (); m_nextRntiDl = (*it).m_rnti; } + std::map ::iterator itTxMode; do { itLcRnti = lcActivesPerRnti.find ((*it).m_rnti); @@ -495,6 +505,12 @@ RrFfMacScheduler::DoSchedDlTriggerReq (const struct FfMacSchedSapProvider::Sched } continue; } + itTxMode = m_uesTxMode.find ((*it).m_rnti); + if (itTxMode == m_uesTxMode.end()) + { + NS_FATAL_ERROR ("No Transmission Mode info on user " << (*it).m_rnti); + } + int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second); int lcNum = (*itLcRnti).second; // create new BuildDataListElement_s for this RNTI BuildDataListElement_s newEl; @@ -505,29 +521,35 @@ RrFfMacScheduler::DoSchedDlTriggerReq (const struct FfMacSchedSapProvider::Sched newDci.m_resAlloc = 0; newDci.m_rbBitmap = 0; std::map ::iterator itCqi = m_p10CqiRxed.find (newEl.m_rnti); - if (itCqi == m_p10CqiRxed.end ()) + for (uint8_t i = 0; i < nLayer; i++) { - newDci.m_mcs.push_back (0); // no info on this user -> lowest MCS - } - else - { - newDci.m_mcs.push_back ( m_amc->GetMcsFromCqi ((*itCqi).second) ); + if (itCqi == m_p10CqiRxed.end ()) + { + newDci.m_mcs.push_back (0); // no info on this user -> lowest MCS + } + else + { + newDci.m_mcs.push_back ( m_amc->GetMcsFromCqi ((*itCqi).second) ); + } } // group the LCs of this RNTI std::vector newRlcPduLe; // int totRbg = lcNum * rbgPerFlow; // totRbg = rbgNum / nTbs; -int tbSize = (m_amc->GetTbSizeFromMcs (newDci.m_mcs.at (0), rbgPerTb * rbgSize) / 8); - NS_LOG_DEBUG (this << "Allocate user " << newEl.m_rnti << " LCs " << (uint16_t)(*itLcRnti).second << " bytes " << tbSize << " PRBs " << rbgPerTb * rbgSize << " mcs " << (uint16_t) newDci.m_mcs.at (0)); + int tbSize = (m_amc->GetTbSizeFromMcs (newDci.m_mcs.at (0), rbgPerTb * rbgSize) / 8); + NS_LOG_DEBUG (this << "Allocate user " << newEl.m_rnti << " LCs " << (uint16_t)(*itLcRnti).second << " bytes " << tbSize << " PRBs " << rbgPerTb * rbgSize << " mcs " << (uint16_t) newDci.m_mcs.at (0) << " layers " << nLayer); uint16_t rlcPduSize = tbSize / lcNum; for (int i = 0; i < lcNum ; i++) { - RlcPduListElement_s newRlcEl; - newRlcEl.m_logicalChannelIdentity = (*it).m_logicalChannelIdentity; - NS_LOG_DEBUG (this << "LCID " << (uint32_t) newRlcEl.m_logicalChannelIdentity << " size " << rlcPduSize << " ID " << (*it).m_rnti); - newRlcEl.m_size = rlcPduSize; - UpdateDlRlcBufferInfo ((*it).m_rnti, newRlcEl.m_logicalChannelIdentity, rlcPduSize); - newRlcPduLe.push_back (newRlcEl); + for (uint8_t j = 0; j < nLayer; j++) + { + RlcPduListElement_s newRlcEl; + newRlcEl.m_logicalChannelIdentity = (*it).m_logicalChannelIdentity; + NS_LOG_DEBUG (this << "LCID " << (uint32_t) newRlcEl.m_logicalChannelIdentity << " size " << rlcPduSize << " ID " << (*it).m_rnti << " layer " << (uint16_t)j); + newRlcEl.m_size = rlcPduSize; + UpdateDlRlcBufferInfo ((*it).m_rnti, newRlcEl.m_logicalChannelIdentity, rlcPduSize); + newRlcPduLe.push_back (newRlcEl); + } it++; if (it == m_rlcBufferReq.end ()) { @@ -543,8 +565,7 @@ int tbSize = (m_amc->GetTbSizeFromMcs (newDci.m_mcs.at (0), rbgPerTb * rbgSize) } newDci.m_rbBitmap = rbgMask; // (32 bit bitmap see 7.1.6 of 36.213) - int nbOfTbsInNewDci = 1; // SISO -> only one TB - for (int i = 0; i < nbOfTbsInNewDci; i++) + for (int i = 0; i < nLayer; i++) { newDci.m_tbsSize.push_back (tbSize); newDci.m_ndi.push_back (1); // TBD (new data indicator) @@ -1034,4 +1055,17 @@ RrFfMacScheduler::UpdateUlRlcBufferInfo (uint16_t rnti, uint16_t size) } + +void +RrFfMacScheduler::TransmissionModeConfigurationUpdate (uint16_t rnti, uint8_t txMode) +{ + NS_LOG_FUNCTION (this << " RNTI " << rnti << " txMode " << (uint16_t)txMode); + FfMacCschedSapUser::CschedUeConfigUpdateIndParameters params; + params.m_rnti = rnti; + params.m_transmissionMode = txMode; + m_cschedSapUser->CschedUeConfigUpdateInd (params); +} + + + } diff --git a/src/lte/model/rr-ff-mac-scheduler.h b/src/lte/model/rr-ff-mac-scheduler.h index 4095e0339..14e179bc3 100644 --- a/src/lte/model/rr-ff-mac-scheduler.h +++ b/src/lte/model/rr-ff-mac-scheduler.h @@ -73,6 +73,8 @@ public: friend class RrSchedulerMemberCschedSapProvider; friend class RrSchedulerMemberSchedSapProvider; + + void TransmissionModeConfigurationUpdate (uint16_t rnti, uint8_t txMode); private: // @@ -183,6 +185,7 @@ private: uint32_t m_cqiTimersThreshold; // # of TTIs for which a CQI canbe considered valid + std::map m_uesTxMode; // txMode of the UEs }; diff --git a/src/lte/test/lte-test-entities.cc b/src/lte/test/lte-test-entities.cc index b29b2e5fb..3dd49cda7 100644 --- a/src/lte/test/lte-test-entities.cc +++ b/src/lte/test/lte-test-entities.cc @@ -450,14 +450,14 @@ void LteTestMac::SendTxOpportunity (Time time, uint32_t bytes) { NS_LOG_FUNCTION (this << time << bytes); - Simulator::Schedule (time, &LteMacSapUser::NotifyTxOpportunity, m_macSapUser, bytes); + Simulator::Schedule (time, &LteMacSapUser::NotifyTxOpportunity, m_macSapUser, bytes, 0); if (m_txOpportunityMode == RANDOM_MODE) + { + if (m_txOppTime != Seconds (0)) { - if (m_txOppTime != Seconds (0)) - { - Simulator::Schedule (m_txOppTime, &LteTestMac::SendTxOpportunity, this, m_txOppTime, m_txOppSize); - } + Simulator::Schedule (m_txOppTime, &LteTestMac::SendTxOpportunity, this, m_txOppTime, m_txOppSize); } + } } void @@ -572,17 +572,17 @@ LteTestMac::DoReportBufferStatus (LteMacSapProvider::ReportBufferStatusParameter if (params.statusPduSize) { Simulator::Schedule (Seconds (0.1), &LteMacSapUser::NotifyTxOpportunity, - m_macSapUser, params.statusPduSize + 2); + m_macSapUser, params.statusPduSize + 2, 0); } else if (params.txQueueSize) { Simulator::Schedule (Seconds (0.1), &LteMacSapUser::NotifyTxOpportunity, - m_macSapUser, params.txQueueSize + 2); + m_macSapUser, params.txQueueSize + 2, 0); } else if (params.retxQueueSize) { Simulator::Schedule (Seconds (0.1), &LteMacSapUser::NotifyTxOpportunity, - m_macSapUser, params.retxQueueSize + 2); + m_macSapUser, params.retxQueueSize + 2, 0); } } } diff --git a/src/lte/test/lte-test-fading.cc b/src/lte/test/lte-test-fading.cc index 082e538c8..ecd7aded7 100644 --- a/src/lte/test/lte-test-fading.cc +++ b/src/lte/test/lte-test-fading.cc @@ -64,13 +64,6 @@ using namespace ns3; */ -// void -// LteTestShadowingDlSchedCallback (LteShadowingSystemTestCase *testcase, std::string path, uint32_t frameNo, uint32_t subframeNo, uint16_t rnti, uint8_t mcsTb1, uint16_t sizeTb1, uint8_t mcsTb2, uint16_t sizeTb2) -// { -// testcase->DlScheduling (frameNo, subframeNo, rnti, mcsTb1, sizeTb1, mcsTb2, sizeTb2); -// } -// - LteFadingTestSuite::LteFadingTestSuite () : TestSuite ("lte-fading-model", SYSTEM) @@ -132,194 +125,7 @@ LteFadingTestSuite::LteFadingTestSuite () mm2->SetPosition (Vector (distance, 0.0, hm)); AddTestCase (new LteFadingTestCase (mm1, mm2, 137.93, "OH Urban Large city")); - -// AddTestCase (new LteFadingTestCase (mm1, mm2, 137.88, "OH Urban small city = ??")); -// -// AddTestCase (new LteFadingTestCase (mm1, mm2, 128.03, "loss OH SubUrban")); -// -// AddTestCase (new LteFadingTestCase (mm1, mm2, 110.21, "loss OH OpenAreas")); -// -// // Test #2 COST231 Model (1500 < freq < 2000~2170 MHz) (Macro<->UE) -// -// freq = 2.1140e9; // E_UTRA BAND #1 see table 5.5-1 of 36.101 -// -// AddTestCase (new LteFadingTestCase (mm1, mm2, 148.55, "COST231 Urban Large city")); -// -// AddTestCase (new LteFadingTestCase (mm1, mm2, 150.64, "COST231 Urban small city and suburban")); -// -// // Test #3 2.6 GHz model (Macro<->UE) -// -// freq = 2.620e9; // E_UTRA BAND #7 see table 5.5-1 of 36.101 -// -// AddTestCase (new LteFadingTestCase (mm1, mm2, 121.83, "2.6GHz model")); -// -// // Test #4 ITU1411 LOS model (Macro<->UE) -// -// freq = 2.1140e9; // E_UTRA BAND #1 see table 5.5-1 of 36.101 -// distance = 100; -// Ptr mm3 = ueNodes.Get (1)->GetObject (); -// mm3->SetPosition (Vector (distance, 0.0, hm)); -// AddTestCase (new LteFadingTestCase (mm1, mm3, 81.00, "ITU1411 LOS")); -// -// // Test #5 ITU1411 NLOS model (Macro<->UE) -// -// freq = 2.1140e9; // E_UTRA BAND #1 see table 5.5-1 of 36.101 -// distance = 900; -// -// Ptr mm4 = ueNodes.Get (2)->GetObject (); -// mm4->SetPosition (Vector (distance, 0.0, hm)); -// AddTestCase (new LteFadingTestCase (mm1, mm4, 143.69, "ITU1411 NLOS")); -// -// // Test #6 ITUP1238 (HeNB <-> UE) -// -// distance = 30; -// freq = 2.1140e9; // E_UTRA BAND #1 see table 5.5-1 of 36.101 -// double henbHeight = 10.0; -// Ptr mm5 = henbNodes.Get (0)->GetObject (); -// mm5->SetPosition (Vector (0.0, 0.0, henbHeight)); -// Ptr building1 = Create (0.0, 10.0, 0.0, 10.0, 0.0, 20.0/*, 1, 1, 1*/); -// building1->SetBuildingType (Building::Residential); -// building1->SetExtWallsType (Building::ConcreteWithWindows); -// mm5->SetIndoor (building1); -// Ptr mm6 = hueNodes.Get (0)->GetObject (); -// mm6->SetPosition (Vector (distance, 0.0, hm)); -// mm6->SetIndoor (building1); -// mm6->SetFloorNumber (2); -// AddTestCase (new LteFadingTestCase (mm5, mm6, 88.3855, "ITUP1238")); -// -// // Test #7 Outdoor -> Indoor OkumuraHata (Macro<->UE) -// -// freq = 2.1140e9; // E_UTRA BAND #1 see table 5.5-1 of 36.101 -// distance = 2000; -// // The loss is as in test #2 (large city) plus the building penetration loss -// // which for ConcreteWithWindows is equal to 7 dB -> 148.55 + 7 = 155.55 -// Ptr mm7 = ueNodes.Get (3)->GetObject (); -// mm7->SetPosition (Vector (distance, 0.0, hm)); -// mm7->SetIndoor (building1); -// AddTestCase (new LteFadingTestCase (mm1, mm7, 155.55, "Okumura Hata Outdoor -> Indoor")); -// -// // Test #8 Outdoor -> Indoor ITU1411 (Macro<->UE) -// freq = 2.1140e9; // E_UTRA BAND #1 see table 5.5-1 of 36.101 -// distance = 100; -// Ptr mm8 = ueNodes.Get (4)->GetObject (); -// mm8->SetPosition (Vector (distance, 0.0, hm)); -// mm8->SetIndoor (building1); -// // The loss is as in test #4 plus the building penetration loss -// // which for ConcreteWithWindows is equal to 7 dB -> 81.000 + 7 = 88.000 -// AddTestCase (new LteFadingTestCase (mm1, mm8, 88.000, "ITU1411 LOS Outdoor -> Indoor")); -// -// // Test #9 Indoor -> Outdoor LOS (HeNB <-> UE) -// -// distance = 100; -// freq = 2.1140e9; // E_UTRA BAND #1 see table 5.5-1 of 36.101 -// Ptr mm9 = henbNodes.Get (1)->GetObject (); -// mm9->SetPosition (Vector (0.0, 0.0, henbHeight)); -// mm9->SetIndoor (building1); -// mm9->SetFloorNumber (2); -// Ptr mm10 = hueNodes.Get (1)->GetObject (); -// mm10->SetPosition (Vector (distance, 0.0, hm)); -// // The loss is similar of test #4 plus the building penetration loss -// // which for ConcreteWithWindows is equal to 7 dB and the height gain -// // (2 floors x 2 dB/floor = 4) -> 81.838 + 7 - 4 = 84.838 -// AddTestCase (new LteFadingTestCase (mm9, mm10, 84.838, "ITU1411 LOS Indoor -> Outdoor")); -// -// // Test #10 Indoor -> Outdoor NLOS (HeNB <-> UE) -// -// distance = 500; -// freq = 2.1140e9; // E_UTRA BAND #1 see table 5.5-1 of 36.101 -// Ptr mm11 = hueNodes.Get (2)->GetObject (); -// mm11->SetPosition (Vector (distance, 0.0, hm)); -// // The loss is similar as in test #4 plus the building penetration loss -// // which for ConcreteWithWindows is equal to 7 dB and the height gain -// // (2 floors x 2 dB/floor = 4) -> 180.90 + 7 - 4 = 183.90 -// AddTestCase (new LteFadingTestCase (mm9, mm11, 183.90, "ITU1411 NLOS Indoor -> Outdoor")); - - - //------------------- SYSTEM TEST ------------------------------ - -/* // LogLevel logLevel = (LogLevel)(LOG_PREFIX_FUNC | LOG_PREFIX_TIME | LOG_LEVEL_ALL); - // - // LogComponentEnable ("LteHelper", logLevel); - LogComponentEnable ("LteShadowingTest", LOG_LEVEL_ALL); - // LogComponentEnable ("BuildingsPropagationLossModel", logLevel); - // LogComponentEnable ("LteInterference", logLevel); - // LogComponentEnable ("LteSpectrumValueHelper", logLevel); - - - struct SnrEfficiencyMcs - { - double snrDb; - double efficiency; - int mcsIndex; - }; - - - SnrEfficiencyMcs snrEfficiencyMcs[] = { - { -5.00000, 0.08024, -1}, - { -4.00000, 0.10030, -1}, - { -3.00000, 0.12518, -1}, - { -2.00000, 0.15589, 0}, - { -1.00000, 0.19365, 0}, - { 0.00000, 0.23983, 2}, - { 1.00000, 0.29593, 2}, - { 2.00000, 0.36360, 2}, - { 3.00000, 0.44451, 4}, - { 4.00000, 0.54031, 4}, - { 5.00000, 0.65251, 6}, - { 6.00000, 0.78240, 6}, - { 7.00000, 0.93086, 8}, - { 8.00000, 1.09835, 8}, - { 9.00000, 1.28485, 10}, - { 10.00000, 1.48981, 12}, - { 11.00000, 1.71229, 12}, - { 12.00000, 1.95096, 14}, - { 13.00000, 2.20429, 14}, - { 14.00000, 2.47062, 16}, - { 15.00000, 2.74826, 18}, - { 16.00000, 3.03560, 18}, - { 17.00000, 3.33115, 20}, - { 18.00000, 3.63355, 20}, - { 19.00000, 3.94163, 22}, - { 20.00000, 4.25439, 22}, - { 21.00000, 4.57095, 24}, - { 22.00000, 4.89060, 24}, - { 23.00000, 5.21276, 26}, - { 24.00000, 5.53693, 26}, - { 25.00000, 5.86271, 28}, - { 26.00000, 6.18980, 28}, - { 27.00000, 6.51792, 28}, - { 28.00000, 6.84687, 28}, - { 29.00000, 7.17649, 28}, - { 30.00000, 7.50663, 28}, - }; - - - double txPowerDbm = 30; // default eNB TX power over whole bandwdith - double txPowerLin = pow (10, (txPowerDbm - 30)/10); - double ktDbm = -174; // reference LTE noise PSD - double noisePowerDbm = ktDbm + 10 * log10 (25 * 180000); // corresponds to kT*bandwidth in linear units - double receiverNoiseFigureDb = 9.0; // default UE noise figure - double noiseLin = pow (10, (noisePowerDbm-30+receiverNoiseFigureDb)/10); - double loss[] = {81.0000, 134.0125, 144.1489}; - double dist[] = {100.0, 500.0, 1500}; - - int numOfTests = sizeof (loss) / sizeof (double); - for ( int i = 0 ; i < numOfTests; i++ ) - { - // double lossDb = txPowerDbm - snrEfficiencyMcs[i].snrDb - noisePowerDbm - receiverNoiseFigureDb; - double sinrLin = (txPowerLin*(pow(10, loss[i]/10))) / noiseLin; - // double sinrDb = txPowerDbm- noisePowerDbm - receiverNoiseFigureDb - loss[i]; - double sinrDb = 10*log10(sinrLin); - NS_LOG_INFO (" Ptx " << txPowerDbm << " Pn " << noisePowerDbm << " Fn " << receiverNoiseFigureDb << " Pl " << loss[i] << " dist " << dist[i]); - std::ostringstream name; - name << " snr= " << sinrDb << " dB, " - << " mcs= " << snrEfficiencyMcs[i].mcsIndex; - AddTestCase (new LteShadowingSystemTestCase (name.str (), sinrDb, dist[i], snrEfficiencyMcs[i].mcsIndex)); - } - */ - - - + } @@ -456,6 +262,7 @@ LteFadingTestCase::DoRun (void) // NS_TEST_ASSERT_MSG_EQ_TOL(loss, m_lossRef, 0.1, "Wrong loss !"); } + void LteFadingTestCase::GetFadingSample () { @@ -488,130 +295,3 @@ LteFadingTestCase::GetFadingSample () (*outPsd1)[1] = (10 * log10 (180000*(*outPsd1)[1])) - (10 * log10 (180000*(*inPsd1)[1])); m_fadingSamples.push_back ((*outPsd1)); } - - -//-------------------- SYSTEM TEST --------------------------------- - -/* -LteShadowingSystemTestCase::LteShadowingSystemTestCase (std::string name, double snrDb, double dist, uint16_t mcsIndex) -: TestCase (name), -m_snrDb (snrDb), -m_distance (dist), -m_mcsIndex (mcsIndex) -{ - std::ostringstream sstream1, sstream2; - sstream1 << " snr=" << snrDb - << " mcs=" << mcsIndex << " distance=" << dist; - - NS_LOG_INFO ("Creating LteShadowingSystemTestCase: " + sstream1.str ()); -} - -LteShadowingSystemTestCase::~LteShadowingSystemTestCase () -{ -} - -void -LteShadowingSystemTestCase::DoRun (void) -{ - - // LogLevel logLevel = (LogLevel)(LOG_PREFIX_FUNC | LOG_PREFIX_TIME | LOG_LEVEL_ALL); - // LogComponentEnable ("LteAmc", LOG_LEVEL_ALL); - // LogComponentEnable ("LtePhy", LOG_LEVEL_ALL); - // LogComponentEnable ("LteEnbPhy", LOG_LEVEL_ALL); - // LogComponentEnable ("LteUePhy", LOG_LEVEL_ALL); - // LogComponentEnable ("SingleModelSpectrumChannel", LOG_LEVEL_ALL); - // LogComponentEnable ("BuildingsPropagationLossModel", logLevel); - - LogComponentEnable ("BuildingsPropagationLossModel", LOG_LEVEL_ALL); - - Ptr lteHelper = CreateObject (); - lteHelper->EnableLogComponents (); - lteHelper->EnableMacTraces (); - lteHelper->EnableRlcTraces (); - lteHelper->SetAttribute ("PropagationModel", StringValue ("ns3::BuildingsPropagationLossModel")); - - //Create Nodes: eNodeB and UE - NodeContainer enbNodes; - NodeContainer ueNodes; - enbNodes.Create (1); - ueNodes.Create (1); - NodeContainer allNodes = NodeContainer ( enbNodes, ueNodes ); - - // Install Mobility Model - MobilityHelper mobility; - mobility.SetMobilityModel ("ns3::BuildingsMobilityModel"); - mobility.Install (allNodes); - - // Create Devices and install them in the Nodes (eNB and UE) - NetDeviceContainer enbDevs; - NetDeviceContainer ueDevs; - lteHelper->SetSchedulerType ("ns3::RrFfMacScheduler"); - enbDevs = lteHelper->InstallEnbDevice (enbNodes); - ueDevs = lteHelper->InstallUeDevice (ueNodes); - - Ptr mm_enb = enbNodes.Get (0)->GetObject (); - mm_enb->SetPosition (Vector (0.0, 0.0, 30.0)); - Ptr mm_ue = ueNodes.Get (0)->GetObject (); - mm_ue->SetPosition (Vector (m_distance, 0.0, 1.0)); - - NS_LOG_INFO (" DISTANCE " << mm_ue->GetDistanceFrom (mm_enb)); - - Ptr lteEnbDev = enbDevs.Get (0)->GetObject (); - Ptr enbPhy = lteEnbDev->GetPhy (); - enbPhy->SetAttribute ("TxPower", DoubleValue (30.0)); - enbPhy->SetAttribute ("NoiseFigure", DoubleValue (5.0)); - - Ptr lteUeDev = ueDevs.Get (0)->GetObject (); - Ptr uePhy = lteUeDev->GetPhy (); - uePhy->SetAttribute ("TxPower", DoubleValue (23.0)); - uePhy->SetAttribute ("NoiseFigure", DoubleValue (9.0)); - - // Attach a UE to a eNB - lteHelper->Attach (ueDevs, enbDevs.Get (0)); - - // Activate an EPS bearer - enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE; - EpsBearer bearer (q); - lteHelper->ActivateEpsBearer (ueDevs, bearer); - - // Use testing chunk processor in the PHY layer - // It will be used to test that the SNR is as intended - // Ptr uePhy = ueDevs.Get (0)->GetObject ()->GetPhy ()->GetObject (); - Ptr testSinr = Create (uePhy); - uePhy->GetDownlinkSpectrumPhy ()->AddSinrChunkProcessor (testSinr); - - // Config::Connect ("/NodeList/0/DeviceList/0/LteEnbMac/DlScheduling", - // MakeBoundCallback (&LteTestShadowingDlSchedCallback, this)); - - Simulator::Stop (Seconds (0.005)); - Simulator::Run (); - - double calculatedSinrDb = 10.0 * log10 (testSinr->GetSinr ()[0]); - NS_LOG_INFO ("Distance " << m_distance << " Calculated SINR " << calculatedSinrDb << " ref " << m_snrDb); - Simulator::Destroy (); - NS_TEST_ASSERT_MSG_EQ_TOL (calculatedSinrDb, m_snrDb, 0.001, "Wrong SINR !"); -} - - -void -LteShadowingSystemTestCase::DlScheduling (uint32_t frameNo, uint32_t subframeNo, uint16_t rnti, - uint8_t mcsTb1, uint16_t sizeTb1, uint8_t mcsTb2, uint16_t sizeTb2) -{ - static bool firstTime = true; - - if ( firstTime ) - { - firstTime = false; - NS_LOG_INFO ("SNR\tRef_MCS\tCalc_MCS"); - } - - - if ( (frameNo > 1) || (subframeNo > 4) ) - { - NS_LOG_INFO (m_snrDb << "\t" << m_mcsIndex << "\t" << (uint16_t)mcsTb1); - - NS_TEST_ASSERT_MSG_EQ ((uint16_t)mcsTb1, m_mcsIndex, "Wrong MCS index"); - } - -} -*/ diff --git a/src/lte/test/lte-test-mimo.cc b/src/lte/test/lte-test-mimo.cc new file mode 100644 index 000000000..4b1589e72 --- /dev/null +++ b/src/lte/test/lte-test-mimo.cc @@ -0,0 +1,286 @@ +/* -*- 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: Marco Miozzo + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ns3/radio-bearer-stats-calculator.h" +#include +#include +#include "ns3/lte-test-mimo.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "ns3/string.h" +#include "ns3/double.h" +#include +#include +#include +#include +#include +#include +#include + + +NS_LOG_COMPONENT_DEFINE ("LenaTestMimo"); + +using namespace ns3; + + +LenaTestMimoSuite::LenaTestMimoSuite () + : TestSuite ("lte-mimo", SYSTEM) +{ + NS_LOG_INFO ("creating LenaMimoTestCase"); + + // RR DOWNLINK- DISTANCE 300 + // [0, 0.2] sec TxMode 0: MCS 20 -> TB size 1191 + // [0.2, 0.3] sec TxMode 1: MCS 26 -> TB size 1836 + // [0.3, 0.4] sec TxMode 2: MCS 18 -> TB size 967 (x2 layers) + // --> + std::vector estThrDl; + estThrDl.push_back (119100); // TTI 1 estimated throughput for TxMode 1 + estThrDl.push_back (183600); // TTI 2 estimated throughput for TxMode 2 + estThrDl.push_back (193400); // TTI 3 estimated throughput for TxMode 3 + AddTestCase (new LenaMimoTestCase(300, estThrDl, "ns3::RrFfMacScheduler")); + AddTestCase (new LenaMimoTestCase(300, estThrDl, "ns3::PfFfMacScheduler")); + + +} + +static LenaTestMimoSuite lenaTestMimoSuite; + +std::string +LenaMimoTestCase::BuildNameString (uint16_t dist) +{ + std::ostringstream oss; + oss << " UE distance " << dist << " m"; + return oss.str (); +} + +LenaMimoTestCase::LenaMimoTestCase (uint16_t dist, std::vector estThrDl, std::string schedulerType) + : TestCase (BuildNameString (dist)), + m_dist (dist), + m_estThrDl (estThrDl), + m_schedulerType (schedulerType) +{ +} + +LenaMimoTestCase::~LenaMimoTestCase () +{ +} + +void +LenaMimoTestCase::DoRun (void) +{ +// Config::SetDefault ("ns3::LteSpectrumPhy::PemEnabled", BooleanValue (false)); + Config::SetDefault ("ns3::LteAmc::AmcModel", EnumValue (LteAmc::PiroEW2010)); + LogComponentDisableAll (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 ("LtePhy", LOG_LEVEL_ALL); +// LogComponentEnable ("LteEnbPhy", LOG_LEVEL_ALL); +// LogComponentEnable ("LteUePhy", LOG_LEVEL_ALL); + +// LogComponentEnable ("LteSpectrumPhy", LOG_LEVEL_ALL); +// LogComponentEnable ("LteInterference", LOG_LEVEL_ALL); +// LogComponentEnable ("LteSinrChunkProcessor", LOG_LEVEL_ALL); +// +// LogComponentEnable ("LtePropagationLossModel", LOG_LEVEL_ALL); +// LogComponentEnable ("LossModel", LOG_LEVEL_ALL); +// LogComponentEnable ("ShadowingLossModel", LOG_LEVEL_ALL); +// LogComponentEnable ("PenetrationLossModel", LOG_LEVEL_ALL); +// LogComponentEnable ("MultipathLossModel", LOG_LEVEL_ALL); +// LogComponentEnable ("PathLossModel", LOG_LEVEL_ALL); +// +// LogComponentEnable ("LteNetDevice", LOG_LEVEL_ALL); +// LogComponentEnable ("LteUeNetDevice", LOG_LEVEL_ALL); +// LogComponentEnable ("LteEnbNetDevice", LOG_LEVEL_ALL); + +// LogComponentEnable ("LteMiErrorModel", LOG_LEVEL_ALL); +// LogComponentEnable ("LteAmc", LOG_LEVEL_ALL); +// LogComponentEnable ("LteSpectrumPhy", LOG_LEVEL_ALL); + + LogComponentEnable ("LenaTestMimo", LOG_LEVEL_ALL); +// LogComponentEnable ("BuildingsPropagationLossModel", LOG_LEVEL_ALL); +// LogComponentEnable ("RrFfMacScheduler", LOG_LEVEL_ALL); +// LogComponentEnable ("PfFfMacScheduler", LOG_LEVEL_ALL); + + + /** + * Initialize Simulation Scenario: 1 eNB and m_nUser UEs + */ + + + Ptr lteHelper = CreateObject (); + + + lteHelper->SetAttribute ("PathlossModel", StringValue ("ns3::HybridBuildingsPropagationLossModel")); + lteHelper->SetPathlossModelAttribute ("ShadowSigmaOutdoor", DoubleValue (0.0)); + lteHelper->SetPathlossModelAttribute ("ShadowSigmaIndoor", DoubleValue (0.0)); + lteHelper->SetPathlossModelAttribute ("ShadowSigmaExtWalls", DoubleValue (0.0)); + +// lteHelper->EnableLogComponents (); + + // Create Nodes: eNodeB and UE + NodeContainer enbNodes; + NodeContainer ueNodes; + enbNodes.Create (1); + ueNodes.Create (1); + + // Install Mobility Model + MobilityHelper mobility; + mobility.SetMobilityModel ("ns3::BuildingsMobilityModel"); + mobility.Install (enbNodes); + mobility.SetMobilityModel ("ns3::BuildingsMobilityModel"); + mobility.Install (ueNodes); + + // Create Devices and install them in the Nodes (eNB and UE) + NetDeviceContainer enbDevs; + NetDeviceContainer ueDevs; + lteHelper->SetSchedulerType (m_schedulerType); + enbDevs = lteHelper->InstallEnbDevice (enbNodes); + ueDevs = lteHelper->InstallUeDevice (ueNodes); + + // Attach a UE to a eNB + lteHelper->Attach (ueDevs, enbDevs.Get (0)); + + // Activate an EPS bearer + enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE; + EpsBearer bearer (q); + lteHelper->ActivateEpsBearer (ueDevs, bearer, EpcTft::Default ()); + + + Ptr lteEnbDev = enbDevs.Get (0)->GetObject (); + Ptr enbPhy = lteEnbDev->GetPhy (); + enbPhy->SetAttribute ("TxPower", DoubleValue (46.0)); + enbPhy->SetAttribute ("NoiseFigure", DoubleValue (5.0)); + Ptr mmenb = enbNodes.Get (0)->GetObject (); + mmenb->SetPosition (Vector (0.0, 0.0, 30.0)); + + // Set UE's position and power + Ptr mmue = ueNodes.Get (0)->GetObject (); + mmue->SetPosition (Vector (m_dist, 0.0, 1.0)); + Ptr lteUeDev = ueDevs.Get (0)->GetObject (); + Ptr uePhy = lteUeDev->GetPhy (); + uePhy->SetAttribute ("TxPower", DoubleValue (23.0)); + uePhy->SetAttribute ("NoiseFigure", DoubleValue (9.0)); + + + lteHelper->EnableRlcTraces (); + lteHelper->EnableMacTraces (); + double simulationTime = 0.401; + double tolerance = 0.1; + + uint8_t rnti = ueDevs.Get (0)->GetObject ()->GetRrc ()->GetRnti (); + Ptr enbNetDev = enbDevs.Get (0)->GetObject (); + + PointerValue ptrval; + enbNetDev->GetAttribute ("FfMacScheduler", ptrval); + Ptr pfsched; + Ptr rrsched; + if (m_schedulerType.compare ("ns3::RrFfMacScheduler") == 0) + { + rrsched = ptrval.Get (); + if (rrsched == 0) + { + NS_FATAL_ERROR ("No RR Scheduler available"); + } + + Simulator::Schedule (Seconds (0.2), &RrFfMacScheduler::TransmissionModeConfigurationUpdate, rrsched, rnti, 1); + Simulator::Schedule (Seconds (0.3), &RrFfMacScheduler::TransmissionModeConfigurationUpdate, rrsched, rnti, 2); + } + else if (m_schedulerType.compare ("ns3::PfFfMacScheduler") == 0) + { + pfsched = ptrval.Get (); + if (pfsched == 0) + { + NS_FATAL_ERROR ("No Pf Scheduler available"); + } + + Simulator::Schedule (Seconds (0.2), &PfFfMacScheduler::TransmissionModeConfigurationUpdate, pfsched, rnti, 1); + Simulator::Schedule (Seconds (0.3), &PfFfMacScheduler::TransmissionModeConfigurationUpdate, pfsched, rnti, 2); + } + else + { + NS_FATAL_ERROR ("Scheduler not supported by this test"); + } + + + Ptr rlcStats = lteHelper->GetRlcStats (); + rlcStats->SetAttribute ("EpochDuration", TimeValue (Seconds (0.1))); + + + /** + * Check that the assignation is done in a RR fashion + */ + NS_LOG_INFO (m_schedulerType << " MIMO test:"); + double sampleTime = 0.2; + for (uint8_t j = 0; j < m_estThrDl.size (); j ++) + { + NS_LOG_INFO ("\t test with user at distance " << m_dist << " time " << sampleTime); + // get the imsi + uint64_t imsi = ueDevs.Get (0)->GetObject ()->GetImsi (); + // get the lcId + uint8_t lcId = ueDevs.Get (0)->GetObject ()->GetRrc ()->GetLcIdVector ().at (0); + Time t = Seconds (sampleTime); + Simulator::Schedule(t, &LenaMimoTestCase::GetRlcBufferSample, this, rlcStats, imsi, lcId); + sampleTime += 0.1; + } + Simulator::Stop (Seconds (simulationTime)); + Simulator::Run (); + Simulator::Destroy (); + + NS_LOG_INFO ("Check consistency"); + for (uint8_t i = 0; i < m_estThrDl.size (); i++) + { + NS_LOG_INFO ("\tTTI " << i + 1 << " bytes rxed " << (double)m_dlDataRxed.at (i) << " ref " << m_estThrDl.at (i)); + NS_TEST_ASSERT_MSG_EQ_TOL ((double)m_dlDataRxed.at (i) , m_estThrDl.at (i), m_estThrDl.at (i) * tolerance, " Unfair Throughput!"); + } + +} + + +void +LenaMimoTestCase::GetRlcBufferSample (Ptr rlcStats, uint64_t imsi, uint8_t lcId) +{ + m_dlDataRxed.push_back (rlcStats->GetDlRxData (imsi, lcId)); +// NS_LOG_INFO ("\t get bytes " << m_dlDataRxed.at (m_dlDataRxed.size () - 1)); +} + + diff --git a/src/lte/test/lte-test-mimo.h b/src/lte/test/lte-test-mimo.h new file mode 100644 index 000000000..060d87adc --- /dev/null +++ b/src/lte/test/lte-test-mimo.h @@ -0,0 +1,67 @@ +/* -*- 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: Marco Miozzo + */ + +#ifndef LENA_TEST_MIMO_H +#define LENA_TEST_MIMO_H + +#include "ns3/simulator.h" +#include "ns3/test.h" + + +using namespace ns3; + + +/** + * This system test program creates different test cases with a single eNB... + */ +class LenaMimoTestCase : public TestCase +{ +public: + LenaMimoTestCase (uint16_t dist, std::vector estThrDl, std::string schedulerType); + virtual ~LenaMimoTestCase (); + +private: + virtual void DoRun (void); + + void GetRlcBufferSample (Ptr rlcStats, uint64_t imsi, uint8_t rnti); + + static std::string BuildNameString (uint16_t dist); + uint16_t m_nUser; + uint16_t m_nLc; + uint16_t m_dist; + std::vector m_estThrDl; + std::string m_schedulerType; + + std::vector m_dlDataRxed; + +}; + + + +class LenaTestMimoSuite : public TestSuite +{ +public: + LenaTestMimoSuite (); +}; + + + + +#endif /* LENA_TEST_MIMO_H */ diff --git a/src/lte/test/test-lte-epc-e2e-data.cc b/src/lte/test/test-lte-epc-e2e-data.cc index b67ce3e00..a16946b9a 100644 --- a/src/lte/test/test-lte-epc-e2e-data.cc +++ b/src/lte/test/test-lte-epc-e2e-data.cc @@ -109,7 +109,7 @@ LteEpcE2eDataTestCase::~LteEpcE2eDataTestCase () void LteEpcE2eDataTestCase::DoRun () { - + Config::SetDefault ("ns3::LteSpectrumPhy::PemEnabled", BooleanValue (false)); Ptr lteHelper = CreateObject (); Ptr epcHelper = CreateObject (); lteHelper->SetEpcHelper (epcHelper); diff --git a/src/lte/wscript b/src/lte/wscript index 72ffe7d16..dec2ec974 100644 --- a/src/lte/wscript +++ b/src/lte/wscript @@ -92,7 +92,8 @@ def build(bld): 'test/epc-test-s1u-uplink.cc', 'test/test-lte-epc-e2e-data.cc', 'test/test-lte-antenna.cc', - 'test/lte-test-phy-error-model.cc' + 'test/lte-test-phy-error-model.cc', + 'test/lte-test-mimo.cc' ] headers = bld.new_task_gen(features=['ns3header']) @@ -176,7 +177,8 @@ def build(bld): 'test/lte-test-rlc-am-e2e.h', 'model/epc-tft.h', 'model/epc-tft-classifier.h', - 'model/lte-mi-error-model.h' + 'model/lte-mi-error-model.h', + 'test/lte-test-mimo.h' ] if (bld.env['ENABLE_EXAMPLES']):