14#include "nr-a2-a4-rsrq-handover-algorithm.h"
17#include "ns3/uinteger.h"
24NS_LOG_COMPONENT_DEFINE(
"NrA2A4RsrqHandoverAlgorithm");
26NS_OBJECT_ENSURE_REGISTERED(NrA2A4RsrqHandoverAlgorithm);
33 : m_servingCellThreshold(30),
34 m_neighbourCellOffset(1),
35 m_handoverManagementSapUser(nullptr)
37 NS_LOG_FUNCTION(
this);
38 m_handoverManagementSapProvider =
42NrA2A4RsrqHandoverAlgorithm::~NrA2A4RsrqHandoverAlgorithm()
44 NS_LOG_FUNCTION(
this);
51 TypeId(
"ns3::NrA2A4RsrqHandoverAlgorithm")
56 "ServingCellThreshold",
57 "If the RSRQ of the serving cell is worse than this "
58 "threshold, neighbour cells are consider for handover. "
59 "Expressed in quantized range of [0..34] as per Section "
60 "9.1.7 of 3GPP TS 36.133.",
62 MakeUintegerAccessor(&NrA2A4RsrqHandoverAlgorithm::m_servingCellThreshold),
63 MakeUintegerChecker<uint8_t>(0, 34))
64 .AddAttribute(
"NeighbourCellOffset",
65 "Minimum offset between the serving and the best neighbour "
66 "cell to trigger the handover. Expressed in quantized "
67 "range of [0..34] as per Section 9.1.7 of 3GPP TS 36.133.",
69 MakeUintegerAccessor(&NrA2A4RsrqHandoverAlgorithm::m_neighbourCellOffset),
70 MakeUintegerChecker<uint8_t>());
77 NS_LOG_FUNCTION(
this << s);
78 m_handoverManagementSapUser = s;
84 NS_LOG_FUNCTION(
this);
85 return m_handoverManagementSapProvider;
89NrA2A4RsrqHandoverAlgorithm::DoInitialize()
91 NS_LOG_FUNCTION(
this);
93 NS_LOG_LOGIC(
this <<
" requesting Event A2 measurements"
94 <<
" (threshold=" << (uint16_t)m_servingCellThreshold <<
")");
100 reportConfigA2.
reportInterval = NrRrcSap::ReportConfigEutra::MS240;
103 NS_LOG_LOGIC(
this <<
" requesting Event A4 measurements"
104 <<
" (threshold=0)");
110 reportConfigA4.
reportInterval = NrRrcSap::ReportConfigEutra::MS480;
113 NrHandoverAlgorithm::DoInitialize();
117NrA2A4RsrqHandoverAlgorithm::DoDispose()
119 NS_LOG_FUNCTION(
this);
120 delete m_handoverManagementSapProvider;
126 NS_LOG_FUNCTION(
this << rnti << (uint16_t)measResults.
measId);
128 if (std::find(begin(m_a2MeasIds), end(m_a2MeasIds), measResults.
measId) !=
129 std::end(m_a2MeasIds))
132 "Invalid UE measurement report");
135 else if (std::find(begin(m_a4MeasIds), end(m_a4MeasIds), measResults.
measId) !=
136 std::end(m_a4MeasIds))
144 NS_ASSERT_MSG(it->haveRsrqResult ==
true,
145 "RSRQ measurement is missing from cellId " << it->physCellId);
146 UpdateNeighbourMeasurements(rnti, it->physCellId, it->rsrqResult);
152 this <<
" Event A4 received without measurement results from neighbouring cells");
157 NS_LOG_WARN(
"Ignoring measId " << (uint16_t)measResults.
measId);
163NrA2A4RsrqHandoverAlgorithm::EvaluateHandover(uint16_t rnti, uint8_t servingCellRsrq)
165 NS_LOG_FUNCTION(
this << rnti << (uint16_t)servingCellRsrq);
167 auto it1 = m_neighbourCellMeasures.find(rnti);
169 if (it1 == m_neighbourCellMeasures.end())
171 NS_LOG_WARN(
"Skipping handover evaluation for RNTI "
172 << rnti <<
" because neighbour cells information is not found");
177 NS_LOG_LOGIC(
"Number of neighbour cells = " << it1->second.size());
178 uint16_t bestNeighbourCellId = 0;
179 uint8_t bestNeighbourRsrq = 0;
180 for (
auto it2 = it1->second.begin(); it2 != it1->second.end(); ++it2)
182 if ((it2->second->m_rsrq > bestNeighbourRsrq) && IsValidNeighbour(it2->first))
184 bestNeighbourCellId = it2->first;
185 bestNeighbourRsrq = it2->second->m_rsrq;
190 if (bestNeighbourCellId > 0)
192 NS_LOG_LOGIC(
"Best neighbour cellId " << bestNeighbourCellId);
194 if ((bestNeighbourRsrq - servingCellRsrq) >= m_neighbourCellOffset)
196 NS_LOG_LOGIC(
"Trigger Handover to cellId " << bestNeighbourCellId);
197 NS_LOG_LOGIC(
"target cell RSRQ " << (uint16_t)bestNeighbourRsrq);
198 NS_LOG_LOGIC(
"serving cell RSRQ " << (uint16_t)servingCellRsrq);
201 m_handoverManagementSapUser->
TriggerHandover(rnti, bestNeighbourCellId);
210NrA2A4RsrqHandoverAlgorithm::IsValidNeighbour(uint16_t cellId)
212 NS_LOG_FUNCTION(
this << cellId);
224NrA2A4RsrqHandoverAlgorithm::UpdateNeighbourMeasurements(uint16_t rnti,
228 NS_LOG_FUNCTION(
this << rnti << cellId << (uint16_t)rsrq);
229 auto it1 = m_neighbourCellMeasures.find(rnti);
231 if (it1 == m_neighbourCellMeasures.end())
234 MeasurementRow_t row;
235 auto ret = m_neighbourCellMeasures.insert(std::pair<uint16_t, MeasurementRow_t>(rnti, row));
236 NS_ASSERT(ret.second);
240 NS_ASSERT(it1 != m_neighbourCellMeasures.end());
241 Ptr<UeMeasure> neighbourCellMeasures;
242 auto it2 = it1->second.find(cellId);
244 if (it2 != it1->second.end())
246 neighbourCellMeasures = it2->second;
247 neighbourCellMeasures->m_cellId = cellId;
248 neighbourCellMeasures->m_rsrp = 0;
249 neighbourCellMeasures->m_rsrq = rsrq;
254 neighbourCellMeasures = Create<UeMeasure>();
255 neighbourCellMeasures->m_cellId = cellId;
256 neighbourCellMeasures->m_rsrp = 0;
257 neighbourCellMeasures->m_rsrq = rsrq;
258 it1->second[cellId] = neighbourCellMeasures;
Handover algorithm implementation based on RSRQ measurements, Event A2 and Event A4.
friend class MemberNrHandoverManagementSapProvider< NrA2A4RsrqHandoverAlgorithm >
let the forwarder class access the protected and private members
void SetNrHandoverManagementSapUser(NrHandoverManagementSapUser *s) override
Set the "user" part of the Handover Management SAP interface that this handover algorithm instance wi...
static TypeId GetTypeId()
Get the type ID.
NrHandoverManagementSapProvider * GetNrHandoverManagementSapProvider() override
Export the "provider" part of the Handover Management SAP interface.
NrA2A4RsrqHandoverAlgorithm()
Creates an A2-A4-RSRQ handover algorithm instance.
void DoReportUeMeas(uint16_t rnti, NrRrcSap::MeasResults measResults) override
Implementation of NrHandoverManagementSapProvider::ReportUeMeas.
The abstract base class of a handover algorithm that operates using the Handover Management SAP inter...
Service Access Point (SAP) offered by the handover algorithm instance to the eNodeB RRC instance.
Service Access Point (SAP) offered by the eNodeB RRC instance to the handover algorithm instance.
virtual void TriggerHandover(uint16_t rnti, uint16_t targetCellId)=0
Instruct the eNodeB RRC entity to prepare a handover.
virtual std::vector< uint8_t > AddUeMeasReportConfigForHandover(NrRrcSap::ReportConfigEutra reportConfig)=0
Request a certain reporting configuration to be fulfilled by the UEs attached to the eNodeB entity.
uint8_t rsrqResult
the RSRQ result
bool haveMeasResultNeighCells
have measure result neighbor cells
MeasResultPCell measResultPCell
measurement result primary cell
std::list< MeasResultEutra > measResultListEutra
measure result list eutra
Specifies criteria for triggering of an E-UTRA measurement reporting event.
enum ns3::NrRrcSap::ReportConfigEutra::@5 triggerQuantity
Trigger type enumeration.
@ RSRQ
Reference Signal Received Quality.
enum ns3::NrRrcSap::ReportConfigEutra::@7 reportInterval
Report interval enumeration.
@ EVENT_A2
Event A2: Serving becomes worse than absolute threshold.
@ EVENT_A4
Event A4: Neighbour becomes better than absolute threshold.
enum ns3::NrRrcSap::ReportConfigEutra::@4 eventId
Event enumeration.
ThresholdEutra threshold1
Threshold for event A1, A2, A4, and A5.
enum ns3::NrRrcSap::ThresholdEutra::@2 choice
Threshold enumeration.
uint8_t range
Value range used in RSRP/RSRQ threshold.
@ THRESHOLD_RSRQ
RSRQ is used for the threshold.