diff --git a/src/lte/helper/lte-helper.cc b/src/lte/helper/lte-helper.cc index efeeed390..238b7a409 100644 --- a/src/lte/helper/lte-helper.cc +++ b/src/lte/helper/lte-helper.cc @@ -600,11 +600,17 @@ LteHelper::Attach (Ptr ueDevice) { NS_LOG_FUNCTION (this); + if (m_epcHelper == 0) + { + NS_FATAL_ERROR ("This function is not valid without properly configured EPC"); + } + Ptr ueLteDevice = ueDevice->GetObject (); if (ueLteDevice == 0) { NS_FATAL_ERROR ("The passed NetDevice must be an LteUeNetDevice"); } + Ptr uePhy = ueLteDevice->GetPhy (); uePhy->CellSearch (); } @@ -867,6 +873,139 @@ LteHelper::ActivateDataRadioBearer (NetDeviceContainer ueDevices, EpsBearer bear } } +void +LteHelper::SetEnbPlmnId (NetDeviceContainer enbDevices, uint32_t plmnId) +{ + for (NetDeviceContainer::Iterator i = enbDevices.Begin (); + i != enbDevices.End (); ++i) + { + SetEnbPlmnId (*i, plmnId); + } +} + +void +LteHelper::SetEnbPlmnId (Ptr enbDevice, uint32_t plmnId) +{ + NS_LOG_FUNCTION (this << enbDevice << plmnId); + + Ptr enbLteDevice = enbDevice->GetObject (); + if (enbLteDevice == 0) + { + NS_FATAL_ERROR ("The passed NetDevice must be an LteEnbNetDevice"); + } + + Ptr rrc = enbLteDevice->GetRrc (); + LteRrcSap::SystemInformationBlockType1 sib1 = rrc->GetSystemInformationBlockType1 (); + sib1.cellAccessRelatedInfo.plmnIdentityInfo.plmnIdentity = plmnId; + rrc->SetSystemInformationBlockType1 (sib1); +} + +void +LteHelper::SetEnbCsgId (NetDeviceContainer enbDevices, uint32_t csgId, + bool csgIndication) +{ + for (NetDeviceContainer::Iterator i = enbDevices.Begin (); + i != enbDevices.End (); ++i) + { + SetEnbCsgId (*i, csgId, csgIndication); + } +} + +void +LteHelper::SetEnbCsgId (Ptr enbDevice, uint32_t csgId, + bool csgIndication) +{ + NS_LOG_FUNCTION (this << enbDevice << csgId << csgIndication); + + Ptr enbLteDevice = enbDevice->GetObject (); + if (enbLteDevice == 0) + { + NS_FATAL_ERROR ("The passed NetDevice must be an LteEnbNetDevice"); + } + + Ptr rrc = enbLteDevice->GetRrc (); + LteRrcSap::SystemInformationBlockType1 sib1 = rrc->GetSystemInformationBlockType1 (); + sib1.cellAccessRelatedInfo.csgIdentity = csgId; + sib1.cellAccessRelatedInfo.csgIndication = csgIndication; + rrc->SetSystemInformationBlockType1 (sib1); +} + +void +LteHelper::SetEnbQRxLevMin (NetDeviceContainer enbDevices, int8_t qRxLevMin) +{ + for (NetDeviceContainer::Iterator i = enbDevices.Begin (); + i != enbDevices.End (); ++i) + { + SetEnbQRxLevMin (*i, qRxLevMin); + } +} + +void +LteHelper::SetEnbQRxLevMin (Ptr enbDevice, int8_t qRxLevMin) +{ + NS_LOG_FUNCTION (this << enbDevice << (int16_t) qRxLevMin); + + Ptr enbLteDevice = enbDevice->GetObject (); + if (enbLteDevice == 0) + { + NS_FATAL_ERROR ("The passed NetDevice must be an LteEnbNetDevice"); + } + + Ptr rrc = enbLteDevice->GetRrc (); + LteRrcSap::SystemInformationBlockType1 sib1 = rrc->GetSystemInformationBlockType1 (); + sib1.cellSelectionInfo.qRxLevMin = qRxLevMin; + rrc->SetSystemInformationBlockType1 (sib1); +} + +void +LteHelper::SetUePlmnId (NetDeviceContainer ueDevices, uint32_t plmnId) +{ + for (NetDeviceContainer::Iterator i = ueDevices.Begin (); + i != ueDevices.End (); ++i) + { + SetUePlmnId (*i, plmnId); + } +} + +void +LteHelper::SetUePlmnId (Ptr ueDevice, uint32_t plmnId) +{ + NS_LOG_FUNCTION (this << ueDevice << plmnId); + + Ptr ueLteDevice = ueDevice->GetObject (); + if (ueLteDevice == 0) + { + NS_FATAL_ERROR ("The passed NetDevice must be an LteUeNetDevice"); + } + + ueLteDevice->GetNas ()->SetPlmnId (plmnId); +} + +void +LteHelper::SetUeCsgId (NetDeviceContainer ueDevices, uint32_t csgId) +{ + for (NetDeviceContainer::Iterator i = ueDevices.Begin (); + i != ueDevices.End (); ++i) + { + SetUeCsgId (*i, csgId); + } +} + +void +LteHelper::SetUeCsgId (Ptr ueDevice, uint32_t csgId) +{ + NS_LOG_FUNCTION (this << ueDevice << csgId); + + Ptr ueLteDevice = ueDevice->GetObject (); + if (ueLteDevice == 0) + { + NS_FATAL_ERROR ("The passed NetDevice must be an LteUeNetDevice"); + } + + ueLteDevice->GetNas ()->SetCsgId (csgId); +} + + void LteHelper::EnableLogComponents (void) { diff --git a/src/lte/helper/lte-helper.h b/src/lte/helper/lte-helper.h index a9eca512c..46df97cb2 100644 --- a/src/lte/helper/lte-helper.h +++ b/src/lte/helper/lte-helper.h @@ -49,8 +49,8 @@ class PropagationLossModel; class SpectrumPropagationLossModel; /** - * Creation and configuration of LTE entities - * + * \ingroup lte + * \brief Creation and configuration of LTE entities */ class LteHelper : public Object { @@ -163,6 +163,7 @@ public: * \param v the value of the attribute */ void SetSpectrumChannelAttribute (std::string n, const AttributeValue &v); + /** * create a set of eNB devices * @@ -183,10 +184,11 @@ public: /** * \brief Instruct a set of UE devices to attach to a suitable cell. - * \param ueDevices + * \param ueDevices the set of UE devices to be attached * - * By calling this, the UE will start the initial cell selection procedure at - * the beginning of simulation. + * By calling this, the UE will start the cell search and initial cell + * selection procedure at the beginning of simulation. Note that this function + * can only be used in EPC-enabled simulation. */ void Attach (NetDeviceContainer ueDevices); @@ -194,8 +196,9 @@ public: * \brief Instruct a UE device to attach to a suitable cell. * \param ueDevice * - * By calling this, the UE will start the initial cell selection procedure at - * the beginning of simulation. + * By calling this, the UE will start the cell search and initial cell + * selection procedure at the beginning of simulation. Note that this function + * can only be used in EPC-enabled simulation. */ void Attach (Ptr ueDevice); @@ -336,6 +339,206 @@ public: */ void SetFadingModelAttribute (std::string n, const AttributeValue &v); + /** + * \brief Associate the eNodeB devices with a particular network operator. + * \param enbDevices the set of eNodeB devices to be updated + * \param plmnId the intended Public Land Mobile Network identity + * + * PLMN identity is a number identifying a cellular network of one operator in + * one country. eNodeB is associated with a single PLMN identity, which will + * be used to limit access of UE to it, so that only UE with the same value of + * PLMN identity is allowed. + * + * If not set, eNodeB devices bear a default PLMN identity of 0. + * + * This restriction only applies to initial cell selection and EPC-enabled + * simulation. + * + * \sa SetUePlmnId(NetDeviceContainer, uint32_t) + */ + void SetEnbPlmnId (NetDeviceContainer enbDevices, uint32_t plmnId); + + /** + * \brief Associate the eNodeB device with a particular network operator. + * \param enbDevice + * \param plmnId the intended Public Land Mobile Network identity + * + * PLMN identity is a number identifying a cellular network of one operator in + * one country. eNodeB is associated with a single PLMN identity, which will + * be used to limit access of UE to it, so that only UE with the same value of + * PLMN identity is allowed. + * + * If not set, eNodeB devices bear a default PLMN identity of 0. + * + * This restriction only applies to initial cell selection and EPC-enabled + * simulation. + * + * \sa SetUePlmnId(Ptr, uint32_t) + */ + void SetEnbPlmnId (Ptr enbDevice, uint32_t plmnId); + + /** + * \brief Associate the eNodeB devices with a particular CSG information. + * \param enbDevices the set of eNodeB devices to be updated + * \param csgId the intended Closed Subscriber Group identity + * \param csgIndication if TRUE, only CSG members are allowed to access the + * cell + * + * CSG identity is a number identifying a Closed Subscriber Group which the + * cell belongs to. eNodeB is associated with a single CSG identity. + * + * The same CSG identity can also be associated to several UEs, which is + * equivalent as enlisting these UEs as the members of this particular CSG. + * When the CSG indication field is set to TRUE, only UEs which are members of + * the CSG (i.e. same CSG ID) can gain access to the eNodeB, therefore + * enforcing closed access mode. Otherwise, the eNodeB operates as a non-CSG + * cell and implements open access mode. + * + * If not set, eNodeB devices are non-CSG cells and bear a CSG identity of 0 + * by default. + * + * This restriction only applies to initial cell selection and EPC-enabled + * simulation. + * + * \sa SetUeCsgId(NetDeviceContainer, uint32_t) + */ + void SetEnbCsgId (NetDeviceContainer enbDevices, uint32_t csgId, + bool csgIndication); + + /** + * \brief Associate the eNodeB devices with a particular CSG information. + * \param enbDevice + * \param csgId the intended Closed Subscriber Group identity + * \param csgIndication if TRUE, only CSG members are allowed to access the + * cell + * + * CSG identity is a number identifying a Closed Subscriber Group which the + * cell belongs to. eNodeB is associated with a single CSG identity. + * + * The same CSG identity can also be associated to several UEs, which is + * equivalent as enlisting these UEs as the members of this particular CSG. + * When the CSG indication field is set to TRUE, only UEs which are members of + * the CSG (i.e. same CSG ID) can gain access to the eNodeB, therefore + * enforcing closed access mode. Otherwise, the eNodeB operates as a non-CSG + * cell and implements open access mode. + * + * If not set, eNodeB devices are non-CSG cells and bear a CSG identity of 0 + * by default. + * + * This restriction only applies to initial cell selection and EPC-enabled + * simulation. + * + * \sa SetUeCsgId(Ptr, uint32_t) + */ + void SetEnbCsgId (Ptr enbDevice, uint32_t csgId, + bool csgIndication); + + /** + * \brief Set the Q-RxLevMin parameter of the eNodeB devices to be used in + * cell selection. + * \param enbDevices the set of eNodeB devices to be updated + * \param qRxLevMin the IE value of Q-RxLevMin parameter, which is + * + * The Q-RxLevMin is a network parameter and is the required minimum RSRP + * level that UE must receive before it may gain access to this cell. The + * actual value of Q-RxLevMin is IE value * 2 [dBm]. + * + * If not set, the default value is -70, which is the minimum possible value. + * This translates to a minimum RSRP of -140 dBm. + * + * This restriction only applies to initial cell selection and EPC-enabled + * simulation. + */ + void SetEnbQRxLevMin (NetDeviceContainer enbDevices, int8_t qRxLevMin); + + /** + * \brief Set the Q-RxLevMin parameter of the eNodeB device to be used in + * cell selection. + * \param enbDevice + * \param qRxLevMin the IE value of Q-RxLevMin parameter, which is + * + * The Q-RxLevMin is a network parameter and is the required minimum RSRP + * level that UE must receive before it may gain access to this cell. The + * actual value of Q-RxLevMin is IE value * 2 [dBm]. + * + * If not set, the default value is -70, which is the minimum possible value. + * This translates to a minimum RSRP of -140 dBm. + * + * This restriction only applies to initial cell selection and EPC-enabled + * simulation. + */ + void SetEnbQRxLevMin (Ptr enbDevice, int8_t qRxLevMin); + + /** + * \brief Associate the UE devices with a particular network operator. + * \param ueDevices the set of UE devices to be updated + * \param plmnId the intended Public Land Mobile Network identity + * + * UE is associated with a single PLMN identity. UE can only gain access to + * cells which bear the same PLMN identity. + * + * If not set, UE devices bear a default PLMN identity of 0. + * + * This restriction only applies to initial cell selection and EPC-enabled + * simulation. + * + * \sa SetEnbPlmnId(NetDeviceContainer, uint32_t) + */ + void SetUePlmnId (NetDeviceContainer ueDevices, uint32_t plmnId); + + /** + * \brief Associate the UE device with a particular network operator. + * \param ueDevice + * \param plmnId the intended Public Land Mobile Network identity + * + * UE is associated with a single PLMN identity. UE can only gain access to + * cells which bear the same PLMN identity. + * + * If not set, UE devices bear a default PLMN identity of 0. + * + * This restriction only applies to initial cell selection and EPC-enabled + * simulation. + * + * \sa SetEnbPlmnId(Ptr, uint32_t) + */ + void SetUePlmnId (Ptr ueDevice, uint32_t plmnId); + + /** + * \brief Enlist the UE devices as members of a particular CSG. + * \param ueDevices the set of UE devices to be updated + * \param csgId the intended Closed Subscriber Group identity + * + * UE is associated with a single CSG identity, and thus becoming a member of + * this particular CSG. As a result, the UE may gain access to cells which + * belong to this CSG. This does not revoke the UE's access to non-CSG cells. + * + * If not set, UE devices bear a default CSG identity of 0. + * + * This restriction only applies to initial cell selection and EPC-enabled + * simulation. + * + * \sa SetEnbCsgId(NetDeviceContainer, uint32_t, bool) + */ + void SetUeCsgId (NetDeviceContainer ueDevices, uint32_t csgId); + + /** + * \brief Enlist the UE device as a member of a particular CSG. + * \param ueDevice + * \param csgId the intended Closed Subscriber Group identity + * + * UE is associated with a single CSG identity, and thus becoming a member of + * this particular CSG. As a result, the UE may gain access to cells which + * belong to this CSG. This does not revoke the UE's access to non-CSG cells. + * + * If not set, UE devices bear a default CSG identity of 0. + * + * This restriction only applies to initial cell selection and EPC-enabled + * simulation. + * + * \sa SetEnbCsgId(Ptr, uint32_t, bool) + */ + void SetUeCsgId (Ptr ueDevice, uint32_t csgId); + /** * Enables logging for all components of the LENA architecture * diff --git a/src/lte/model/epc-ue-nas.cc b/src/lte/model/epc-ue-nas.cc index b00d8e1a1..843526b44 100644 --- a/src/lte/model/epc-ue-nas.cc +++ b/src/lte/model/epc-ue-nas.cc @@ -56,6 +56,8 @@ NS_OBJECT_ENSURE_REGISTERED (EpcUeNas); EpcUeNas::EpcUeNas () : m_state (OFF), + m_plmnId (0), + m_csgId (0), m_asSapProvider (0), m_bidCounter (0) { @@ -73,7 +75,7 @@ void EpcUeNas::DoDispose () { NS_LOG_FUNCTION (this); - delete m_asSapUser; + delete m_asSapUser; } TypeId @@ -101,19 +103,45 @@ EpcUeNas::SetImsi (uint64_t imsi) m_imsi = imsi; } +void +EpcUeNas::SetPlmnId (uint32_t plmnId) +{ + m_plmnId = plmnId; + m_asSapProvider->SetSelectedPlmn (plmnId); +} + +uint32_t +EpcUeNas::GetPlmnId () const +{ + return m_plmnId; +} + +void +EpcUeNas::SetCsgId (uint32_t csgId) +{ + m_csgId = csgId; + m_asSapProvider->SetCsgWhiteList (csgId); +} + +uint32_t +EpcUeNas::GetCsgId () const +{ + return m_csgId; +} + void EpcUeNas::SetAsSapProvider (LteAsSapProvider* s) { m_asSapProvider = s; } -LteAsSapUser* +LteAsSapUser* EpcUeNas::GetAsSapUser () { return m_asSapUser; } -void +void EpcUeNas::SetForwardUpCallback (Callback > cb) { m_forwardUpCallback = cb; diff --git a/src/lte/model/epc-ue-nas.h b/src/lte/model/epc-ue-nas.h index fda378982..47878b1ec 100644 --- a/src/lte/model/epc-ue-nas.h +++ b/src/lte/model/epc-ue-nas.h @@ -65,27 +65,51 @@ public: void SetImsi (uint64_t imsi); /** + * + * \param plmnId Public Land Mobile Network identity + */ + void SetPlmnId (uint32_t plmnId); + + /** + * + * \return plmnId Public Land Mobile Network identity + */ + uint32_t GetPlmnId () const; + + /** + * + * \param csgId Closed Subscriber Group identity + */ + void SetCsgId (uint32_t csgId); + + /** + * + * \return csgId Closed Subscriber Group identity + */ + uint32_t GetCsgId () const; + + /** * Set the AS SAP provider to interact with the NAS entity - * + * * \param s the AS SAP provider */ void SetAsSapProvider (LteAsSapProvider* s); - /** - * - * + /** + * + * * \return the AS SAP user exported by this RRC */ LteAsSapUser* GetAsSapUser (); - /** + /** * set the callback used to forward data packets up the stack - * + * * \param cb the callback */ void SetForwardUpCallback (Callback > cb); - - /** + + /** * \brief Instruct the NAS to go to ACTIVE state * * The end result is equivalent with EMM Registered + ECM Connected states. @@ -168,6 +192,9 @@ private: uint64_t m_imsi; + uint32_t m_plmnId; + uint32_t m_csgId; + LteAsSapProvider* m_asSapProvider; LteAsSapUser* m_asSapUser; diff --git a/src/lte/model/lte-as-sap.h b/src/lte/model/lte-as-sap.h index 2158b9d88..679dbee54 100644 --- a/src/lte/model/lte-as-sap.h +++ b/src/lte/model/lte-as-sap.h @@ -33,7 +33,7 @@ class LteEnbNetDevice; /** * This class implements the Access Stratum (AS) Service Access Point * (SAP), i.e., the interface between the EpcUeNas and the LteUeRrc. - * In particular, this class implements the + * In particular, this class implements the * Provider part of the SAP, i.e., the methods exported by the * LteUeRrc and called by the EpcUeNas. * @@ -43,6 +43,22 @@ class LteAsSapProvider public: virtual ~LteAsSapProvider (); + /** + * \brief Set the selected Public Land Mobile Network identity to be used for + * cell selection. + * + * \param plmnId identity of the selected PLMN + */ + virtual void SetSelectedPlmn (uint32_t plmnId) = 0; + + /** + * \brief Set the selected Closed Subscriber Group subscription list to be + * used for cell selection + * + * \param csgId identity of the subscribed CSG + */ + virtual void SetCsgWhiteList (uint32_t csgId) = 0; + /** * Force the RRC to stay camped on a certain eNB * @@ -51,7 +67,7 @@ public: * \param cellId the Cell ID identifying the eNB */ virtual void ForceCampedOnEnb (uint16_t cellId, uint16_t earfcn) = 0; - + /** * Tell the RRC to go into Connected Mode * @@ -74,7 +90,7 @@ public: virtual void Disconnect () = 0; }; - + /** * This class implements the Access Stratum (AS) Service Access Point @@ -132,8 +148,10 @@ public: MemberLteAsSapProvider (C* owner); // inherited from LteAsSapProvider - virtual void Connect (void); + virtual void SetSelectedPlmn (uint32_t plmnId); + virtual void SetCsgWhiteList (uint32_t csgId); virtual void ForceCampedOnEnb (uint16_t cellId, uint16_t earfcn); + virtual void Connect (void); virtual void SendData (Ptr packet, uint8_t bid); virtual void Disconnect (); @@ -155,12 +173,25 @@ MemberLteAsSapProvider::MemberLteAsSapProvider () template void +MemberLteAsSapProvider::SetSelectedPlmn (uint32_t plmnId) +{ + m_owner->DoSetSelectedPlmn (plmnId); +} + +template +void +MemberLteAsSapProvider::SetCsgWhiteList (uint32_t csgId) +{ + m_owner->DoSetCsgWhiteList (csgId); +} + +template +void MemberLteAsSapProvider::ForceCampedOnEnb (uint16_t cellId, uint16_t earfcn) { m_owner->DoForceCampedOnEnb (cellId, earfcn); } - template void MemberLteAsSapProvider::Connect () diff --git a/src/lte/model/lte-common.cc b/src/lte/model/lte-common.cc index 69392cdd2..39441cbfa 100644 --- a/src/lte/model/lte-common.cc +++ b/src/lte/model/lte-common.cc @@ -264,6 +264,27 @@ EutranMeasurementMapping::GetActualA3Offset (int8_t a3Offset) return (static_cast (a3Offset) * 0.5); } +double +EutranMeasurementMapping::GetActualQRxLevMin (int8_t qRxLevMin) +{ + if ((qRxLevMin < -70) || (qRxLevMin > -22)) + { + NS_FATAL_ERROR ("The value " << qRxLevMin << " is out of the allowed range (-70..-22) for Q-RxLevMin"); + } + + return (static_cast (qRxLevMin) * 2); +} + +double +EutranMeasurementMapping::GetActualQQualMin (int8_t qQualMin) +{ + if ((qQualMin < -34) || (qQualMin > -3)) + { + NS_FATAL_ERROR ("The value " << qQualMin << " is out of the allowed range (-34..-3) for Q-QualMin"); + } + + return (static_cast (qQualMin)); +} }; // namespace ns3 diff --git a/src/lte/model/lte-common.h b/src/lte/model/lte-common.h index d508ed084..31f33e4b5 100644 --- a/src/lte/model/lte-common.h +++ b/src/lte/model/lte-common.h @@ -220,19 +220,45 @@ public: * \return hysteresis actual value in dB, which is IE value * 0.5 dB * * As per section 6.3.5 of 3GPP TS 36.331. + * + * \sa LteRrcSap::ReportConfigEutra */ static double GetActualHysteresis (uint8_t hysteresis); /** * \brief Returns the actual value of an a3-Offset parameter. - * \param IE value of hysteresis + * \param IE value of a3-offset * \return a3-Offset actual value in dB, which is IE value * 0.5 dB * * As per section 6.3.5 of 3GPP TS 36.331. + * + * \sa LteRrcSap::ReportConfigEutra */ static double GetActualA3Offset (int8_t a3Offset); -}; + /** + * \brief Returns the actual value of an Q-RxLevMin parameter. + * \param IE value of Q-RxLevMin + * \return Q-RxLevMin actual value in dBm, which is IE value * 2 dBm + * + * As per section 6.3.4 of 3GPP TS 36.331. + * + * \sa LteRrcSap::CellSelectionInfo + */ + static double GetActualQRxLevMin (int8_t qRxLevMin); + + /** + * \brief Returns the actual value of an Q-QualMin parameter. + * \param IE value of Q-QualMin + * \return Q-QualMin actual value in dB, which is IE value dB + * + * As per section 6.3.4 of 3GPP TS 36.331. + * + * \sa LteRrcSap::CellSelectionInfo + */ + static double GetActualQQualMin (int8_t qQualMin); + +}; // end of class EutranMeasurementMapping }; // namespace ns3 diff --git a/src/lte/model/lte-enb-rrc.cc b/src/lte/model/lte-enb-rrc.cc index 9ee71637b..1ce3ae438 100644 --- a/src/lte/model/lte-enb-rrc.cc +++ b/src/lte/model/lte-enb-rrc.cc @@ -533,10 +533,10 @@ UeManager::PrepareHandover (uint16_t cellId) hpi.asConfig.sourceRadioResourceConfig = GetRadioResourceConfigForHandoverPreparationInfo (); hpi.asConfig.sourceMasterInformationBlock.dlBandwidth = m_rrc->m_dlBandwidth; hpi.asConfig.sourceMasterInformationBlock.systemFrameNumber = 0; - hpi.asConfig.sourceSystemInformationBlockType1.cellAccessRelatedInfo.plmnIdentityInfo.plmnIdentity = 0; + hpi.asConfig.sourceSystemInformationBlockType1.cellAccessRelatedInfo.plmnIdentityInfo.plmnIdentity = m_rrc->m_sib1.cellAccessRelatedInfo.plmnIdentityInfo.plmnIdentity; hpi.asConfig.sourceSystemInformationBlockType1.cellAccessRelatedInfo.cellIdentity = m_rrc->m_cellId; - hpi.asConfig.sourceSystemInformationBlockType1.cellAccessRelatedInfo.csgIndication = 0; - hpi.asConfig.sourceSystemInformationBlockType1.cellAccessRelatedInfo.csgIdentity = 0; + hpi.asConfig.sourceSystemInformationBlockType1.cellAccessRelatedInfo.csgIndication = m_rrc->m_sib1.cellAccessRelatedInfo.csgIndication; + hpi.asConfig.sourceSystemInformationBlockType1.cellAccessRelatedInfo.csgIdentity = m_rrc->m_sib1.cellAccessRelatedInfo.csgIdentity; LteEnbCmacSapProvider::RachConfig rc = m_rrc->m_cmacSapProvider->GetRachConfig (); hpi.asConfig.sourceSystemInformationBlockType2.radioResourceConfigCommon.rachConfigCommon.preambleInfo.numberOfRaPreambles = rc.numberOfRaPreambles; hpi.asConfig.sourceSystemInformationBlockType2.radioResourceConfigCommon.rachConfigCommon.raSupervisionInfo.preambleTransMax = rc.preambleTransMax; @@ -1657,18 +1657,14 @@ LteEnbRrc::ConfigureCell (uint8_t ulBandwidth, uint8_t dlBandwidth, mib.dlBandwidth = m_dlBandwidth; m_cphySapProvider->SetMasterInformationBlock (mib); - // Enabling SIB1 transmission - LteRrcSap::SystemInformationBlockType1 sib1; - sib1.cellAccessRelatedInfo.cellIdentity = cellId; - sib1.cellAccessRelatedInfo.csgIndication = false; - sib1.cellAccessRelatedInfo.csgIdentity = 0; - LteRrcSap::PlmnIdentityInfo plmnIdentityInfo; - plmnIdentityInfo.plmnIdentity = 0; - sib1.cellAccessRelatedInfo.plmnIdentityInfo = plmnIdentityInfo; - sib1.cellSelectionInfo.qQualMin = -34; - sib1.cellSelectionInfo.qRxLevMin = -70; - // TODO the above fields should not be hardcoded like this - m_cphySapProvider->SetSystemInformationBlockType1 (sib1); + // Enabling SIB1 transmission with default values + m_sib1.cellAccessRelatedInfo.cellIdentity = cellId; + m_sib1.cellAccessRelatedInfo.csgIndication = false; + m_sib1.cellAccessRelatedInfo.csgIdentity = 0; + m_sib1.cellAccessRelatedInfo.plmnIdentityInfo.plmnIdentity = 0; + m_sib1.cellSelectionInfo.qQualMin = -34; // not used, set as minimum value + m_sib1.cellSelectionInfo.qRxLevMin = -70; // set as minimum value + m_cphySapProvider->SetSystemInformationBlockType1 (m_sib1); /* * Enabling transmission of other SIB. The first time System Information is @@ -1687,6 +1683,10 @@ void LteEnbRrc::SetCellId (uint16_t cellId) { m_cellId = cellId; + + // update SIB1 too + m_sib1.cellAccessRelatedInfo.cellIdentity = cellId; + m_cphySapProvider->SetSystemInformationBlockType1 (m_sib1); } bool @@ -2145,6 +2145,19 @@ LteEnbRrc::AddX2Neighbour (uint16_t cellId) m_neighbourRelationTable[cellId] = neighbourRelation; } +LteRrcSap::SystemInformationBlockType1 +LteEnbRrc::GetSystemInformationBlockType1 () const +{ + return m_sib1; +} + +void +LteEnbRrc::SetSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 sib1) +{ + m_sib1 = sib1; + m_cphySapProvider->SetSystemInformationBlockType1 (sib1); +} + // from 3GPP TS 36.213 table 8.2-1 UE Specific SRS Periodicity const uint8_t SRS_ENTRIES = 9; @@ -2287,5 +2300,6 @@ LteEnbRrc::SendSystemInformation () Simulator::Schedule (m_systemInformationPeriodicity, &LteEnbRrc::SendSystemInformation, this); } + } // namespace ns3 diff --git a/src/lte/model/lte-enb-rrc.h b/src/lte/model/lte-enb-rrc.h index 45e0de6f5..8a592b873 100644 --- a/src/lte/model/lte-enb-rrc.h +++ b/src/lte/model/lte-enb-rrc.h @@ -766,6 +766,18 @@ public: */ uint32_t GetSrsPeriodicity () const; + /** + * + * \param sib1 System Information Block Type 1 to be broadcasted over BCH + */ + void SetSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 sib1); + + /** + * + * \return the System Information Block Type 1 that is currently broadcasted over BCH + */ + LteRrcSap::SystemInformationBlockType1 GetSystemInformationBlockType1 () const; + private: /** @@ -843,6 +855,9 @@ private: uint16_t m_ulBandwidth; uint16_t m_lastAllocatedRnti; + /// the System Information Block Type 1 that is currently broadcasted over BCH + LteRrcSap::SystemInformationBlockType1 m_sib1; + std::map > m_ueMap; /** diff --git a/src/lte/model/lte-ue-rrc.cc b/src/lte/model/lte-ue-rrc.cc index efbd3396a..08db7dff4 100644 --- a/src/lte/model/lte-ue-rrc.cc +++ b/src/lte/model/lte-ue-rrc.cc @@ -131,7 +131,9 @@ LteUeRrc::LteUeRrc () m_connectionPending (false), m_hasReceivedMib (false), m_hasReceivedSib1 (false), - m_hasReceivedSib2 (false) + m_hasReceivedSib2 (false), + m_selectedPlmn (0), + m_csgWhiteList (0) { NS_LOG_FUNCTION (this); m_cphySapUser = new MemberLteUeCphySapUser (this); @@ -505,6 +507,20 @@ LteUeRrc::DoNotifyRandomAccessFailed () } +void +LteUeRrc::DoSetSelectedPlmn (uint32_t plmnId) +{ + NS_LOG_FUNCTION (this << plmnId); + m_selectedPlmn = plmnId; +} + +void +LteUeRrc::DoSetCsgWhiteList (uint32_t csgId) +{ + NS_LOG_FUNCTION (this << csgId); + m_csgWhiteList = csgId; +} + void LteUeRrc::DoForceCampedOnEnb (uint16_t cellId, uint16_t earfcn) { @@ -566,7 +582,7 @@ LteUeRrc::DoRecvMasterInformationBlock (uint16_t cellId, if ((m_state == IDLE_CELL_SELECTION) && m_hasReceivedSib1) { - InitialCellSelection (); + EvaluateCellForSelection (); } // manual attachment procedure may camp without SIB1 @@ -589,7 +605,7 @@ LteUeRrc::DoRecvSystemInformationBlockType1 (uint16_t cellId, if (m_state == IDLE_CELL_SELECTION && m_hasReceivedMib) { - InitialCellSelection (); + EvaluateCellForSelection (); } } @@ -598,51 +614,23 @@ LteUeRrc::DoReportUeMeasurements (LteUeCphySapUser::UeMeasurementsParameters par { NS_LOG_FUNCTION (this); + bool useLayer3Filtering = (m_state == CONNECTED_NORMALLY); + + std::vector ::iterator newMeasIt; + for (newMeasIt = params.m_ueMeasurementsList.begin (); + newMeasIt != params.m_ueMeasurementsList.end (); ++newMeasIt) + { + SaveUeMeasurements (newMeasIt->m_cellId, newMeasIt->m_rsrp, + newMeasIt->m_rsrq, useLayer3Filtering); + } + if (m_state == IDLE_CELL_SELECTION) { - double maxRsrp = -std::numeric_limits::infinity (); - uint16_t maxRsrpCellId = 0; - - std::vector ::iterator newMeasIt; - for (newMeasIt = params.m_ueMeasurementsList.begin (); - newMeasIt != params.m_ueMeasurementsList.end (); ++newMeasIt) - { - /* - * This block attempts to find a cell with strongest RSRP and has not - * yet been identified as "acceptable cell". - */ - if (maxRsrp < newMeasIt->m_rsrp) - { - std::set::const_iterator itCell; - itCell = m_acceptableCell.find (newMeasIt->m_cellId); - if (itCell == m_acceptableCell.end ()) - { - maxRsrp = newMeasIt->m_rsrp; - maxRsrpCellId = newMeasIt->m_cellId; - } - } - } - - if (maxRsrpCellId == 0) - { - NS_LOG_WARN (this << " Cell search has detected no surrounding cell"); - } - else - { - m_cphySapProvider->SyncronizeWithEnb (maxRsrpCellId, m_dlEarfcn); - } - - } // end of if (m_state == IDLE_CELL_SELECTION) + // start decoding BCH + SynchronizeToStrongestCell (); + } else { - std::vector ::iterator newMeasIt; - for (newMeasIt = params.m_ueMeasurementsList.begin (); - newMeasIt != params.m_ueMeasurementsList.end (); ++newMeasIt) - { - Layer3Filtering (newMeasIt->m_cellId, newMeasIt->m_rsrp, - newMeasIt->m_rsrq); - } - std::map::iterator measIdIt; for (measIdIt = m_varMeasConfig.measIdList.begin (); measIdIt != m_varMeasConfig.measIdList.end (); ++measIdIt) @@ -840,7 +828,46 @@ LteUeRrc::DoRecvRrcConnectionReject (LteRrcSap::RrcConnectionReject msg) void -LteUeRrc::InitialCellSelection () +LteUeRrc::SynchronizeToStrongestCell () +{ + uint16_t maxRsrpCellId = 0; + double maxRsrp = -std::numeric_limits::infinity (); + + std::map::iterator it; + for (it = m_storedMeasValues.begin (); it != m_storedMeasValues.end (); it++) + { + /* + * This block attempts to find a cell with strongest RSRP and has not + * yet been identified as "acceptable cell". + */ + if (maxRsrp < it->second.rsrp) + { + std::set::const_iterator itCell; + itCell = m_acceptableCell.find (it->first); + if (itCell == m_acceptableCell.end ()) + { + maxRsrpCellId = it->first; + maxRsrp = it->second.rsrp; + } + } + } + + if (maxRsrpCellId == 0) + { + NS_LOG_WARN (this << " Cell search is unable to detect surrounding cell to attach to"); + } + else + { + NS_LOG_LOGIC (this << " cell " << maxRsrpCellId + << " is the strongest untried surrounding cell"); + m_cphySapProvider->SyncronizeWithEnb (maxRsrpCellId, m_dlEarfcn); + } + +} // end of void LteUeRrc::SynchronizeToStrongestCell () + + +void +LteUeRrc::EvaluateCellForSelection () { NS_LOG_FUNCTION (this); NS_ASSERT (m_state == IDLE_CELL_SELECTION); @@ -848,7 +875,36 @@ LteUeRrc::InitialCellSelection () NS_ASSERT (m_hasReceivedSib1); uint16_t cellId = m_lastSib1.cellAccessRelatedInfo.cellIdentity; - bool isSuitableCell = true; // TODO evaluate cell selection criteria + // Cell selection criteria evaluation + + bool isSuitableCell = false; + bool isAcceptableCell = false; + std::map::iterator storedMeasIt = m_storedMeasValues.find (cellId); + double qRxLevMeas = storedMeasIt->second.rsrp; + double qRxLevMin = EutranMeasurementMapping::GetActualQRxLevMin (m_lastSib1.cellSelectionInfo.qRxLevMin); + NS_LOG_LOGIC (this << " cell selection to cellId=" << cellId + << " qrxlevmeas=" << qRxLevMeas << " dBm" + << " qrxlevmin=" << qRxLevMin << " dBm"); + + if (qRxLevMeas - qRxLevMin > 0) + { + isAcceptableCell = true; + + uint32_t cellPlmnId = m_lastSib1.cellAccessRelatedInfo.plmnIdentityInfo.plmnIdentity; + uint32_t cellCsgId = m_lastSib1.cellAccessRelatedInfo.csgIdentity; + bool cellCsgIndication = m_lastSib1.cellAccessRelatedInfo.csgIndication; + + bool isPlmnMatch = (cellPlmnId == m_selectedPlmn); + bool isCsgMatch = (cellCsgIndication == false) + || (cellCsgId == m_csgWhiteList); + isSuitableCell = (isPlmnMatch && isCsgMatch); + + NS_LOG_LOGIC (this << " plmn(ue/cell)=" << m_selectedPlmn << "/" << cellPlmnId + << " csg(ue/cell/indication)=" << m_csgWhiteList << "/" + << cellCsgId << "/" << cellCsgIndication); + } + + // Cell selection decision if (isSuitableCell) { @@ -868,15 +924,21 @@ LteUeRrc::InitialCellSelection () } else { - m_acceptableCell.insert (cellId); + // ignore the MIB and SIB1 received from this cell + m_hasReceivedMib = false; + m_hasReceivedSib1 = false; + m_initialCellSelectionEndErrorTrace (m_imsi, cellId); - /* - * As long as RRC state stays at IDLE_CELL_SELECTION, the cell selection - * process will repeat again after another call to DoReportUeMeasurements. - */ + + if (isAcceptableCell) + { + m_acceptableCell.insert (cellId); + } + + SynchronizeToStrongestCell (); // retry to a different cell } -} // end of void LteUeRrc::InitialCellSelection () +} // end of void LteUeRrc::EvaluateCellForSelection () void @@ -1310,14 +1372,32 @@ LteUeRrc::ApplyMeasConfig (LteRrcSap::MeasConfig mc) } void -LteUeRrc::Layer3Filtering (uint16_t cellId, double rsrp, double rsrq) +LteUeRrc::SaveUeMeasurements (uint16_t cellId, double rsrp, double rsrq, + bool useLayer3Filtering) { NS_LOG_LOGIC (this << " CellId " << cellId << " RSRP " << rsrp << " RSRQ " << rsrq); - std::map::iterator storedMeasIt = m_storedMeasValues.find (cellId); - if (storedMeasIt == m_storedMeasValues.end ()) + std::map::iterator storedMeasIt = m_storedMeasValues.find (cellId);; + + if (storedMeasIt != m_storedMeasValues.end ()) { - // first value is unfiltered + if (useLayer3Filtering) + { + // F_n = (1-a) F_{n-1} + a M_n + storedMeasIt->second.rsrp = (1 - m_varMeasConfig.aRsrp) * storedMeasIt->second.rsrp + + m_varMeasConfig.aRsrp * rsrp; + storedMeasIt->second.rsrq = (1 - m_varMeasConfig.aRsrq) * storedMeasIt->second.rsrq + + m_varMeasConfig.aRsrq * rsrq; + } + else + { + storedMeasIt->second.rsrp = rsrp; + storedMeasIt->second.rsrq = rsrq; + } + } + else + { + // first value is always unfiltered MeasValues v; v.rsrp = rsrp; v.rsrq = rsrq; @@ -1327,17 +1407,10 @@ LteUeRrc::Layer3Filtering (uint16_t cellId, double rsrp, double rsrq) NS_ASSERT_MSG (ret.second == true, "element already existed"); storedMeasIt = ret.first; } - else - { - // F_n = (1-a) F_{n-1} + a M_n - storedMeasIt->second.rsrp = (1 - m_varMeasConfig.aRsrp) * storedMeasIt->second.rsrp - + m_varMeasConfig.aRsrp * rsrp; - storedMeasIt->second.rsrq = (1 - m_varMeasConfig.aRsrq) * storedMeasIt->second.rsrq - + m_varMeasConfig.aRsrq * rsrq; - } storedMeasIt->second.timestamp = Simulator::Now (); -} + +} // end of void SaveUeMeasurements void LteUeRrc::MeasurementReportTriggering (uint8_t measId) @@ -2183,6 +2256,7 @@ LteUeRrc::CancelLeavingTrigger (uint8_t measId, uint16_t cellId) void LteUeRrc::VarMeasReportListAdd (uint8_t measId, ConcernedCells_t enteringCells) { + NS_LOG_FUNCTION (this << (uint16_t) measId); NS_ASSERT (!enteringCells.empty ()); std::map::iterator @@ -2264,6 +2338,7 @@ void LteUeRrc::VarMeasReportListErase (uint8_t measId, ConcernedCells_t leavingCells, bool reportOnLeave) { + NS_LOG_FUNCTION (this << (uint16_t) measId); NS_ASSERT (!leavingCells.empty ()); std::map::iterator diff --git a/src/lte/model/lte-ue-rrc.h b/src/lte/model/lte-ue-rrc.h index 9835ba8eb..3d24a6c64 100644 --- a/src/lte/model/lte-ue-rrc.h +++ b/src/lte/model/lte-ue-rrc.h @@ -241,8 +241,8 @@ public: */ void SetUlEarfcn (uint16_t earfcn); - /** - * + /** + * * \return the current state */ State GetState (); @@ -267,6 +267,8 @@ private: void DoNotifyRandomAccessFailed (); // LTE AS SAP methods + void DoSetSelectedPlmn (uint32_t plmnId); + void DoSetCsgWhiteList (uint32_t csgId); void DoForceCampedOnEnb (uint16_t cellId, uint16_t earfcn); void DoConnect (); void DoSendData (Ptr packet, uint8_t bid); @@ -291,7 +293,10 @@ private: // internal methods - void InitialCellSelection (); + void SaveUeMeasurements (uint16_t cellId, double rsrp, double rsrq, + bool useLayer3Filtering); + void SynchronizeToStrongestCell (); + void EvaluateCellForSelection (); void ApplyRadioResourceConfigDedicated (LteRrcSap::RadioResourceConfigDedicated rrcd); /// 3GPP TS 36.331 section 5.5.2 Measurement configuration void ApplyMeasConfig (LteRrcSap::MeasConfig mc); @@ -377,6 +382,9 @@ private: /// List of cell ID of acceptable cells for cell selection that have been detected. std::set m_acceptableCell; + uint32_t m_selectedPlmn; + uint32_t m_csgWhiteList; + /** * \brief Includes the accumulated configuration of the measurements to be * performed by the UE. diff --git a/src/lte/test/lte-test-cell-selection.cc b/src/lte/test/lte-test-cell-selection.cc index d6b367a72..78f1e6c53 100644 --- a/src/lte/test/lte-test-cell-selection.cc +++ b/src/lte/test/lte-test-cell-selection.cc @@ -38,8 +38,9 @@ #include #include -#include #include +#include +#include NS_LOG_COMPONENT_DEFINE ("LteCellSelectionTest"); @@ -54,7 +55,7 @@ namespace ns3 { LteCellSelectionTestSuite::LteCellSelectionTestSuite () : TestSuite ("lte-cell-selection", SYSTEM) { - //LogComponentEnableAll (LOG_PREFIX_ALL); + //LogComponentEnable ("LteCellSelectionTest", LOG_PREFIX_ALL); //LogComponentEnable ("LteCellSelectionTest", LOG_FUNCTION); //LogComponentEnable ("LteUePhy", LOG_INFO); //LogComponentEnable ("LteUePhy", LOG_WARN); @@ -64,32 +65,73 @@ LteCellSelectionTestSuite::LteCellSelectionTestSuite () //LogComponentEnable ("LteSpectrumPhy", LOG_LOGIC); //LogComponentEnable ("LteSpectrumPhy", LOG_FUNCTION); //LogComponentEnable ("LteEnbPhy", LOG_FUNCTION); - //LogComponentEnable ("LteUeRrc", LOG_FUNCTION); + //LogComponentEnable ("LteUeRrc", LOG_PREFIX_ALL); + //LogComponentEnable ("LteUeRrc", LOG_LOGIC); + //LogComponentEnable ("LteUeRrc", LOG_WARN); std::vector x; - x.clear (); // position x y z, plmn csg expectedCellId - x.push_back (LteCellSelectionTestCase::UeSetup_t (Vector (80, 10, 0), 0, 0, 1)); - AddTestCase (new LteCellSelectionTestCase ("[EPC] In front of cell 1", - true, x, MilliSeconds (261)), - TestCase::QUICK); - + /* + * <-- <-- + * ue1---CELL3 ue2---CELL4 ue3 + * / / + * / / + * / --> --> / + * ue4 CELL1---ue5 CELL2---ue6 + */ x.clear (); // position x y z, plmn csg expectedCellId - x.push_back (LteCellSelectionTestCase::UeSetup_t (Vector (-80, 20, 0), 0, 0, 2)); - AddTestCase (new LteCellSelectionTestCase ("[EPC] In front of cell 2", - true, x, MilliSeconds (261)), + x.push_back (LteCellSelectionTestCase::UeSetup_t (Vector (-80, 20, 0), 0, 0, 3)); + x.push_back (LteCellSelectionTestCase::UeSetup_t (Vector ( 80, 20, 0), 0, 0, 4)); + x.push_back (LteCellSelectionTestCase::UeSetup_t (Vector (240, 20, 0), 0, 0, 2)); + x.push_back (LteCellSelectionTestCase::UeSetup_t (Vector (-80, 10, 0), 0, 0, 3)); + x.push_back (LteCellSelectionTestCase::UeSetup_t (Vector ( 80, 10, 0), 0, 0, 1)); + x.push_back (LteCellSelectionTestCase::UeSetup_t (Vector (240, 10, 0), 0, 0, 2)); + AddTestCase (new LteCellSelectionTestCase ("[EPC] Open access", + true, false, false, x, + MilliSeconds (261)), TestCase::QUICK); + /* + * <-- <-- + * ue1---CELL3 ue2---CELL4 ue3 + * (1) (1) (1) / (0) /(1) + * /-------------/ / + * / --> / --> / + * ue4 CELL1 ue5 CELL2---ue6 + * (0) (1) (0) (0) (0) + */ x.clear (); // position x y z, plmn csg expectedCellId - x.push_back (LteCellSelectionTestCase::UeSetup_t (Vector (-80, 10, 0), 0, 0, 2)); - AddTestCase (new LteCellSelectionTestCase ("[EPC] Behind cell 1", - true, x, MilliSeconds (261)), + x.push_back (LteCellSelectionTestCase::UeSetup_t (Vector (-80, 20, 0), 0, 1, 3)); + x.push_back (LteCellSelectionTestCase::UeSetup_t (Vector ( 80, 20, 0), 0, 1, 4)); + x.push_back (LteCellSelectionTestCase::UeSetup_t (Vector (240, 20, 0), 0, 1, 2)); + x.push_back (LteCellSelectionTestCase::UeSetup_t (Vector (-80, 10, 0), 0, 0, 4)); + x.push_back (LteCellSelectionTestCase::UeSetup_t (Vector ( 80, 10, 0), 0, 0, 4)); + x.push_back (LteCellSelectionTestCase::UeSetup_t (Vector (240, 10, 0), 0, 0, 2)); + AddTestCase (new LteCellSelectionTestCase ("[EPC] Some CSG closed access 1", + true, false, true, x, + MilliSeconds (361)), TestCase::QUICK); - x.clear (); // position x y z, plmn csg expectedCellId - x.push_back (LteCellSelectionTestCase::UeSetup_t (Vector (80, 20, 0), 0, 0, 1)); - AddTestCase (new LteCellSelectionTestCase ("[EPC] Behind cell 2", - true, x, MilliSeconds (261)), + /* + * /-------------\ + * / <-- \ <-- + * ue1 CELL3 ue2---CELL4 ue3 + * (0) / (1) (0) (0) /(0) + * / / + * / --> --> / + * ue4 CELL1---ue5 CELL2---ue6 + * (1) (1) (1) (0) (1) + */ + x.clear (); // position x y z, plmn csg expectedCellId + x.push_back (LteCellSelectionTestCase::UeSetup_t (Vector (-80, 20, 0), 0, 0, 4)); + x.push_back (LteCellSelectionTestCase::UeSetup_t (Vector ( 80, 20, 0), 0, 0, 4)); + x.push_back (LteCellSelectionTestCase::UeSetup_t (Vector (240, 20, 0), 0, 0, 2)); + x.push_back (LteCellSelectionTestCase::UeSetup_t (Vector (-80, 10, 0), 0, 1, 3)); + x.push_back (LteCellSelectionTestCase::UeSetup_t (Vector ( 80, 10, 0), 0, 1, 1)); + x.push_back (LteCellSelectionTestCase::UeSetup_t (Vector (240, 10, 0), 0, 1, 2)); + AddTestCase (new LteCellSelectionTestCase ("[EPC] Some CSG closed access 2", + true, false, true, x, + MilliSeconds (361)), TestCase::QUICK); } // end of LteCellSelectionTestSuite::LteCellSelectionTestSuite () @@ -115,10 +157,12 @@ LteCellSelectionTestCase::UeSetup_t::UeSetup_t (Vector position, LteCellSelectionTestCase::LteCellSelectionTestCase ( - std::string name, bool isEpcMode, std::vector ueSetupList, - Time duration) - : TestCase (name), m_isEpcMode (isEpcMode), m_ueSetupList (ueSetupList), - m_duration (duration), m_lastState (LteUeRrc::NUM_STATES) + std::string name, bool isEpcMode, bool hasPlmnDiversity, bool hasCsgDiversity, + std::vector ueSetupList, Time duration) + : TestCase (name), m_isEpcMode (isEpcMode), + m_hasPlmnDiversity (hasPlmnDiversity), m_hasCsgDiversity (hasCsgDiversity), + m_ueSetupList (ueSetupList), m_duration (duration), + m_lastState (LteUeRrc::NUM_STATES) { NS_LOG_FUNCTION (this << GetName ()); } @@ -151,25 +195,29 @@ LteCellSelectionTestCase::DoRun () /* * The topology is the following: * - * <--x eNodeB 2 - Both cells are separated by 10 m - * | - Parabolic antenna model is used - * | 10 m - eNodeB 1 at (0, 10, 0) is facing east - * | - eNodeB 2 at (0, 20, 0) is facing west - * eNodeB 1 x--> - UEs are placed according to input - * - UEs do not move during simulation + * + <--x <--x - Parabolic antenna model is used + * | Cell3 Cell4 - eNodeB 1 at ( 0, 10, 0), facing east + * 10 m | - eNodeB 2 at (160, 10, 0), facing east + * | - eNodeB 3 at ( 0, 20, 0), facing west + * + x--> x--> - eNodeB 4 at (160, 20, 0), facing west + * Cell1 Cell2 - UEs are placed according to input + * - UEs do not move during simulation + * +------ 160 m ------+ */ // Create Nodes NodeContainer enbNodes; - enbNodes.Create (2); + enbNodes.Create (4); NodeContainer ueNodes; uint16_t nUe = m_ueSetupList.size (); ueNodes.Create (nUe); // Assign nodes to position Ptr positionAlloc = CreateObject (); - positionAlloc->Add (Vector (0.0, 10.0, 0.0)); - positionAlloc->Add (Vector (0.0, 20.0, 0.0)); + positionAlloc->Add (Vector ( 0.0, 10.0, 0.0)); + positionAlloc->Add (Vector (160.0, 10.0, 0.0)); + positionAlloc->Add (Vector ( 0.0, 20.0, 0.0)); + positionAlloc->Add (Vector (160.0, 20.0, 0.0)); std::vector::const_iterator itSetup; for (itSetup = m_ueSetupList.begin (); itSetup != m_ueSetupList.end (); itSetup++) @@ -190,17 +238,46 @@ LteCellSelectionTestCase::DoRun () NetDeviceContainer enbDevs; lteHelper->SetEnbAntennaModelAttribute ("Orientation", DoubleValue (0)); enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (0))); - lteHelper->SetEnbAntennaModelAttribute ("Orientation", DoubleValue (180)); enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (1))); + lteHelper->SetEnbAntennaModelAttribute ("Orientation", DoubleValue (180)); + enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (2))); + enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (3))); + + /* + * Diversity of PLMN and CSG within cells (if enabled) + * + * Cell PLMN ID CSG ID CSG indication + * ==== ======= ====== ============== + * 1 0 1 true + * 2 0 0 false + * 3 1 1 true + * 4 1 0 false + */ + + if (m_hasPlmnDiversity) + { + lteHelper->SetEnbPlmnId (enbDevs.Get (2), 1); + lteHelper->SetEnbPlmnId (enbDevs.Get (3), 1); + } + + if (m_hasCsgDiversity) + { + lteHelper->SetEnbCsgId (enbDevs.Get (0), 1, true); + lteHelper->SetEnbCsgId (enbDevs.Get (2), 1, true); + } NetDeviceContainer ueDevs; ueDevs = lteHelper->InstallUeDevice (ueNodes); // Set the PLMN and CSG ID + NS_ASSERT (m_ueSetupList.size () == ueDevs.GetN ()); NetDeviceContainer::Iterator itDev; - for (itSetup = m_ueSetupList.begin (); itSetup != m_ueSetupList.end (); itSetup++) + for (itSetup = m_ueSetupList.begin (), itDev = ueDevs.Begin (); + itSetup != m_ueSetupList.end () || itDev != ueDevs.End (); + itSetup++, itDev++) { - // TODO + lteHelper->SetUePlmnId (*itDev, itSetup->plmnIdentity); + lteHelper->SetUeCsgId (*itDev, itSetup->csgIdentity); } if (m_isEpcMode) @@ -286,7 +363,8 @@ LteCellSelectionTestCase::DoRun () uint16_t actualCellId = ueDev->GetRrc ()->GetCellId (); uint16_t expectedCellId = itSetup->expectedCellId; NS_TEST_ASSERT_MSG_EQ (actualCellId, expectedCellId, - "UE has attached to an unexpected cell"); + "IMSI " << ueDev->GetImsi () + << " has attached to an unexpected cell"); } NS_TEST_ASSERT_MSG_EQ (m_lastState, 5, "UE is not at CONNECTED_NORMALLY state"); diff --git a/src/lte/test/lte-test-cell-selection.h b/src/lte/test/lte-test-cell-selection.h index e8e27513e..1c4865886 100644 --- a/src/lte/test/lte-test-cell-selection.h +++ b/src/lte/test/lte-test-cell-selection.h @@ -74,6 +74,7 @@ public: * \param duration length of simulation */ LteCellSelectionTestCase (std::string name, bool isEpcMode, + bool hasPlmnDiversity, bool hasCsgDiversity, std::vector ueSetupList, Time duration); virtual ~LteCellSelectionTestCase (); @@ -104,6 +105,17 @@ private: */ bool m_isEpcMode; + /** + * \brief If true, then the north and south cells will be on their own PLMN. + */ + bool m_hasPlmnDiversity; + + /** + * \brief If true, then the west cells in the simulation will be CSG cell, + * while the east cells will be non-CSG cells. + */ + bool m_hasCsgDiversity; + /** * \brief The list of UE setups to be used during the test execution. */