From c5d79310d33f688eedd44eeb46e582a571dd49cf Mon Sep 17 00:00:00 2001 From: Budiarto Herman Date: Mon, 12 Aug 2013 11:25:23 +0300 Subject: [PATCH] LTE Automatic Neighbour Relation (ANR) function --- src/lte/helper/lte-helper.cc | 11 +- src/lte/model/a2-rsrq-handover-algorithm.cc | 9 +- src/lte/model/handover-management-sap.h | 8 +- src/lte/model/lte-anr-sap.cc | 38 ++++ src/lte/model/lte-anr-sap.h | 233 +++++++++++++++++++ src/lte/model/lte-anr.cc | 236 ++++++++++++++++++++ src/lte/model/lte-anr.h | 140 ++++++++++++ src/lte/model/lte-enb-net-device.cc | 6 + src/lte/model/lte-enb-net-device.h | 3 + src/lte/model/lte-enb-rrc.cc | 140 +++++------- src/lte/model/lte-enb-rrc.h | 52 +++-- src/lte/wscript | 4 + 12 files changed, 768 insertions(+), 112 deletions(-) create mode 100644 src/lte/model/lte-anr-sap.cc create mode 100644 src/lte/model/lte-anr-sap.h create mode 100644 src/lte/model/lte-anr.cc create mode 100644 src/lte/model/lte-anr.h diff --git a/src/lte/helper/lte-helper.cc b/src/lte/helper/lte-helper.cc index 5feacdde0..47ec926ea 100644 --- a/src/lte/helper/lte-helper.cc +++ b/src/lte/helper/lte-helper.cc @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -391,6 +392,7 @@ LteHelper::InstallSingleEnbDevice (Ptr n) Ptr mac = CreateObject (); Ptr sched = m_schedulerFactory.Create (); Ptr handoverAlgorithm = m_handoverAlgorithmFactory.Create (); + Ptr anr = CreateObject (); Ptr rrc = CreateObject (); if (m_useIdealRrc) @@ -428,6 +430,9 @@ LteHelper::InstallSingleEnbDevice (Ptr n) rrc->SetHandoverManagementSapProvider (handoverAlgorithm->GetHandoverManagementSapProvider ()); handoverAlgorithm->SetHandoverManagementSapUser (rrc->GetHandoverManagementSapUser ()); + rrc->SetLteAnrSapProvider (anr->GetLteAnrSapProvider ()); + anr->SetLteAnrSapUser (rrc->GetLteAnrSapUser ()); + mac->SetFfMacSchedSapProvider (sched->GetFfMacSchedSapProvider ()); mac->SetFfMacCschedSapProvider (sched->GetFfMacCschedSapProvider ()); @@ -437,7 +442,6 @@ LteHelper::InstallSingleEnbDevice (Ptr n) phy->SetLteEnbPhySapUser (mac->GetLteEnbPhySapUser ()); mac->SetLteEnbPhySapProvider (phy->GetLteEnbPhySapProvider ()); - phy->SetLteEnbCphySapUser (rrc->GetLteEnbCphySapUser ()); rrc->SetLteEnbCphySapProvider (phy->GetLteEnbCphySapProvider ()); @@ -449,6 +453,7 @@ LteHelper::InstallSingleEnbDevice (Ptr n) dev->SetAttribute ("FfMacScheduler", PointerValue (sched)); dev->SetAttribute ("LteEnbRrc", PointerValue (rrc)); dev->SetAttribute ("HandoverAlgorithm", PointerValue (handoverAlgorithm)); + dev->SetAttribute ("LteAnr", PointerValue (anr)); phy->SetDevice (dev); dlPhy->SetDevice (dev); @@ -858,7 +863,7 @@ LteHelper::DoHandoverRequest (Ptr ueDev, Ptr sourceEnbDev, uint16_t targetCellId = targetEnbDev->GetObject ()->GetCellId (); Ptr sourceRrc = sourceEnbDev->GetObject ()->GetRrc (); uint16_t rnti = ueDev->GetObject ()->GetRrc ()->GetRnti (); - sourceRrc->SendHandoverRequest (rnti, targetCellId); + sourceRrc->SendHandoverRequest (rnti, targetCellId); } @@ -869,7 +874,7 @@ void LteHelper::ActivateDataRadioBearer (NetDeviceContainer ueDevices, EpsBearer bearer) { NS_LOG_FUNCTION (this); - for (NetDeviceContainer::Iterator i = ueDevices.Begin (); i != ueDevices.End (); ++i) + for (NetDeviceContainer::Iterator i = ueDevices.Begin (); i != ueDevices.End (); ++i) { ActivateDataRadioBearer (*i, bearer); } diff --git a/src/lte/model/a2-rsrq-handover-algorithm.cc b/src/lte/model/a2-rsrq-handover-algorithm.cc index 1e0a9ef75..897697bab 100644 --- a/src/lte/model/a2-rsrq-handover-algorithm.cc +++ b/src/lte/model/a2-rsrq-handover-algorithm.cc @@ -101,10 +101,11 @@ A2RsrqHandoverAlgorithm::GetTypeId (void) .SetParent () .AddConstructor () .AddAttribute ("ServingCellThreshold", - "If serving cell is worse than this threshold, neighbour cells are consider for Handover", + "If the RSRQ of the serving cell is worse than this threshold, " + "neighbour cells are consider for handover", UintegerValue (30), MakeUintegerAccessor (&A2RsrqHandoverAlgorithm::m_servingCellThreshold), - MakeUintegerChecker ()) + MakeUintegerChecker (0, 34)) // RSRQ range is [0..34] as per Section 9.1.7 of 3GPP TS 36.133 .AddAttribute ("NeighbourCellOffset", "Minimum offset between serving and best neighbour cell to trigger the Handover", UintegerValue (1), @@ -142,7 +143,7 @@ A2RsrqHandoverAlgorithm::DoInitialize () reportConfigA2.threshold1.range = m_servingCellThreshold; reportConfigA2.triggerQuantity = LteRrcSap::ReportConfigEutra::RSRQ; reportConfigA2.reportInterval = LteRrcSap::ReportConfigEutra::MS240; - m_a2measId = m_handoverManagementSapUser->AddUeMeasReportConfig (reportConfigA2); + m_a2measId = m_handoverManagementSapUser->AddUeMeasReportConfigForHandover (reportConfigA2); LteRrcSap::ReportConfigEutra reportConfigA4; reportConfigA4.eventId = LteRrcSap::ReportConfigEutra::EVENT_A4; @@ -150,7 +151,7 @@ A2RsrqHandoverAlgorithm::DoInitialize () reportConfigA4.threshold1.range = 0; // intentionally very low threshold reportConfigA4.triggerQuantity = LteRrcSap::ReportConfigEutra::RSRQ; reportConfigA4.reportInterval = LteRrcSap::ReportConfigEutra::MS480; - m_a4measId = m_handoverManagementSapUser->AddUeMeasReportConfig (reportConfigA4); + m_a4measId = m_handoverManagementSapUser->AddUeMeasReportConfigForHandover (reportConfigA4); HandoverAlgorithm::DoInitialize (); } diff --git a/src/lte/model/handover-management-sap.h b/src/lte/model/handover-management-sap.h index e1c55d327..4487de5b1 100644 --- a/src/lte/model/handover-management-sap.h +++ b/src/lte/model/handover-management-sap.h @@ -42,8 +42,10 @@ public: * where the report originates from * \param measResults a single report of one measurement identity * - * The received measurement report may be stored and utilized for the purpose - * of making handover decision. + * The received measurement report is a result of the UE measurement + * configuration previously configured by calling + * HandoverManagementSapUser::AddUeMeasReportConfigForHandover. The report + * may be stored and utilized for the purpose of making handover decision. */ virtual void ReportUeMeas (uint16_t rnti, LteRrcSap::MeasResults measResults) = 0; @@ -76,7 +78,7 @@ public: * * This function is only valid before the simulation begins. */ - virtual uint8_t AddUeMeasReportConfig (LteRrcSap::ReportConfigEutra reportConfig) = 0; + virtual uint8_t AddUeMeasReportConfigForHandover (LteRrcSap::ReportConfigEutra reportConfig) = 0; /** * \brief Instruct the eNodeB RRC entity to prepare a handover. diff --git a/src/lte/model/lte-anr-sap.cc b/src/lte/model/lte-anr-sap.cc new file mode 100644 index 000000000..c50c83061 --- /dev/null +++ b/src/lte/model/lte-anr-sap.cc @@ -0,0 +1,38 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2013 University of Jyvaskyla + * + * 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: Budiarto Herman + * + */ + +#include "lte-anr-sap.h" + + +namespace ns3 { + + +LteAnrSapProvider::~LteAnrSapProvider () +{ +} + + +LteAnrSapUser::~LteAnrSapUser () +{ +} + + +} // end of namespace ns3 diff --git a/src/lte/model/lte-anr-sap.h b/src/lte/model/lte-anr-sap.h new file mode 100644 index 000000000..59d4bc8d8 --- /dev/null +++ b/src/lte/model/lte-anr-sap.h @@ -0,0 +1,233 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2013 University of Jyvaskyla + * + * 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: Budiarto Herman + * + */ + +#ifndef LTE_ANR_SAP_H +#define LTE_ANR_SAP_H + +#include + +namespace ns3 { + + +/** + * \brief Service Access Point (SAP) offered by the Automatic Neighbour Relation + * (ANR) function to the eNodeB RRC instance. + * + * This is the ANR SAP Provider, i.e., the part of the SAP that contains the ANR + * methods called by the eNodeB RRC. + */ +class LteAnrSapProvider +{ +public: + virtual ~LteAnrSapProvider (); + + /** + * \brief Send a UE measurement report to the ANC instance. + * \param measResults a single report of one measurement identity + * + * The received measurement report is a result of the UE measurement + * configuration previously configured by calling + * LteAnrSapUser::AddUeMeasReportConfigForAnr. The report may be stored and + * utilized for the purpose of maintaining Neighbour Relation Table (NRT). + */ + virtual void ReportUeMeas (LteRrcSap::MeasResults measResults) = 0; + + /** + * \brief Add a new Neighbour Relation entry. + * \param cellId the Physical Cell ID of the new neighbouring cell + */ + virtual void AddNeighbourRelation (uint16_t cellId) = 0; + + /** + * \brief Get the value of *No Remove* field of a neighbouring cell from the + * Neighbour Relation Table (NRT). + * \param cellId the Physical Cell ID of the neighbouring cell of interest + * \return if true, the Neighbour Relation shall *not* be removed from the NRT + */ + virtual bool GetNoRemove (uint16_t cellId) = 0; + + /** + * \brief Get the value of *No HO* field of a neighbouring cell from the + * Neighbour Relation Table (NRT). + * \param cellId the Physical Cell ID of the neighbouring cell of interest + * \return if true, the Neighbour Relation shall *not* be used by the eNodeB + * for handover reasons + */ + virtual bool GetNoHo (uint16_t cellId) = 0; + + /** + * \brief Get the value of *No X2* field of a neighbouring cell from the + * Neighbour Relation Table (NRT). + * \param cellId the Physical Cell ID of the neighbouring cell of interest + * \return if true, the Neighbour Relation shall *not* use an X2 interface in + * order to initiate procedures towards the eNodeB parenting the + * target cell + */ + virtual bool GetNoX2 (uint16_t cellId) = 0; + +}; // end of class LteAnrSapProvider + + + +/** + * \brief Service Access Point (SAP) offered by the eNodeB RRC instance to the + * Automatic Neighbour Relation (ANR) function. + * + * This is the ANR SAP User, i.e., the part of the SAP that contains the eNodeB + * RRC methods called by the ANR. + */ +class LteAnrSapUser +{ +public: + virtual ~LteAnrSapUser (); + + /** + * \brief Request a certain reporting configuration to be fulfilled by the UEs + * attached to the eNodeB entity. + * \param reportConfig the UE measurement reporting configuration + * \return the measurement identity associated with this newly added + * reporting configuration + * + * The eNodeB RRC entity is expected to configure the same reporting + * configuration in each of the attached UEs. When later in the simulation a + * UE measurement report is received from a UE as a result of this + * configuration, the eNodeB RRC entity shall forward this report to the ANC + * instance through the LteAnrSapProvider::ReportUeMeas SAP function. + * + * This function is only valid before the simulation begins. + */ + virtual uint8_t AddUeMeasReportConfigForAnr (LteRrcSap::ReportConfigEutra reportConfig) = 0; + +}; // end of class LteAnrSapUser + + + +/** + * \brief Template for the implementation of the LteAnrSapProvider as a member + * of an owner class of type C to which all methods are forwarded. + */ +template +class MemberLteAnrSapProvider : public LteAnrSapProvider +{ +public: + MemberLteAnrSapProvider (C* owner); + + // inherited from LteAnrSapProvider + virtual void ReportUeMeas (LteRrcSap::MeasResults measResults); + virtual void AddNeighbourRelation (uint16_t cellId); + virtual bool GetNoRemove (uint16_t cellId); + virtual bool GetNoHo (uint16_t cellId); + virtual bool GetNoX2 (uint16_t cellId); + +private: + MemberLteAnrSapProvider (); + C* m_owner; + +}; // end of class MemberLteAnrSapProvider + + +template +MemberLteAnrSapProvider::MemberLteAnrSapProvider (C* owner) + : m_owner (owner) +{ +} + + +template +void +MemberLteAnrSapProvider::ReportUeMeas (LteRrcSap::MeasResults measResults) +{ + m_owner->DoReportUeMeas (measResults); +} + + +template +void +MemberLteAnrSapProvider::AddNeighbourRelation (uint16_t cellId) +{ + m_owner->DoAddNeighbourRelation (cellId); +} + + +template +bool +MemberLteAnrSapProvider::GetNoRemove (uint16_t cellId) +{ + return m_owner->DoGetNoRemove (cellId); +} + + +template +bool +MemberLteAnrSapProvider::GetNoHo (uint16_t cellId) +{ + return m_owner->DoGetNoHo (cellId); +} + + +template +bool +MemberLteAnrSapProvider::GetNoX2 (uint16_t cellId) +{ + return m_owner->DoGetNoX2 (cellId); +} + + + +/** + * \brief Template for the implementation of the LteAnrSapUser as a member of an + * owner class of type C to which all methods are forwarded. + */ +template +class MemberLteAnrSapUser : public LteAnrSapUser +{ +public: + MemberLteAnrSapUser (C* owner); + + // inherited from LteAnrSapUser + virtual uint8_t AddUeMeasReportConfigForAnr (LteRrcSap::ReportConfigEutra reportConfig); + +private: + MemberLteAnrSapUser (); + C* m_owner; + +}; // end of class MemberLteAnrSapUser + + +template +MemberLteAnrSapUser::MemberLteAnrSapUser (C* owner) + : m_owner (owner) +{ +} + + +template +uint8_t +MemberLteAnrSapUser::AddUeMeasReportConfigForAnr (LteRrcSap::ReportConfigEutra reportConfig) +{ + return m_owner->DoAddUeMeasReportConfigForAnr (reportConfig); +} + + +} // end of namespace ns3 + + +#endif /* LTE_ANR_SAP_H */ diff --git a/src/lte/model/lte-anr.cc b/src/lte/model/lte-anr.cc new file mode 100644 index 000000000..d57de2a36 --- /dev/null +++ b/src/lte/model/lte-anr.cc @@ -0,0 +1,236 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2013 University of Jyvaskyla + * + * 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: Budiarto Herman + * + */ + +#include "lte-anr.h" +#include +#include + +NS_LOG_COMPONENT_DEFINE ("LteAnr"); + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (LteAnr); + + +LteAnr::LteAnr () + : m_anrSapUser (0), + m_threshold (0), + m_measId (0) +{ + m_anrSapProvider = new MemberLteAnrSapProvider (this); +} + + +LteAnr::~LteAnr () +{ +} + + +void +LteAnr::DoDispose () +{ + delete m_anrSapProvider; + m_neighbourRelationTable.clear (); +} + + +TypeId +LteAnr::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::LteAnr") + .SetParent () + .AddConstructor () + .AddAttribute ("Threshold", + "Minimum RSRQ range value required for detecting a neighbour cell", + UintegerValue (0), + MakeUintegerAccessor (&LteAnr::m_threshold), + MakeUintegerChecker (0, 34)) // RSRQ range is [0..34] as per Section 9.1.7 of 3GPP TS 36.133 + ; + return tid; +} + + +void +LteAnr::AddNeighbourRelation (uint16_t cellId) +{ + NS_LOG_FUNCTION (this << cellId); + + if (m_neighbourRelationTable.find (cellId) != m_neighbourRelationTable.end ()) + { + NS_FATAL_ERROR ("There is already an entry in the NRT for cell ID " << cellId); + } + + NeighbourRelation_t neighbourRelation; + neighbourRelation.noRemove = true; + neighbourRelation.noHo = true; + neighbourRelation.noX2 = false; + neighbourRelation.detectedAsNeighbour = false; + m_neighbourRelationTable[cellId] = neighbourRelation; +} + + +void +LteAnr::RemoveNeighbourRelation (uint16_t cellId) +{ + NS_LOG_FUNCTION (this << cellId); + + NeighbourRelationTable_t::iterator it = m_neighbourRelationTable.find (cellId); + if (it != m_neighbourRelationTable.end ()) + { + NS_FATAL_ERROR ("Cell ID " << cellId << " cannot be found in NRT"); + } + + m_neighbourRelationTable.erase (it); +} + + +void +LteAnr::SetLteAnrSapUser (LteAnrSapUser* s) +{ + m_anrSapUser = s; +} + + +LteAnrSapProvider* +LteAnr::GetLteAnrSapProvider () +{ + return m_anrSapProvider; +} + + +void +LteAnr::DoInitialize () +{ + LteRrcSap::ReportConfigEutra reportConfig; + reportConfig.eventId = LteRrcSap::ReportConfigEutra::EVENT_A4; + reportConfig.threshold1.choice = LteRrcSap::ThresholdEutra::THRESHOLD_RSRQ; + reportConfig.threshold1.range = m_threshold; + reportConfig.triggerQuantity = LteRrcSap::ReportConfigEutra::RSRQ; + reportConfig.reportInterval = LteRrcSap::ReportConfigEutra::MS480; + m_measId = m_anrSapUser->AddUeMeasReportConfigForAnr (reportConfig); +} + + +void +LteAnr::DoReportUeMeas (LteRrcSap::MeasResults measResults) +{ + uint8_t measId = measResults.measId; + NS_LOG_FUNCTION (this << (uint16_t) measId); + + if (measId != m_measId) + { + NS_LOG_WARN (this << " Skipping unexpected measurement identity " << (uint16_t) measId); + } + else + { + if (measResults.haveMeasResultNeighCells + && !(measResults.measResultListEutra.empty ())) + { + for (std::list ::iterator it = measResults.measResultListEutra.begin (); + it != measResults.measResultListEutra.end (); + ++it) + { + // Keep new RSRQ value reported for the neighbour cell + NS_ASSERT_MSG (it->haveRsrqResult == true, + "RSRQ measure missing for cellId " << it->physCellId); + + // Update Neighbour Relation Table + if (m_neighbourRelationTable.find (it->physCellId) != m_neighbourRelationTable.end ()) + { + // Update neighbour info + NeighbourRelation_t neighbourRelation = m_neighbourRelationTable[it->physCellId]; + + if (neighbourRelation.noX2 == false) + { + neighbourRelation.noHo = false; + } + neighbourRelation.detectedAsNeighbour = true; + } + else // new neighbour + { + NeighbourRelation_t neighbourRelation; + neighbourRelation.noRemove = false; + neighbourRelation.noHo = true; + neighbourRelation.noX2 = true; + neighbourRelation.detectedAsNeighbour = true; + m_neighbourRelationTable[it->physCellId] = neighbourRelation; + } + + } // end of for (it = measResults.measResultListEutra.begin ()) + + } // end of if (measResults.haveMeasResultNeighCells && !(measResults.measResultListEutra.empty ())) + else + { + NS_LOG_LOGIC ("WARNING"); + // NS_ASSERT_MSG ("Event A4 received without measure results for neighbour cells"); + // TODO Remove neighbours in the neighbourCellMeasures table + } + + } // end of else of if (measId != m_measId) + +} // end of DoReportUeMeas + + +void +LteAnr::DoAddNeighbourRelation (uint16_t cellId) +{ + AddNeighbourRelation (cellId); +} + + +bool +LteAnr::DoGetNoRemove (uint16_t cellId) +{ + NS_LOG_FUNCTION (this << cellId); + return Find (cellId)->noRemove; +} + + +bool +LteAnr::DoGetNoHo (uint16_t cellId) +{ + NS_LOG_FUNCTION (this << cellId); + return Find (cellId)->noHo; +} + + +bool +LteAnr::DoGetNoX2 (uint16_t cellId) +{ + NS_LOG_FUNCTION (this << cellId); + return Find (cellId)->noX2; +} + + +LteAnr::NeighbourRelation_t * +LteAnr::Find (uint16_t cellId) +{ + NeighbourRelationTable_t::iterator it = m_neighbourRelationTable.find (cellId); + if (it == m_neighbourRelationTable.end ()) + { + NS_FATAL_ERROR ("Cell ID " << cellId << " cannot be found in NRT"); + } + return &(it->second); +} + + +} // end of namespace ns3 + diff --git a/src/lte/model/lte-anr.h b/src/lte/model/lte-anr.h new file mode 100644 index 000000000..193e8059a --- /dev/null +++ b/src/lte/model/lte-anr.h @@ -0,0 +1,140 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2013 University of Jyvaskyla + * + * 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: Budiarto Herman + * + */ + +#ifndef LTE_ANR_H +#define LTE_ANR_H + +#include +#include +#include +#include + +namespace ns3 { + + +class LteAnrSapProvider; +class LteAnrSapUser; +class LteNeighbourRelation; + +/** + * \brief Automatic Neighbour Relation function. + * + * Based on Section 22.3.2a and 22.3.3 of 3GPP TS 36.300. + */ +class LteAnr : public Object +{ +public: + LteAnr (); + virtual ~LteAnr (); + + // inherited from Object + virtual void DoDispose (void); + static TypeId GetTypeId (void); + + /** + * \brief Provide an advance information about a related neighbouring cell + * and add it as a new Neighbour Relation entry. + * + * This function simulates the Neighbour Relation addition operation by + * network operations and maintenance, as depicted in Section 22.3.2a of + * 3GPP TS 36.300. + * + * An entry added by this function will have NoRemove flag set to TRUE and + * NoHo flag set to TRUE. Hence, the cell may not act as the targel cell of a + * handover, unless a measurement report of the cell is received, which will + * update the NoHo flag to FALSE. + */ + void AddNeighbourRelation (uint16_t cellId); + + /** + * \brief Remove an existing Neighbour Relation entry. + * + * This function simulates the Neighbour Relation removal operation by + * network operations and maintenance, as depicted in Section 22.3.2a of + * 3GPP TS 36.300. + */ + void RemoveNeighbourRelation (uint16_t cellId); + + /** + * \brief Set the user part of the LteAnrSap that this ANR instance will + * interact with. Normally this part of the SAP is exported by the + * eNodeB RRC. + * \param s + */ + virtual void SetLteAnrSapUser (LteAnrSapUser* s); + + /** + * + * \return the Provider part of the LteAnrSap provided by the ANR instance + */ + virtual LteAnrSapProvider* GetLteAnrSapProvider (); + + friend class MemberLteAnrSapProvider; + +protected: + // inherited from Object + virtual void DoInitialize (); + +private: + // ANR SAP provider implementation + void DoReportUeMeas (LteRrcSap::MeasResults measResults); + void DoAddNeighbourRelation (uint16_t cellId); + bool DoGetNoRemove (uint16_t cellId); + bool DoGetNoHo (uint16_t cellId); + bool DoGetNoX2 (uint16_t cellId); + + // ANR SAPs + LteAnrSapUser* m_anrSapUser; + LteAnrSapProvider* m_anrSapProvider; + + // Class Attributes + uint8_t m_threshold; + + /** + * \brief Neighbour Relation between two eNodeBs (serving eNodeB and neighbour + * eNodeB). + */ + struct NeighbourRelation_t + { + bool noRemove; + bool noHo; + bool noX2; + bool detectedAsNeighbour; + }; + + // cellId + typedef std::map NeighbourRelationTable_t; + + NeighbourRelationTable_t m_neighbourRelationTable; + + // internal methods + NeighbourRelation_t* Find (uint16_t cellId); + + // The expected measurement identity + uint8_t m_measId; + +}; // end of class LteAnr + + +} // end of namespace ns3 + + +#endif /* LTE_ANR_H */ diff --git a/src/lte/model/lte-enb-net-device.cc b/src/lte/model/lte-enb-net-device.cc index d94d8460e..3bd7881a9 100644 --- a/src/lte/model/lte-enb-net-device.cc +++ b/src/lte/model/lte-enb-net-device.cc @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -66,6 +67,11 @@ TypeId LteEnbNetDevice::GetTypeId (void) PointerValue (), MakePointerAccessor (&LteEnbNetDevice::m_handoverAlgorithm), MakePointerChecker ()) + .AddAttribute ("LteAnr", + "The automatic neighbour relation function associated to this EnbNetDevice", + PointerValue (), + MakePointerAccessor (&LteEnbNetDevice::m_anr), + MakePointerChecker ()) .AddAttribute ("LteEnbMac", "The MAC associated to this EnbNetDevice", PointerValue (), diff --git a/src/lte/model/lte-enb-net-device.h b/src/lte/model/lte-enb-net-device.h index edb4b33e0..792d34489 100644 --- a/src/lte/model/lte-enb-net-device.h +++ b/src/lte/model/lte-enb-net-device.h @@ -41,6 +41,7 @@ class LteEnbMac; class LteEnbRrc; class FfMacScheduler; class HandoverAlgorithm; +class LteAnr; /** @@ -149,6 +150,8 @@ private: Ptr m_handoverAlgorithm; + Ptr m_anr; + uint16_t m_cellId; /**< Cell Identifer. Part of the CGI, see TS 29.274, section 8.21.1 */ uint8_t m_dlBandwidth; /**< downlink bandwidth in RBs */ diff --git a/src/lte/model/lte-enb-rrc.cc b/src/lte/model/lte-enb-rrc.cc index 14611b11d..183f293ed 100644 --- a/src/lte/model/lte-enb-rrc.cc +++ b/src/lte/model/lte-enb-rrc.cc @@ -113,7 +113,7 @@ public: EnbRrcMemberHandoverManagementSapUser (LteEnbRrc* rrc); // methods inherited from HandoverManagementSapUser go here - virtual uint8_t AddUeMeasReportConfig (LteRrcSap::ReportConfigEutra reportConfig); + virtual uint8_t AddUeMeasReportConfigForHandover (LteRrcSap::ReportConfigEutra reportConfig); virtual void TriggerHandover (uint16_t rnti, uint16_t targetCellId); private: @@ -126,9 +126,9 @@ EnbRrcMemberHandoverManagementSapUser::EnbRrcMemberHandoverManagementSapUser (Lt } uint8_t -EnbRrcMemberHandoverManagementSapUser::AddUeMeasReportConfig (LteRrcSap::ReportConfigEutra reportConfig) +EnbRrcMemberHandoverManagementSapUser::AddUeMeasReportConfigForHandover (LteRrcSap::ReportConfigEutra reportConfig) { - return m_rrc->DoAddUeMeasReportConfig (reportConfig); + return m_rrc->DoAddUeMeasReportConfigForHandover (reportConfig); } void @@ -140,6 +140,11 @@ EnbRrcMemberHandoverManagementSapUser::TriggerHandover (uint16_t rnti, +/////////////////////////////////////////// +// UeManager +/////////////////////////////////////////// + + const char* g_ueManagerStateName[UeManager::NUM_STATES] = { "INITIAL_RANDOM_ACCESS", @@ -160,12 +165,6 @@ std::string ToString (UeManager::State s) } - -/////////////////////////////////////////// -// UeManager -/////////////////////////////////////////// - - NS_OBJECT_ENSURE_REGISTERED (UeManager); @@ -971,8 +970,9 @@ UeManager::RecvRrcConnectionReestablishmentComplete (LteRrcSap::RrcConnectionRee void UeManager::RecvMeasurementReport (LteRrcSap::MeasurementReport msg) { - NS_LOG_FUNCTION (this); - NS_LOG_LOGIC ("measId " << (uint16_t) msg.measResults.measId + uint8_t measId = msg.measResults.measId; + NS_LOG_FUNCTION (this << (uint16_t) measId); + NS_LOG_LOGIC ("measId " << (uint16_t) measId << " haveMeasResultNeighCells " << msg.measResults.haveMeasResultNeighCells << " measResultListEutra " << msg.measResults.measResultListEutra.size ()); NS_LOG_LOGIC ("serving cellId " << m_rrc->m_cellId @@ -988,57 +988,18 @@ UeManager::RecvMeasurementReport (LteRrcSap::MeasurementReport msg) << " RSRQ " << (it->haveRsrqResult ? (uint16_t) it->rsrqResult : 255)); } - /// Event A4 (Neighbour becomes better than threshold) - if (msg.measResults.measId == 2) // TODO remove this hardcode + if (m_rrc->m_handoverMeasIds.find (measId) != m_rrc->m_handoverMeasIds.end ()) { - // Update the NRT - if (msg.measResults.haveMeasResultNeighCells - && !(msg.measResults.measResultListEutra.empty ())) - { - for (std::list ::iterator it = msg.measResults.measResultListEutra.begin (); - it != msg.measResults.measResultListEutra.end (); - ++it) - { - // Keep new RSRQ value reported for the neighbour cell - NS_ASSERT_MSG (it->haveRsrqResult == true, "RSRQ measure missing for cellId " << it->physCellId); - - // Update Neighbour Relation Table - if (m_rrc->m_neighbourRelationTable.find (it->physCellId) != m_rrc->m_neighbourRelationTable.end ()) - { - // Update neighbour info - Ptr neighbourRelation = m_rrc->m_neighbourRelationTable[it->physCellId]; - NS_ASSERT_MSG (neighbourRelation->m_physCellId == it->physCellId, - "Wrong cellId " << neighbourRelation->m_physCellId); - - if (neighbourRelation->m_noX2 == false) - { - neighbourRelation->m_noHo = false; - } - neighbourRelation->m_detectedAsNeighbour = true; - } - else // new neighbour - { - Ptr neighbourRelation = CreateObject (); - neighbourRelation->m_physCellId = it->physCellId; - neighbourRelation->m_noRemove = false; - neighbourRelation->m_noHo = true; - neighbourRelation->m_noX2 = true; - neighbourRelation->m_detectedAsNeighbour = true; - m_rrc->m_neighbourRelationTable[it->physCellId] = neighbourRelation; - } - } - } - else - { - NS_LOG_LOGIC ("WARNING"); - // NS_ASSERT_MSG ("Event A4 received without measure results for neighbour cells"); - // TODO Remove neighbours in the neighbourCellMeasures table - } + // this measurement was requested by the handover algorithm + m_rrc->m_handoverManagementSapProvider->ReportUeMeas (m_rnti, + msg.measResults); } - // forward the UE measurements report to the active handover algorithm - m_rrc->m_handoverManagementSapProvider->ReportUeMeas (m_rnti, - msg.measResults); + if (m_rrc->m_anrMeasIds.find (measId) != m_rrc->m_anrMeasIds.end ()) + { + // this measurement was requested by the ANR function + m_rrc->m_anrSapProvider->ReportUeMeas (msg.measResults); + } // fire a trace source m_rrc->m_recvMeasurementReportTrace (m_imsi, m_rrc->m_cellId, m_rnti, msg); @@ -1312,6 +1273,7 @@ LteEnbRrc::LteEnbRrc () : m_x2SapProvider (0), m_cmacSapProvider (0), m_handoverManagementSapProvider (0), + m_anrSapProvider (0), m_rrcSapUser (0), m_macSapProvider (0), m_s1SapProvider (0), @@ -1325,6 +1287,7 @@ LteEnbRrc::LteEnbRrc () NS_LOG_FUNCTION (this); m_cmacSapUser = new EnbRrcMemberLteEnbCmacSapUser (this); m_handoverManagementSapUser = new EnbRrcMemberHandoverManagementSapUser (this); + m_anrSapUser = new MemberLteAnrSapUser (this); m_rrcSapProvider = new MemberLteEnbRrcSapProvider (this); m_x2SapUser = new EpcX2SpecificEpcX2SapUser (this); m_s1SapUser = new MemberEpcEnbS1SapUser (this); @@ -1345,6 +1308,7 @@ LteEnbRrc::DoDispose () m_ueMap.clear (); delete m_cmacSapUser; delete m_handoverManagementSapUser; + delete m_anrSapUser; delete m_rrcSapProvider; delete m_x2SapUser; delete m_s1SapUser; @@ -1506,6 +1470,20 @@ LteEnbRrc::GetHandoverManagementSapUser () return m_handoverManagementSapUser; } +void +LteEnbRrc::SetLteAnrSapProvider (LteAnrSapProvider * s) +{ + NS_LOG_FUNCTION (this << s); + m_anrSapProvider = s; +} + +LteAnrSapUser* +LteEnbRrc::GetLteAnrSapUser () +{ + NS_LOG_FUNCTION (this); + return m_anrSapUser; +} + void LteEnbRrc::SetLteEnbRrcSapUser (LteEnbRrcSapUser * s) { @@ -2033,10 +2011,12 @@ LteEnbRrc::DoNotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success) uint8_t -LteEnbRrc::DoAddUeMeasReportConfig (LteRrcSap::ReportConfigEutra reportConfig) +LteEnbRrc::DoAddUeMeasReportConfigForHandover (LteRrcSap::ReportConfigEutra reportConfig) { NS_LOG_FUNCTION (this); - return AddUeMeasReportConfig (reportConfig); + uint8_t measId = AddUeMeasReportConfig (reportConfig); + m_handoverMeasIds.insert (measId); + return measId; } void @@ -2044,18 +2024,23 @@ LteEnbRrc::DoTriggerHandover (uint16_t rnti, uint16_t targetCellId) { NS_LOG_FUNCTION (this << rnti << targetCellId); - std::map >::iterator it; - it = m_neighbourRelationTable.find (targetCellId); - NS_ASSERT_MSG (it != m_neighbourRelationTable.end (), - "Unable to find neighbouring cell with cell ID " << targetCellId); - // ensure that proper neighbour relationship exists between source and target cells - if ((it->second->m_noHo == false) && (it->second->m_noX2 == false)) - { + if ((m_anrSapProvider->GetNoHo (targetCellId) == false) + && (m_anrSapProvider->GetNoX2 (targetCellId) == false)) + { Ptr ueManager = GetUeManager (rnti); NS_ASSERT_MSG (ueManager != 0, "Cannot find UE context with RNTI " << rnti); ueManager->PrepareHandover (targetCellId); - } + } +} + +uint8_t +LteEnbRrc::DoAddUeMeasReportConfigForAnr (LteRrcSap::ReportConfigEutra reportConfig) +{ + NS_LOG_FUNCTION (this); + uint8_t measId = AddUeMeasReportConfig (reportConfig); + m_anrMeasIds.insert (measId); + return measId; } @@ -2073,7 +2058,7 @@ LteEnbRrc::AddUe (UeManager::State state) if ((rnti != 0) && (m_ueMap.find (rnti) == m_ueMap.end ())) { found = true; - break; + break; } } @@ -2103,7 +2088,7 @@ LteEnbRrc::RemoveUe (uint16_t rnti) } // need to do this after UeManager has been deleted RemoveSrsConfigurationIndex (srsCi); - } +} TypeId LteEnbRrc::GetRlcType (EpsBearer bearer) @@ -2143,17 +2128,8 @@ LteEnbRrc::GetRlcType (EpsBearer bearer) void LteEnbRrc::AddX2Neighbour (uint16_t cellId) { - NS_LOG_FUNCTION (cellId); - NS_ASSERT_MSG (m_neighbourRelationTable.find (cellId) == m_neighbourRelationTable.end (), - "There is already an entry in the Neighbour Relation Table for cellId " << cellId); - - Ptr neighbourRelation = CreateObject (); - neighbourRelation->m_physCellId = cellId; - neighbourRelation->m_noRemove = true; - neighbourRelation->m_noHo = true; - neighbourRelation->m_noX2 = false; - neighbourRelation->m_detectedAsNeighbour = false; - m_neighbourRelationTable[cellId] = neighbourRelation; + NS_LOG_FUNCTION (this << cellId); + m_anrSapProvider->AddNeighbourRelation (cellId); } LteRrcSap::SystemInformationBlockType1 diff --git a/src/lte/model/lte-enb-rrc.h b/src/lte/model/lte-enb-rrc.h index e9ee0f538..3fc9aca8f 100644 --- a/src/lte/model/lte-enb-rrc.h +++ b/src/lte/model/lte-enb-rrc.h @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -51,19 +52,6 @@ class LteUeRrc; class LteEnbRrc; -/** - * Neighbour Relation between two eNBs (serving eNB and neighbour eNB) - * See XXXXX for more info - */ -class NeighbourRelation : public Object -{ -public: - uint16_t m_physCellId; - bool m_noRemove; - bool m_noHo; - bool m_noX2; - bool m_detectedAsNeighbour; -}; /** * Measurements reported by a UE for a cellId @@ -440,6 +428,8 @@ private: class HandoverManagementSapProvider; class HandoverManagementSapUser; +class LteAnrSapProvider; +class LteAnrSapUser; /** @@ -452,6 +442,7 @@ class LteEnbRrc : public Object friend class EnbRrcMemberLteEnbCmacSapUser; friend class EnbRrcMemberHandoverManagementSapUser; + friend class MemberLteAnrSapUser; friend class MemberLteEnbRrcSapProvider; friend class MemberEpcEnbS1SapUser; friend class EpcX2SpecificEpcX2SapUser; @@ -519,6 +510,21 @@ public: HandoverManagementSapUser* GetHandoverManagementSapUser (); + /** + * set the ANR SAP this RRC should interact with + * + * \param s the ANR SAP Provider to be used by this RRC + */ + void SetLteAnrSapProvider (LteAnrSapProvider * s); + + /** + * Get the ANR SAP offered by this RRC + * \return s the ANR SAP User interface offered to the ANR instance by this + * RRC + */ + LteAnrSapUser* GetLteAnrSapUser (); + + /** * set the RRC SAP this RRC should interact with * @@ -705,7 +711,7 @@ private: // RRC SAP methods - + void DoCompleteSetupUe (uint16_t rnti, LteEnbRrcSapProvider::CompleteSetupUeParameters params); void DoRecvRrcConnectionRequest (uint16_t rnti, LteRrcSap::RrcConnectionRequest msg); void DoRecvRrcConnectionSetupCompleted (uint16_t rnti, LteRrcSap::RrcConnectionSetupCompleted msg); @@ -735,12 +741,16 @@ private: uint16_t DoAllocateTemporaryCellRnti (); void DoNotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success); void DoRrcConfigurationUpdateInd (LteEnbCmacSapUser::UeConfig params); - + // Handover Management SAP methods - uint8_t DoAddUeMeasReportConfig (LteRrcSap::ReportConfigEutra reportConfig); + uint8_t DoAddUeMeasReportConfigForHandover (LteRrcSap::ReportConfigEutra reportConfig); void DoTriggerHandover (uint16_t rnti, uint16_t targetCellId); + // ANR SAP methods + + uint8_t DoAddUeMeasReportConfigForAnr (LteRrcSap::ReportConfigEutra reportConfig); + // Internal methods @@ -867,6 +877,9 @@ private: HandoverManagementSapUser* m_handoverManagementSapUser; HandoverManagementSapProvider* m_handoverManagementSapProvider; + LteAnrSapUser* m_anrSapUser; + LteAnrSapProvider* m_anrSapProvider; + LteEnbRrcSapUser* m_rrcSapUser; LteEnbRrcSapProvider* m_rrcSapProvider; @@ -897,6 +910,9 @@ private: */ LteRrcSap::MeasConfig m_ueMeasConfig; + std::set m_handoverMeasIds; + std::set m_anrMeasIds; + struct X2uTeidInfo { uint16_t rnti; @@ -932,10 +948,6 @@ private: Time m_handoverJoiningTimeoutDuration; Time m_handoverLeavingTimeoutDuration; - // cellid - std::map > m_neighbourRelationTable; - - // cellid rnti TracedCallback m_newUeContextTrace; // imsi cellid rnti diff --git a/src/lte/wscript b/src/lte/wscript index 20adcb370..220d31b5d 100644 --- a/src/lte/wscript +++ b/src/lte/wscript @@ -101,6 +101,8 @@ def build(bld): 'model/handover-management-sap.cc', 'model/handover-algorithm.cc', 'model/a2-rsrq-handover-algorithm.cc', + 'model/lte-anr-sap.cc', + 'model/lte-anr.cc', ] module_test = bld.create_ns3_module_test_library('lte') @@ -249,6 +251,8 @@ def build(bld): 'model/handover-management-sap.h', 'model/handover-algorithm.h', 'model/a2-rsrq-handover-algorithm.h', + 'model/lte-anr-sap.h', + 'model/lte-anr.h', ] if (bld.env['ENABLE_EXAMPLES']):