Handover management SAP interface and A2/RSRQ-based handover algorithm
This commit is contained in:
@@ -124,7 +124,7 @@ NotifyHandoverEndOkEnb (std::string context,
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
// LogLevel logLevel = (LogLevel)(LOG_PREFIX_FUNC | LOG_PREFIX_TIME | LOG_LEVEL_ALL);
|
||||
// LogLevel logLevel = (LogLevel)(LOG_PREFIX_ALL | LOG_LEVEL_ALL);
|
||||
|
||||
// LogComponentEnable ("LteHelper", logLevel);
|
||||
// LogComponentEnable ("EpcHelper", logLevel);
|
||||
@@ -136,15 +136,16 @@ main (int argc, char *argv[])
|
||||
// LogComponentEnable ("LteEnbNetDevice", logLevel);
|
||||
// LogComponentEnable ("LteUeRrc", logLevel);
|
||||
// LogComponentEnable ("LteUeNetDevice", logLevel);
|
||||
// LogComponentEnable ("A2RsrqHandoverAlgorithm", logLevel);
|
||||
|
||||
uint16_t numberOfUes = 1;
|
||||
uint16_t numberOfEnbs = 2;
|
||||
uint16_t numBearersPerUe = 0;
|
||||
double distance = 1000.0; // m
|
||||
double yForUe = 1000.0; // m
|
||||
double speed = 20; // m/s
|
||||
double simTime = 3.0 * distance / speed; // 3000 m / 20 m/s = 150 secs
|
||||
double enbTxPowerDbm = 20.0;
|
||||
double distance = 500.0; // m
|
||||
double yForUe = 500.0; // m
|
||||
double speed = 20; // m/s
|
||||
double simTime = (double)(numberOfEnbs + 1) * distance / speed; // 1500 m / 20 m/s = 75 secs
|
||||
double enbTxPowerDbm = 46.0;
|
||||
|
||||
// change some default attributes so that they are reasonable for
|
||||
// this scenario, but do this before processing command line
|
||||
@@ -157,7 +158,7 @@ main (int argc, char *argv[])
|
||||
CommandLine cmd;
|
||||
cmd.AddValue ("simTime", "Total duration of the simulation (in seconds)", simTime);
|
||||
cmd.AddValue ("speed", "Speed of the UE (default = 20 m/s)", speed);
|
||||
cmd.AddValue ("enbTxPowerDbm", "TX power [dBm] used by HeNBs (defalut = 20.0)", enbTxPowerDbm);
|
||||
cmd.AddValue ("enbTxPowerDbm", "TX power [dBm] used by HeNBs (defalut = 46.0)", enbTxPowerDbm);
|
||||
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
@@ -166,6 +167,11 @@ main (int argc, char *argv[])
|
||||
Ptr<EpcHelper> epcHelper = CreateObject<EpcHelper> ();
|
||||
lteHelper->SetEpcHelper (epcHelper);
|
||||
lteHelper->SetSchedulerType ("ns3::RrFfMacScheduler");
|
||||
lteHelper->SetHandoverAlgorithmType ("ns3::A2RsrqHandoverAlgorithm");
|
||||
lteHelper->SetHandoverAlgorithmAttribute ("ServingCellThreshold",
|
||||
UintegerValue (15));
|
||||
lteHelper->SetHandoverAlgorithmAttribute ("NeighbourCellOffset",
|
||||
UintegerValue (1));
|
||||
|
||||
Ptr<Node> pgw = epcHelper->GetPgwNode ();
|
||||
|
||||
@@ -194,6 +200,21 @@ main (int argc, char *argv[])
|
||||
// interface 0 is localhost, 1 is the p2p device
|
||||
remoteHostStaticRouting->AddNetworkRouteTo (Ipv4Address ("7.0.0.0"), Ipv4Mask ("255.0.0.0"), 1);
|
||||
|
||||
/*
|
||||
* Network topology:
|
||||
*
|
||||
* | + --------------------------------------------------------->
|
||||
* | UE
|
||||
* |
|
||||
* | d d d
|
||||
* y | |-------------------x-------------------x-------------------
|
||||
* | | eNodeB eNodeB
|
||||
* | d |
|
||||
* | |
|
||||
* | | d = distance
|
||||
* o (0, 0, 0) y = yForUe
|
||||
*/
|
||||
|
||||
NodeContainer ueNodes;
|
||||
NodeContainer enbNodes;
|
||||
enbNodes.Create (numberOfEnbs);
|
||||
@@ -223,49 +244,6 @@ main (int argc, char *argv[])
|
||||
NetDeviceContainer enbLteDevs = lteHelper->InstallEnbDevice (enbNodes);
|
||||
NetDeviceContainer ueLteDevs = lteHelper->InstallUeDevice (ueNodes);
|
||||
|
||||
// Setup pre-GSOC UE measurement configuration to the eNodeBs
|
||||
|
||||
// Event A2
|
||||
LteRrcSap::ReportConfigEutra reportConfigA2;
|
||||
reportConfigA2.triggerType = LteRrcSap::ReportConfigEutra::EVENT;
|
||||
reportConfigA2.eventId = LteRrcSap::ReportConfigEutra::EVENT_A2;
|
||||
reportConfigA2.threshold1.choice = LteRrcSap::ThresholdEutra::THRESHOLD_RSRQ;
|
||||
reportConfigA2.threshold1.range = 34;
|
||||
reportConfigA2.hysteresis = 0;
|
||||
reportConfigA2.timeToTrigger = 0;
|
||||
reportConfigA2.triggerQuantity = LteRrcSap::ReportConfigEutra::RSRQ;
|
||||
reportConfigA2.reportQuantity = LteRrcSap::ReportConfigEutra::SAME_AS_TRIGGER_QUANTITY;
|
||||
reportConfigA2.maxReportCells = LteRrcSap::MaxReportCells;
|
||||
reportConfigA2.reportInterval = LteRrcSap::ReportConfigEutra::MS480;
|
||||
reportConfigA2.reportAmount = 255;
|
||||
|
||||
// Event A4
|
||||
LteRrcSap::ReportConfigEutra reportConfigA4;
|
||||
reportConfigA4.triggerType = LteRrcSap::ReportConfigEutra::EVENT;
|
||||
reportConfigA4.eventId = LteRrcSap::ReportConfigEutra::EVENT_A4;
|
||||
reportConfigA4.threshold1.choice = LteRrcSap::ThresholdEutra::THRESHOLD_RSRQ;
|
||||
reportConfigA4.threshold1.range = 0;
|
||||
reportConfigA4.hysteresis = 0;
|
||||
reportConfigA4.timeToTrigger = 0;
|
||||
reportConfigA4.triggerQuantity = LteRrcSap::ReportConfigEutra::RSRQ;
|
||||
reportConfigA4.reportQuantity = LteRrcSap::ReportConfigEutra::SAME_AS_TRIGGER_QUANTITY;
|
||||
reportConfigA4.maxReportCells = LteRrcSap::MaxReportCells;
|
||||
reportConfigA4.reportInterval = LteRrcSap::ReportConfigEutra::MS480;
|
||||
reportConfigA4.reportAmount = 255;
|
||||
|
||||
uint8_t measId;
|
||||
|
||||
for (NetDeviceContainer::Iterator it = enbLteDevs.Begin ();
|
||||
it != enbLteDevs.End ();
|
||||
++it)
|
||||
{
|
||||
Ptr<LteEnbRrc> enbRrc = (*it)->GetObject<LteEnbNetDevice> ()->GetRrc ();
|
||||
measId = enbRrc->AddUeMeasReportConfig (reportConfigA2);
|
||||
NS_ASSERT (measId == 1);
|
||||
measId = enbRrc->AddUeMeasReportConfig (reportConfigA4);
|
||||
NS_ASSERT (measId == 2);
|
||||
}
|
||||
|
||||
// Install the IP stack on the UEs
|
||||
internet.Install (ueNodes);
|
||||
Ipv4InterfaceContainer ueIpIfaces;
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include <ns3/lte-enb-net-device.h>
|
||||
#include <ns3/lte-ue-net-device.h>
|
||||
#include <ns3/ff-mac-scheduler.h>
|
||||
#include <ns3/handover-algorithm.h>
|
||||
#include <ns3/lte-rlc.h>
|
||||
#include <ns3/lte-rlc-um.h>
|
||||
#include <ns3/lte-rlc-am.h>
|
||||
@@ -63,9 +64,9 @@ namespace ns3 {
|
||||
NS_OBJECT_ENSURE_REGISTERED (LteHelper);
|
||||
|
||||
LteHelper::LteHelper (void)
|
||||
: m_fadingStreamsAssigned (false),
|
||||
m_imsiCounter (0),
|
||||
m_cellIdCounter (0)
|
||||
: m_fadingStreamsAssigned (false),
|
||||
m_imsiCounter (0),
|
||||
m_cellIdCounter (0)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_enbNetDeviceFactory.SetTypeId (LteEnbNetDevice::GetTypeId ());
|
||||
@@ -145,6 +146,13 @@ TypeId LteHelper::GetTypeId (void)
|
||||
StringValue ("ns3::PfFfMacScheduler"),
|
||||
MakeStringAccessor (&LteHelper::SetSchedulerType),
|
||||
MakeStringChecker ())
|
||||
.AddAttribute ("HandoverAlgorithm",
|
||||
"The type of handover algorithm to be used for eNBs. "
|
||||
"The allowed values for this attributes are the type names "
|
||||
"of any class inheriting from ns3::HandoverAlgorithm.",
|
||||
StringValue ("ns3::A2RsrqHandoverAlgorithm"),
|
||||
MakeStringAccessor (&LteHelper::SetHandoverAlgorithmType),
|
||||
MakeStringChecker ())
|
||||
.AddAttribute ("PathlossModel",
|
||||
"The type of pathloss model to be used. "
|
||||
"The allowed values for this attributes are the type names "
|
||||
@@ -202,6 +210,21 @@ LteHelper::SetSchedulerAttribute (std::string n, const AttributeValue &v)
|
||||
m_schedulerFactory.Set (n, v);
|
||||
}
|
||||
|
||||
void
|
||||
LteHelper::SetHandoverAlgorithmType (std::string type)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << type);
|
||||
m_handoverAlgorithmFactory = ObjectFactory ();
|
||||
m_handoverAlgorithmFactory.SetTypeId (type);
|
||||
}
|
||||
|
||||
void
|
||||
LteHelper::SetHandoverAlgorithmAttribute (std::string n, const AttributeValue &v)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << n);
|
||||
m_handoverAlgorithmFactory.Set (n, v);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LteHelper::SetPathlossModelType (std::string type)
|
||||
@@ -367,6 +390,7 @@ LteHelper::InstallSingleEnbDevice (Ptr<Node> n)
|
||||
|
||||
Ptr<LteEnbMac> mac = CreateObject<LteEnbMac> ();
|
||||
Ptr<FfMacScheduler> sched = m_schedulerFactory.Create<FfMacScheduler> ();
|
||||
Ptr<HandoverAlgorithm> handoverAlgorithm = m_handoverAlgorithmFactory.Create<HandoverAlgorithm> ();
|
||||
Ptr<LteEnbRrc> rrc = CreateObject<LteEnbRrc> ();
|
||||
|
||||
if (m_useIdealRrc)
|
||||
@@ -401,6 +425,9 @@ LteHelper::InstallSingleEnbDevice (Ptr<Node> n)
|
||||
mac->SetLteEnbCmacSapUser (rrc->GetLteEnbCmacSapUser ());
|
||||
rrc->SetLteMacSapProvider (mac->GetLteMacSapProvider ());
|
||||
|
||||
rrc->SetHandoverManagementSapProvider (handoverAlgorithm->GetHandoverManagementSapProvider ());
|
||||
handoverAlgorithm->SetHandoverManagementSapUser (rrc->GetHandoverManagementSapUser ());
|
||||
|
||||
mac->SetFfMacSchedSapProvider (sched->GetFfMacSchedSapProvider ());
|
||||
mac->SetFfMacCschedSapProvider (sched->GetFfMacCschedSapProvider ());
|
||||
|
||||
@@ -421,6 +448,7 @@ LteHelper::InstallSingleEnbDevice (Ptr<Node> n)
|
||||
dev->SetAttribute ("LteEnbMac", PointerValue (mac));
|
||||
dev->SetAttribute ("FfMacScheduler", PointerValue (sched));
|
||||
dev->SetAttribute ("LteEnbRrc", PointerValue (rrc));
|
||||
dev->SetAttribute ("HandoverAlgorithm", PointerValue (handoverAlgorithm));
|
||||
|
||||
phy->SetDevice (dev);
|
||||
dlPhy->SetDevice (dev);
|
||||
@@ -447,7 +475,7 @@ LteHelper::InstallSingleEnbDevice (Ptr<Node> n)
|
||||
{
|
||||
NS_LOG_WARN ("UL propagation model does not have a Frequency attribute");
|
||||
}
|
||||
|
||||
|
||||
|
||||
dev->Initialize ();
|
||||
|
||||
@@ -463,7 +491,7 @@ LteHelper::InstallSingleEnbDevice (Ptr<Node> n)
|
||||
// S1 SAPs
|
||||
rrc->SetS1SapProvider (enbApp->GetS1SapProvider ());
|
||||
enbApp->SetS1SapUser (rrc->GetS1SapUser ());
|
||||
|
||||
|
||||
// X2 SAPs
|
||||
Ptr<EpcX2> x2 = n->GetObject<EpcX2> ();
|
||||
x2->SetEpcX2SapUser (rrc->GetEpcX2SapUser ());
|
||||
|
||||
@@ -106,6 +106,20 @@ public:
|
||||
*/
|
||||
void SetSchedulerAttribute (std::string n, const AttributeValue &v);
|
||||
|
||||
/**
|
||||
*
|
||||
* \param type the type of handover algorithm to be used for the eNBs
|
||||
*/
|
||||
void SetHandoverAlgorithmType (std::string type);
|
||||
|
||||
/**
|
||||
* set an attribute for the handover algorithm to be created
|
||||
*
|
||||
* \param n the name of the attribute
|
||||
* \param v the value of the attribute
|
||||
*/
|
||||
void SetHandoverAlgorithmAttribute (std::string n, const AttributeValue &v);
|
||||
|
||||
/**
|
||||
* set an attribute for the LteEnbNetDevice to be created
|
||||
*
|
||||
@@ -630,6 +644,7 @@ private:
|
||||
Ptr<Object> m_uplinkPathlossModel;
|
||||
|
||||
ObjectFactory m_schedulerFactory;
|
||||
ObjectFactory m_handoverAlgorithmFactory;
|
||||
ObjectFactory m_propagationModelFactory;
|
||||
ObjectFactory m_enbNetDeviceFactory;
|
||||
ObjectFactory m_enbAntennaModelFactory;
|
||||
|
||||
313
src/lte/model/a2-rsrq-handover-algorithm.cc
Normal file
313
src/lte/model/a2-rsrq-handover-algorithm.cc
Normal file
@@ -0,0 +1,313 @@
|
||||
/* -*- 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 <buherman@student.jyu.fi>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "a2-rsrq-handover-algorithm.h"
|
||||
#include <ns3/handover-management-sap.h>
|
||||
#include <ns3/log.h>
|
||||
#include <ns3/uinteger.h>
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("A2RsrqHandoverAlgorithm");
|
||||
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (A2RsrqHandoverAlgorithm);
|
||||
|
||||
|
||||
///////////////////////////////////////////
|
||||
// Handover Management SAP forwarder
|
||||
///////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* \brief Class for forwarding Handover Management SAP Provider functions.
|
||||
*/
|
||||
class A2RsrqMemberHandoverManagementSapProvider : public HandoverManagementSapProvider
|
||||
{
|
||||
public:
|
||||
A2RsrqMemberHandoverManagementSapProvider (A2RsrqHandoverAlgorithm* handoverAlgorithm);
|
||||
|
||||
// methods inherited from HandoverManagementSapProvider go here
|
||||
virtual void ReportUeMeas (uint16_t rnti, LteRrcSap::MeasResults measResults);
|
||||
|
||||
private:
|
||||
A2RsrqHandoverAlgorithm* m_handoverAlgorithm;
|
||||
};
|
||||
|
||||
A2RsrqMemberHandoverManagementSapProvider::A2RsrqMemberHandoverManagementSapProvider (A2RsrqHandoverAlgorithm* handoverAlgorithm)
|
||||
: m_handoverAlgorithm (handoverAlgorithm)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
A2RsrqMemberHandoverManagementSapProvider::ReportUeMeas (uint16_t rnti,
|
||||
LteRrcSap::MeasResults measResults)
|
||||
{
|
||||
m_handoverAlgorithm->DoReportUeMeas (rnti, measResults);
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////
|
||||
// A2 Based Handover Algorithm
|
||||
///////////////////////////////////////////
|
||||
|
||||
|
||||
A2RsrqHandoverAlgorithm::A2RsrqHandoverAlgorithm ()
|
||||
: m_handoverManagementSapUser (0)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_handoverManagementSapProvider = new A2RsrqMemberHandoverManagementSapProvider (this);
|
||||
}
|
||||
|
||||
|
||||
A2RsrqHandoverAlgorithm::~A2RsrqHandoverAlgorithm ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
A2RsrqHandoverAlgorithm::DoDispose ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
delete m_handoverManagementSapProvider;
|
||||
}
|
||||
|
||||
|
||||
TypeId
|
||||
A2RsrqHandoverAlgorithm::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::A2RsrqHandoverAlgorithm")
|
||||
.SetParent<HandoverAlgorithm> ()
|
||||
.AddConstructor<A2RsrqHandoverAlgorithm> ()
|
||||
.AddAttribute ("ServingCellThreshold",
|
||||
"If serving cell is worse than this threshold, neighbour cells are consider for Handover",
|
||||
UintegerValue (30),
|
||||
MakeUintegerAccessor (&A2RsrqHandoverAlgorithm::m_servingCellThreshold),
|
||||
MakeUintegerChecker<uint8_t> ())
|
||||
.AddAttribute ("NeighbourCellOffset",
|
||||
"Minimum offset between serving and best neighbour cell to trigger the Handover",
|
||||
UintegerValue (1),
|
||||
MakeUintegerAccessor (&A2RsrqHandoverAlgorithm::m_neighbourCellOffset),
|
||||
MakeUintegerChecker<uint8_t> ())
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
A2RsrqHandoverAlgorithm::SetHandoverManagementSapUser (HandoverManagementSapUser* s)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << s);
|
||||
m_handoverManagementSapUser = s;
|
||||
}
|
||||
|
||||
|
||||
HandoverManagementSapProvider*
|
||||
A2RsrqHandoverAlgorithm::GetHandoverManagementSapProvider ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_handoverManagementSapProvider;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
A2RsrqHandoverAlgorithm::DoInitialize ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
LteRrcSap::ReportConfigEutra reportConfigA2;
|
||||
reportConfigA2.eventId = LteRrcSap::ReportConfigEutra::EVENT_A2;
|
||||
reportConfigA2.threshold1.choice = LteRrcSap::ThresholdEutra::THRESHOLD_RSRQ;
|
||||
reportConfigA2.threshold1.range = m_servingCellThreshold;
|
||||
reportConfigA2.triggerQuantity = LteRrcSap::ReportConfigEutra::RSRQ;
|
||||
reportConfigA2.reportInterval = LteRrcSap::ReportConfigEutra::MS240;
|
||||
m_a2measId = m_handoverManagementSapUser->AddUeMeasReportConfig (reportConfigA2);
|
||||
|
||||
LteRrcSap::ReportConfigEutra reportConfigA4;
|
||||
reportConfigA4.eventId = LteRrcSap::ReportConfigEutra::EVENT_A4;
|
||||
reportConfigA4.threshold1.choice = LteRrcSap::ThresholdEutra::THRESHOLD_RSRQ;
|
||||
reportConfigA4.threshold1.range = 0; // intentionally very low threshold
|
||||
reportConfigA4.triggerQuantity = LteRrcSap::ReportConfigEutra::RSRQ;
|
||||
reportConfigA4.reportInterval = LteRrcSap::ReportConfigEutra::MS480;
|
||||
m_a4measId = m_handoverManagementSapUser->AddUeMeasReportConfig (reportConfigA4);
|
||||
|
||||
HandoverAlgorithm::DoInitialize ();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
A2RsrqHandoverAlgorithm::DoReportUeMeas (uint16_t rnti,
|
||||
LteRrcSap::MeasResults measResults)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << rnti << (uint16_t) measResults.measId);
|
||||
|
||||
if (measResults.measId == m_a2measId)
|
||||
{
|
||||
NS_ASSERT_MSG (measResults.rsrqResult <= m_servingCellThreshold,
|
||||
"Invalid UE measurement report");
|
||||
EvaluateHandover (rnti, measResults.rsrqResult);
|
||||
}
|
||||
else if (measResults.measId == m_a4measId)
|
||||
{
|
||||
if (measResults.haveMeasResultNeighCells
|
||||
&& !measResults.measResultListEutra.empty ())
|
||||
{
|
||||
for (std::list <LteRrcSap::MeasResultEutra>::iterator it = measResults.measResultListEutra.begin ();
|
||||
it != measResults.measResultListEutra.end ();
|
||||
++it)
|
||||
{
|
||||
NS_ASSERT_MSG (it->haveRsrqResult == true,
|
||||
"RSRQ measure missing for cellId " << it->physCellId);
|
||||
UpdateNeighbourMeasurements (rnti, it->physCellId, it->rsrqResult);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_LOGIC ("WARNING");
|
||||
// NS_ASSERT_MSG ("Event A4 received without measure results for neighbour cells");
|
||||
// TODO Remove neighbours in the neighbourCellMeasures table
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_WARN ("Ignoring measId " << (uint16_t) measResults.measId);
|
||||
}
|
||||
|
||||
} // end of DoReportUeMeas
|
||||
|
||||
|
||||
void
|
||||
A2RsrqHandoverAlgorithm::EvaluateHandover (uint16_t rnti,
|
||||
uint8_t servingCellRsrq)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << rnti << (uint16_t) servingCellRsrq);
|
||||
|
||||
MeasurementTable_t::iterator it1;
|
||||
it1 = m_neighbourCellMeasures.find (rnti);
|
||||
|
||||
if (it1 == m_neighbourCellMeasures.end ())
|
||||
{
|
||||
NS_LOG_WARN ("Skipping handover evaluation for RNTI " << rnti << " because neighbour cells information is not found");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Find the best neighbour cell (eNB)
|
||||
NS_LOG_LOGIC ("Number of neighbour cells = " << it1->second.size ());
|
||||
uint16_t bestNeighbourCellId = 0;
|
||||
uint8_t bestNeighbourRsrq = 0;
|
||||
MeasurementRow_t::iterator it2;
|
||||
for (it2 = it1->second.begin (); it2 != it1->second.end (); ++it2)
|
||||
{
|
||||
if ((it2->second->m_rsrq > bestNeighbourRsrq)
|
||||
&& IsValidNeighbour (it2->first))
|
||||
{
|
||||
bestNeighbourCellId = it2->first;
|
||||
bestNeighbourRsrq = it2->second->m_rsrq;
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger Handover, if needed
|
||||
if (bestNeighbourCellId > 0)
|
||||
{
|
||||
NS_LOG_LOGIC ("Best neighbour cellId " << bestNeighbourCellId);
|
||||
|
||||
if ((bestNeighbourRsrq - servingCellRsrq) >= m_neighbourCellOffset)
|
||||
{
|
||||
NS_LOG_LOGIC ("Trigger Handover to cellId " << bestNeighbourCellId);
|
||||
NS_LOG_LOGIC ("target cell RSRQ " << (uint16_t) bestNeighbourRsrq);
|
||||
NS_LOG_LOGIC ("serving cell RSRQ " << (uint16_t) servingCellRsrq);
|
||||
|
||||
// Inform eNodeB RRC about handover
|
||||
m_handoverManagementSapUser->TriggerHandover (rnti,
|
||||
bestNeighbourCellId);
|
||||
}
|
||||
}
|
||||
|
||||
} // end of else of if (it1 == m_neighbourCellMeasures.end ())
|
||||
|
||||
} // end of EvaluateMeasurementReport
|
||||
|
||||
|
||||
bool
|
||||
A2RsrqHandoverAlgorithm::IsValidNeighbour (uint16_t cellId)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << cellId);
|
||||
|
||||
// Ptr<NeighbourRelation> neighbourRelation = m_rrc->m_neighbourRelationTable[it->second->m_cellId];
|
||||
// if ((neighbourRelation->m_noHo == false) &&
|
||||
// (neighbourRelation->m_noX2 == false))
|
||||
// {
|
||||
// bestNeighbour = it->second;
|
||||
// bestNeighbourRsrq = it->second->m_rsrq;
|
||||
// }
|
||||
// TODO
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
A2RsrqHandoverAlgorithm::UpdateNeighbourMeasurements (uint16_t rnti,
|
||||
uint16_t cellId,
|
||||
uint8_t rsrq)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << rnti << cellId << (uint16_t) rsrq);
|
||||
MeasurementTable_t::iterator it1;
|
||||
it1 = m_neighbourCellMeasures.find (rnti);
|
||||
|
||||
if (it1 == m_neighbourCellMeasures.end ())
|
||||
{
|
||||
// insert a new UE entry
|
||||
MeasurementRow_t row;
|
||||
std::pair<MeasurementTable_t::iterator, bool> ret;
|
||||
ret = m_neighbourCellMeasures.insert (std::pair<uint16_t, MeasurementRow_t> (rnti, row));
|
||||
NS_ASSERT (ret.second);
|
||||
it1 = ret.first;
|
||||
}
|
||||
|
||||
NS_ASSERT (it1 != m_neighbourCellMeasures.end ());
|
||||
Ptr<UeMeasure> neighbourCellMeasures;
|
||||
std::map<uint16_t, Ptr<UeMeasure> >::iterator it2;
|
||||
it2 = it1->second.find (cellId);
|
||||
|
||||
if (it2 != it1->second.end ())
|
||||
{
|
||||
neighbourCellMeasures = it2->second;
|
||||
neighbourCellMeasures->m_cellId = cellId;
|
||||
neighbourCellMeasures->m_rsrp = 0;
|
||||
neighbourCellMeasures->m_rsrq = rsrq;
|
||||
}
|
||||
else
|
||||
{
|
||||
// insert a new cell entry
|
||||
neighbourCellMeasures = CreateObject<UeMeasure> ();
|
||||
neighbourCellMeasures->m_cellId = cellId;
|
||||
neighbourCellMeasures->m_rsrp = 0;
|
||||
neighbourCellMeasures->m_rsrq = rsrq;
|
||||
it1->second[cellId] = neighbourCellMeasures;
|
||||
}
|
||||
|
||||
} // end of UpdateNeighbourMeasurements
|
||||
|
||||
|
||||
} // end of namespace ns3
|
||||
113
src/lte/model/a2-rsrq-handover-algorithm.h
Normal file
113
src/lte/model/a2-rsrq-handover-algorithm.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/* -*- 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 <buherman@student.jyu.fi>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef A2_RSRQ_HANDOVER_ALGORITHM_H
|
||||
#define A2_RSRQ_HANDOVER_ALGORITHM_H
|
||||
|
||||
#include <ns3/handover-algorithm.h>
|
||||
#include <ns3/lte-rrc-sap.h>
|
||||
#include <map>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
|
||||
class HandoverManagementSapProvider;
|
||||
class HandoverManagementSapUser;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Implements the Handover Management SAP for a handover algorithm based
|
||||
* on RSRQ and Event A2 (serving cell's RSRQ becomes worse than a
|
||||
* threshold).
|
||||
*
|
||||
* The threshold used by the algorithm can be configured in the
|
||||
* `ServingCellThreshold` attribute.
|
||||
*/
|
||||
class A2RsrqHandoverAlgorithm : public HandoverAlgorithm
|
||||
{
|
||||
public:
|
||||
A2RsrqHandoverAlgorithm ();
|
||||
virtual ~A2RsrqHandoverAlgorithm ();
|
||||
|
||||
// inherited from Object
|
||||
virtual void DoDispose (void);
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
// inherited from HandoverAlgorithm
|
||||
virtual void SetHandoverManagementSapUser (HandoverManagementSapUser* s);
|
||||
virtual HandoverManagementSapProvider* GetHandoverManagementSapProvider ();
|
||||
|
||||
friend class A2RsrqMemberHandoverManagementSapProvider;
|
||||
|
||||
protected:
|
||||
// inherited from Object
|
||||
virtual void DoInitialize ();
|
||||
|
||||
private:
|
||||
|
||||
// Handover Management SAP implementation
|
||||
void DoReportUeMeas (uint16_t rnti, LteRrcSap::MeasResults measResults);
|
||||
|
||||
// Internal methods
|
||||
void EvaluateHandover (uint16_t rnti, uint8_t servingCellRsrq);
|
||||
bool IsValidNeighbour (uint16_t cellId);
|
||||
void UpdateNeighbourMeasurements (uint16_t rnti, uint16_t cellId,
|
||||
uint8_t rsrq);
|
||||
|
||||
// The expected measurement identities
|
||||
uint8_t m_a2measId;
|
||||
uint8_t m_a4measId;
|
||||
|
||||
/**
|
||||
* \brief Measurements reported by a UE for a cell ID.
|
||||
*
|
||||
* The values are quantized according 3GPP TS 36.133 section 9.1.4 and 9.1.7.
|
||||
*/
|
||||
class UeMeasure : public Object
|
||||
{
|
||||
public:
|
||||
uint16_t m_cellId;
|
||||
uint8_t m_rsrp;
|
||||
uint8_t m_rsrq;
|
||||
};
|
||||
// TODO instead of class, try using struct or SimpleRefCount
|
||||
|
||||
// cellId
|
||||
typedef std::map<uint16_t, Ptr<UeMeasure> > MeasurementRow_t;
|
||||
// rnti
|
||||
typedef std::map<uint16_t, MeasurementRow_t> MeasurementTable_t;
|
||||
MeasurementTable_t m_neighbourCellMeasures;
|
||||
|
||||
// Class attributes
|
||||
uint8_t m_servingCellThreshold;
|
||||
uint8_t m_neighbourCellOffset;
|
||||
|
||||
// Handover Management SAPs
|
||||
HandoverManagementSapUser* m_handoverManagementSapUser;
|
||||
HandoverManagementSapProvider* m_handoverManagementSapProvider;
|
||||
|
||||
}; // end of class A2RsrqHandoverAlgorithm
|
||||
|
||||
|
||||
} // end of namespace ns3
|
||||
|
||||
|
||||
#endif /* A2_RSRQ_HANDOVER_ALGORITHM_H */
|
||||
58
src/lte/model/handover-algorithm.cc
Normal file
58
src/lte/model/handover-algorithm.cc
Normal file
@@ -0,0 +1,58 @@
|
||||
/* -*- 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 <buherman@student.jyu.fi>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "handover-algorithm.h"
|
||||
#include <ns3/log.h>
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("HandoverAlgorithm");
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (HandoverAlgorithm);
|
||||
|
||||
|
||||
HandoverAlgorithm::HandoverAlgorithm ()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
HandoverAlgorithm::~HandoverAlgorithm ()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HandoverAlgorithm::DoDispose ()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
TypeId
|
||||
HandoverAlgorithm::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::HandoverAlgorithm")
|
||||
.SetParent<Object> ()
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
|
||||
} // end of namespace ns3
|
||||
69
src/lte/model/handover-algorithm.h
Normal file
69
src/lte/model/handover-algorithm.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/* -*- 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 <buherman@student.jyu.fi>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HANDOVER_ALGORITHM_H
|
||||
#define HANDOVER_ALGORITHM_H
|
||||
|
||||
#include <ns3/object.h>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class HandoverManagementSapProvider;
|
||||
class HandoverManagementSapUser;
|
||||
|
||||
|
||||
/**
|
||||
* \brief This abstract base class identifies the interface by means of which
|
||||
* the helper object can plug on the eNodeB RRC a handover algorithm
|
||||
* implementation.
|
||||
*/
|
||||
class HandoverAlgorithm : public Object
|
||||
{
|
||||
public:
|
||||
HandoverAlgorithm ();
|
||||
virtual ~HandoverAlgorithm ();
|
||||
|
||||
// inherited from Object
|
||||
virtual void DoDispose (void);
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
/**
|
||||
* \brief Set the user part of the HandoverManagementSap that this handover
|
||||
* algorithm will interact with. Normally this part of the SAP is
|
||||
* exported by the eNodeB RRC.
|
||||
* \param s
|
||||
*/
|
||||
virtual void SetHandoverManagementSapUser (HandoverManagementSapUser* s) = 0;
|
||||
|
||||
/**
|
||||
*
|
||||
* \return the Provider part of the HandoverManagementSap provided by the
|
||||
* handover algorithm
|
||||
*/
|
||||
virtual HandoverManagementSapProvider* GetHandoverManagementSapProvider () = 0;
|
||||
|
||||
}; // end of class HandoverAlgorithm
|
||||
|
||||
|
||||
} // end of namespace ns3
|
||||
|
||||
|
||||
#endif /* HANDOVER_ALGORITHM_H */
|
||||
37
src/lte/model/handover-management-sap.cc
Normal file
37
src/lte/model/handover-management-sap.cc
Normal file
@@ -0,0 +1,37 @@
|
||||
/* -*- 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 <buherman@student.jyu.fi>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "handover-management-sap.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
|
||||
HandoverManagementSapProvider::~HandoverManagementSapProvider ()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
HandoverManagementSapUser::~HandoverManagementSapUser ()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
} // end of namespace ns3
|
||||
102
src/lte/model/handover-management-sap.h
Normal file
102
src/lte/model/handover-management-sap.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/* -*- 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 <buherman@student.jyu.fi>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HANDOVER_MANAGEMENT_SAP_H
|
||||
#define HANDOVER_MANAGEMENT_SAP_H
|
||||
|
||||
#include <ns3/lte-rrc-sap.h>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
|
||||
/**
|
||||
* \brief Service Access Point (SAP) used by the eNodeB RRC instance to send
|
||||
* messages to the handover algorithm instance.
|
||||
*/
|
||||
class HandoverManagementSapProvider
|
||||
{
|
||||
public:
|
||||
virtual ~HandoverManagementSapProvider ();
|
||||
|
||||
/**
|
||||
* \brief Send a UE measurement report to handover algorithm.
|
||||
* \param rnti Radio Network Temporary Identity, an integer identifying the UE
|
||||
* 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.
|
||||
*/
|
||||
virtual void ReportUeMeas (uint16_t rnti,
|
||||
LteRrcSap::MeasResults measResults) = 0;
|
||||
|
||||
}; // end of class HandoverManagementSapProvider
|
||||
|
||||
|
||||
/**
|
||||
* \brief Service Access Point (SAP) used by the handover algorithm instance to
|
||||
* send messages to the eNodeB RRC instance.
|
||||
*/
|
||||
class HandoverManagementSapUser
|
||||
{
|
||||
public:
|
||||
virtual ~HandoverManagementSapUser ();
|
||||
|
||||
/**
|
||||
* \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
|
||||
* handover algorithm through the HandoverManagementSapProvider::ReportUeMeas
|
||||
* SAP function.
|
||||
*
|
||||
* This function is only valid before the simulation begins.
|
||||
*/
|
||||
virtual uint8_t AddUeMeasReportConfig (LteRrcSap::ReportConfigEutra reportConfig) = 0;
|
||||
|
||||
/**
|
||||
* \brief Instruct the eNodeB RRC entity to prepare a handover.
|
||||
* \param rnti Radio Network Temporary Identity, an integer identifying the
|
||||
* UE which shall perform the handover
|
||||
* \param targetCellId the cell ID of the target eNodeB
|
||||
*
|
||||
* This function is used by the handover algorithm entity when a handover
|
||||
* decision has been reached.
|
||||
*
|
||||
* The process to produce the decision is up to the implementation of handover
|
||||
* algorithm. It is typically based on the reported UE measurements, which are
|
||||
* received through the HandoverManagementSapProvider::ReportUeMeas function.
|
||||
*/
|
||||
virtual void TriggerHandover (uint16_t rnti, uint16_t targetCellId) = 0;
|
||||
|
||||
}; // end of class HandoverManagementSapUser
|
||||
|
||||
|
||||
} // end of namespace ns3
|
||||
|
||||
|
||||
#endif /* HANDOVER_MANAGEMENT_SAP_H */
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <ns3/lte-ue-net-device.h>
|
||||
#include <ns3/lte-enb-phy.h>
|
||||
#include <ns3/ff-mac-scheduler.h>
|
||||
#include <ns3/handover-algorithm.h>
|
||||
#include <ns3/ipv4-l3-protocol.h>
|
||||
#include <ns3/abort.h>
|
||||
#include <ns3/log.h>
|
||||
@@ -60,6 +61,11 @@ TypeId LteEnbNetDevice::GetTypeId (void)
|
||||
PointerValue (),
|
||||
MakePointerAccessor (&LteEnbNetDevice::m_rrc),
|
||||
MakePointerChecker <LteEnbRrc> ())
|
||||
.AddAttribute ("HandoverAlgorithm",
|
||||
"The handover algorithm associated to this EnbNetDevice",
|
||||
PointerValue (),
|
||||
MakePointerAccessor (&LteEnbNetDevice::m_handoverAlgorithm),
|
||||
MakePointerChecker <HandoverAlgorithm> ())
|
||||
.AddAttribute ("LteEnbMac",
|
||||
"The MAC associated to this EnbNetDevice",
|
||||
PointerValue (),
|
||||
@@ -132,6 +138,9 @@ LteEnbNetDevice::DoDispose ()
|
||||
m_rrc->Dispose ();
|
||||
m_rrc = 0;
|
||||
|
||||
m_handoverAlgorithm->Dispose ();
|
||||
m_handoverAlgorithm = 0;
|
||||
|
||||
m_phy->Dispose ();
|
||||
m_phy = 0;
|
||||
|
||||
@@ -253,6 +262,7 @@ LteEnbNetDevice::DoInitialize (void)
|
||||
m_phy->Initialize ();
|
||||
m_mac->Initialize ();
|
||||
m_rrc->Initialize ();
|
||||
m_handoverAlgorithm->Initialize ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ class LteEnbPhy;
|
||||
class LteEnbMac;
|
||||
class LteEnbRrc;
|
||||
class FfMacScheduler;
|
||||
class HandoverAlgorithm;
|
||||
|
||||
|
||||
/**
|
||||
@@ -146,6 +147,8 @@ private:
|
||||
|
||||
Ptr<FfMacScheduler> m_scheduler;
|
||||
|
||||
Ptr<HandoverAlgorithm> m_handoverAlgorithm;
|
||||
|
||||
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 */
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "lte-radio-bearer-info.h"
|
||||
#include "eps-bearer-tag.h"
|
||||
#include "ff-mac-csched-sap.h"
|
||||
#include <ns3/handover-management-sap.h>
|
||||
#include "epc-enb-s1-sap.h"
|
||||
|
||||
#include "lte-rlc.h"
|
||||
@@ -54,10 +55,13 @@ NS_LOG_COMPONENT_DEFINE ("LteEnbRrc");
|
||||
namespace ns3 {
|
||||
|
||||
|
||||
// ///////////////////////////
|
||||
///////////////////////////////////////////
|
||||
// CMAC SAP forwarder
|
||||
// ///////////////////////////
|
||||
///////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* \brief Class for forwarding CMAC SAP User functions.
|
||||
*/
|
||||
class EnbRrcMemberLteEnbCmacSapUser : public LteEnbCmacSapUser
|
||||
{
|
||||
public:
|
||||
@@ -95,19 +99,60 @@ EnbRrcMemberLteEnbCmacSapUser::RrcConfigurationUpdateInd (UeConfig params)
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////
|
||||
// Handover Management SAP forwarder
|
||||
///////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* \brief Class for forwarding Handover Management SAP User functions.
|
||||
*/
|
||||
class EnbRrcMemberHandoverManagementSapUser : public HandoverManagementSapUser
|
||||
{
|
||||
public:
|
||||
EnbRrcMemberHandoverManagementSapUser (LteEnbRrc* rrc);
|
||||
|
||||
// methods inherited from HandoverManagementSapUser go here
|
||||
virtual uint8_t AddUeMeasReportConfig (LteRrcSap::ReportConfigEutra reportConfig);
|
||||
virtual void TriggerHandover (uint16_t rnti, uint16_t targetCellId);
|
||||
|
||||
private:
|
||||
LteEnbRrc* m_rrc;
|
||||
};
|
||||
|
||||
EnbRrcMemberHandoverManagementSapUser::EnbRrcMemberHandoverManagementSapUser (LteEnbRrc* rrc)
|
||||
: m_rrc (rrc)
|
||||
{
|
||||
}
|
||||
|
||||
uint8_t
|
||||
EnbRrcMemberHandoverManagementSapUser::AddUeMeasReportConfig (LteRrcSap::ReportConfigEutra reportConfig)
|
||||
{
|
||||
return m_rrc->DoAddUeMeasReportConfig (reportConfig);
|
||||
}
|
||||
|
||||
void
|
||||
EnbRrcMemberHandoverManagementSapUser::TriggerHandover (uint16_t rnti,
|
||||
uint16_t targetCellId)
|
||||
{
|
||||
m_rrc->DoTriggerHandover (rnti, targetCellId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char* g_ueManagerStateName[UeManager::NUM_STATES] =
|
||||
{
|
||||
"INITIAL_RANDOM_ACCESS",
|
||||
"CONNECTION_SETUP",
|
||||
"CONNECTION_REJECTED",
|
||||
"CONNECTED_NORMALLY",
|
||||
"CONNECTION_RECONFIGURATION",
|
||||
"CONNECTION_REESTABLISHMENT",
|
||||
"HANDOVER_PREPARATION",
|
||||
"HANDOVER_JOINING",
|
||||
"HANDOVER_PATH_SWITCH",
|
||||
"HANDOVER_LEAVING",
|
||||
};
|
||||
{
|
||||
"INITIAL_RANDOM_ACCESS",
|
||||
"CONNECTION_SETUP",
|
||||
"CONNECTION_REJECTED",
|
||||
"CONNECTED_NORMALLY",
|
||||
"CONNECTION_RECONFIGURATION",
|
||||
"CONNECTION_REESTABLISHMENT",
|
||||
"HANDOVER_PREPARATION",
|
||||
"HANDOVER_JOINING",
|
||||
"HANDOVER_PATH_SWITCH",
|
||||
"HANDOVER_LEAVING",
|
||||
};
|
||||
|
||||
std::string ToString (UeManager::State s)
|
||||
{
|
||||
@@ -490,8 +535,8 @@ UeManager::ScheduleRrcConnectionReconfiguration ()
|
||||
// a previous reconfiguration still ongoing, we need to wait for it to be finished
|
||||
m_pendingRrcConnectionReconfiguration = true;
|
||||
break;
|
||||
|
||||
case CONNECTED_NORMALLY:
|
||||
|
||||
case CONNECTED_NORMALLY:
|
||||
{
|
||||
m_pendingRrcConnectionReconfiguration = false;
|
||||
LteRrcSap::RrcConnectionReconfiguration msg = BuildRrcConnectionReconfiguration ();
|
||||
@@ -499,8 +544,8 @@ UeManager::ScheduleRrcConnectionReconfiguration ()
|
||||
RecordDataRadioBearersToBeStarted ();
|
||||
SwitchToState (CONNECTION_RECONFIGURATION);
|
||||
}
|
||||
break;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
|
||||
break;
|
||||
@@ -509,11 +554,11 @@ UeManager::ScheduleRrcConnectionReconfiguration ()
|
||||
|
||||
void
|
||||
UeManager::PrepareHandover (uint16_t cellId)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << cellId);
|
||||
{
|
||||
NS_LOG_FUNCTION (this << cellId);
|
||||
switch (m_state)
|
||||
{
|
||||
case CONNECTED_NORMALLY:
|
||||
case CONNECTED_NORMALLY:
|
||||
{
|
||||
m_targetCellId = cellId;
|
||||
EpcX2SapProvider::HandoverRequestParams params;
|
||||
@@ -943,68 +988,12 @@ UeManager::RecvMeasurementReport (LteRrcSap::MeasurementReport msg)
|
||||
<< " RSRQ " << (it->haveRsrqResult ? (uint16_t) it->rsrqResult : 255));
|
||||
}
|
||||
|
||||
m_rrc->m_recvMeasurementReportTrace (m_imsi, m_rrc->m_cellId, m_rnti, msg);
|
||||
|
||||
/*
|
||||
* The code below assumes event A2 at measId 1 and A4 at measId 2, which is
|
||||
* the default configuration from previous release of LENA. This section will
|
||||
* be moved as a separate handover algorithm. To avoid automatically invoking
|
||||
* handover, disable it by setting ns3::LteEnbRrc::AdmitHandoverRequest
|
||||
* attribute to false.
|
||||
*/
|
||||
|
||||
/// Event A2 (Serving becomes worse than threshold)
|
||||
if (msg.measResults.measId == 1)
|
||||
{
|
||||
// Keep new RSRQ value reported for the serving cell
|
||||
m_servingCellMeasures->m_rsrq = msg.measResults.rsrqResult;
|
||||
m_servingCellMeasures->m_rsrp = msg.measResults.rsrpResult;
|
||||
|
||||
// Serving cell is worse than a handover threshold.
|
||||
// This handover threshold is independent from the event A2 threshold
|
||||
if (m_servingCellMeasures->m_rsrq <= m_rrc->m_servingCellHandoverThreshold)
|
||||
{
|
||||
// Find the best neighbour cell (eNB)
|
||||
Ptr<UeMeasure> bestNeighbour = 0;
|
||||
uint8_t bestNeighbourRsrq = 0;
|
||||
NS_LOG_LOGIC ("Number of neighbour cells = " << m_neighbourCellMeasures.size ());
|
||||
for (std::map <uint16_t, Ptr<UeMeasure> >::iterator it = m_neighbourCellMeasures.begin ();
|
||||
it != m_neighbourCellMeasures.end ();
|
||||
++it)
|
||||
{
|
||||
if (it->second->m_rsrq > bestNeighbourRsrq)
|
||||
{
|
||||
Ptr<NeighbourRelation> neighbourRelation = m_rrc->m_neighbourRelationTable[it->second->m_cellId];
|
||||
if ((neighbourRelation->m_noHo == false) &&
|
||||
(neighbourRelation->m_noX2 == false))
|
||||
{
|
||||
bestNeighbour = it->second;
|
||||
bestNeighbourRsrq = it->second->m_rsrq;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger Handover, if needed
|
||||
if (bestNeighbour)
|
||||
{
|
||||
uint16_t targetCellId = bestNeighbour->m_cellId;
|
||||
NS_LOG_LOGIC ("Best neighbour cellId " << targetCellId);
|
||||
if ( (bestNeighbour->m_rsrq - m_servingCellMeasures->m_rsrq >= m_rrc->m_neighbourCellHandoverOffset) &&
|
||||
(m_state == CONNECTED_NORMALLY) )
|
||||
{
|
||||
NS_LOG_LOGIC ("Trigger Handover to cellId " << targetCellId);
|
||||
NS_LOG_LOGIC ("target cell RSRQ " << (uint16_t) bestNeighbour->m_rsrq);
|
||||
NS_LOG_LOGIC ("serving cell RSRQ " << (uint16_t) m_servingCellMeasures->m_rsrq);
|
||||
PrepareHandover (targetCellId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Event A4 (Neighbour becomes better than threshold)
|
||||
else if (msg.measResults.measId == 2)
|
||||
if (msg.measResults.measId == 2) // TODO remove this hardcode
|
||||
{
|
||||
// Update the NRT
|
||||
if (msg.measResults.haveMeasResultNeighCells && ! (msg.measResults.measResultListEutra.empty ()))
|
||||
if (msg.measResults.haveMeasResultNeighCells
|
||||
&& !(msg.measResults.measResultListEutra.empty ()))
|
||||
{
|
||||
for (std::list <LteRrcSap::MeasResultEutra>::iterator it = msg.measResults.measResultListEutra.begin ();
|
||||
it != msg.measResults.measResultListEutra.end ();
|
||||
@@ -1037,34 +1026,24 @@ UeManager::RecvMeasurementReport (LteRrcSap::MeasurementReport msg)
|
||||
neighbourRelation->m_detectedAsNeighbour = true;
|
||||
m_rrc->m_neighbourRelationTable[it->physCellId] = neighbourRelation;
|
||||
}
|
||||
|
||||
// Update measure info of the neighbour cell
|
||||
Ptr<UeMeasure> neighbourCellMeasures;
|
||||
if (m_neighbourCellMeasures.find (it->physCellId) != m_neighbourCellMeasures.end ())
|
||||
{
|
||||
neighbourCellMeasures = m_neighbourCellMeasures[it->physCellId];
|
||||
neighbourCellMeasures->m_cellId = it->physCellId;
|
||||
neighbourCellMeasures->m_rsrq = it->rsrqResult;
|
||||
neighbourCellMeasures->m_rsrp = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
neighbourCellMeasures = CreateObject <UeMeasure> ();
|
||||
neighbourCellMeasures->m_cellId = it->physCellId;
|
||||
neighbourCellMeasures->m_rsrq = it->rsrqResult;
|
||||
neighbourCellMeasures->m_rsrp = 0;
|
||||
m_neighbourCellMeasures[it->physCellId] = neighbourCellMeasures;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_LOGIC ("WARNING");
|
||||
// NS_ASSERT_MSG ("Event A4 received without measure results for neighbour cells");
|
||||
// TODO Remove neighbours in the neighbourCellMeasures table
|
||||
NS_LOG_LOGIC ("WARNING");
|
||||
// NS_ASSERT_MSG ("Event A4 received without measure results for neighbour cells");
|
||||
// TODO Remove neighbours in the neighbourCellMeasures table
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// forward the UE measurements report to the active handover algorithm
|
||||
m_rrc->m_handoverManagementSapProvider->ReportUeMeas (m_rnti,
|
||||
msg.measResults);
|
||||
|
||||
// fire a trace source
|
||||
m_rrc->m_recvMeasurementReportTrace (m_imsi, m_rrc->m_cellId, m_rnti, msg);
|
||||
|
||||
} // end of UeManager::RecvMeasurementReport
|
||||
|
||||
|
||||
// methods forwarded from CMAC SAP
|
||||
@@ -1322,16 +1301,17 @@ UeManager::SwitchToState (State newState)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ///////////////////////////
|
||||
|
||||
///////////////////////////////////////////
|
||||
// eNB RRC methods
|
||||
// ///////////////////////////
|
||||
///////////////////////////////////////////
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (LteEnbRrc);
|
||||
|
||||
LteEnbRrc::LteEnbRrc ()
|
||||
: m_x2SapProvider (0),
|
||||
m_cmacSapProvider (0),
|
||||
m_handoverManagementSapProvider (0),
|
||||
m_rrcSapUser (0),
|
||||
m_macSapProvider (0),
|
||||
m_s1SapProvider (0),
|
||||
@@ -1344,6 +1324,7 @@ LteEnbRrc::LteEnbRrc ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_cmacSapUser = new EnbRrcMemberLteEnbCmacSapUser (this);
|
||||
m_handoverManagementSapUser = new EnbRrcMemberHandoverManagementSapUser (this);
|
||||
m_rrcSapProvider = new MemberLteEnbRrcSapProvider<LteEnbRrc> (this);
|
||||
m_x2SapUser = new EpcX2SpecificEpcX2SapUser<LteEnbRrc> (this);
|
||||
m_s1SapUser = new MemberEpcEnbS1SapUser<LteEnbRrc> (this);
|
||||
@@ -1363,6 +1344,7 @@ LteEnbRrc::DoDispose ()
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_ueMap.clear ();
|
||||
delete m_cmacSapUser;
|
||||
delete m_handoverManagementSapUser;
|
||||
delete m_rrcSapProvider;
|
||||
delete m_x2SapUser;
|
||||
delete m_s1SapUser;
|
||||
@@ -1440,16 +1422,6 @@ LteEnbRrc::GetTypeId (void)
|
||||
BooleanValue (true),
|
||||
MakeBooleanAccessor (&LteEnbRrc::m_admitRrcConnectionRequest),
|
||||
MakeBooleanChecker ())
|
||||
.AddAttribute ("ServingCellHandoverThreshold",
|
||||
"If serving cell is worse than this threshold, neighbour cells are consider for Handover",
|
||||
UintegerValue (15),
|
||||
MakeUintegerAccessor (&LteEnbRrc::m_servingCellHandoverThreshold),
|
||||
MakeUintegerChecker<uint8_t> ())
|
||||
.AddAttribute ("NeighbourCellHandoverOffset",
|
||||
"Minimum offset between serving and best neighbour cell to trigger the Handover",
|
||||
UintegerValue (1),
|
||||
MakeUintegerAccessor (&LteEnbRrc::m_neighbourCellHandoverOffset),
|
||||
MakeUintegerChecker<uint8_t> ())
|
||||
|
||||
// UE measurements related attributes
|
||||
.AddAttribute ("RsrpFilterCoefficient",
|
||||
@@ -1520,6 +1492,20 @@ LteEnbRrc::GetLteEnbCmacSapUser ()
|
||||
return m_cmacSapUser;
|
||||
}
|
||||
|
||||
void
|
||||
LteEnbRrc::SetHandoverManagementSapProvider (HandoverManagementSapProvider * s)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << s);
|
||||
m_handoverManagementSapProvider = s;
|
||||
}
|
||||
|
||||
HandoverManagementSapUser*
|
||||
LteEnbRrc::GetHandoverManagementSapUser ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_handoverManagementSapUser;
|
||||
}
|
||||
|
||||
void
|
||||
LteEnbRrc::SetLteEnbRrcSapUser (LteEnbRrcSapUser * s)
|
||||
{
|
||||
@@ -1585,14 +1571,14 @@ LteEnbRrc::AddUeMeasReportConfig (LteRrcSap::ReportConfigEutra config)
|
||||
NS_ASSERT_MSG (m_ueMeasConfig.measIdToAddModList.size () == m_ueMeasConfig.reportConfigToAddModList.size (),
|
||||
"Measurement identities and reporting configuration should not have different quantity");
|
||||
|
||||
uint8_t nextId = m_ueMeasConfig.reportConfigToAddModList.size () + 1;
|
||||
|
||||
if (Simulator::Now () != Seconds (0))
|
||||
{
|
||||
NS_FATAL_ERROR ("AddUeMeasReportConfig may not be called after the simulation has run");
|
||||
}
|
||||
// TODO more asserts to validate the input
|
||||
|
||||
uint8_t nextId = m_ueMeasConfig.reportConfigToAddModList.size () + 1;
|
||||
|
||||
// create the reporting configuration
|
||||
LteRrcSap::ReportConfigToAddMod reportConfig;
|
||||
reportConfig.reportConfigId = nextId;
|
||||
@@ -2046,6 +2032,23 @@ LteEnbRrc::DoNotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success)
|
||||
}
|
||||
|
||||
|
||||
uint8_t
|
||||
LteEnbRrc::DoAddUeMeasReportConfig (LteRrcSap::ReportConfigEutra reportConfig)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return AddUeMeasReportConfig (reportConfig);
|
||||
}
|
||||
|
||||
void
|
||||
LteEnbRrc::DoTriggerHandover (uint16_t rnti, uint16_t targetCellId)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << rnti << targetCellId);
|
||||
Ptr<UeManager> ueManager = GetUeManager (rnti);
|
||||
NS_ASSERT_MSG (ueManager != 0, "Cannot find UE context with RNTI " << rnti);
|
||||
ueManager->PrepareHandover (targetCellId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint16_t
|
||||
LteEnbRrc::AddUe (UeManager::State state)
|
||||
|
||||
@@ -94,19 +94,19 @@ public:
|
||||
*
|
||||
*/
|
||||
enum State
|
||||
{
|
||||
INITIAL_RANDOM_ACCESS = 0,
|
||||
CONNECTION_SETUP,
|
||||
CONNECTION_REJECTED,
|
||||
CONNECTED_NORMALLY,
|
||||
CONNECTION_RECONFIGURATION,
|
||||
CONNECTION_REESTABLISHMENT,
|
||||
HANDOVER_PREPARATION,
|
||||
HANDOVER_JOINING,
|
||||
HANDOVER_PATH_SWITCH,
|
||||
HANDOVER_LEAVING,
|
||||
NUM_STATES
|
||||
};
|
||||
{
|
||||
INITIAL_RANDOM_ACCESS = 0,
|
||||
CONNECTION_SETUP,
|
||||
CONNECTION_REJECTED,
|
||||
CONNECTED_NORMALLY,
|
||||
CONNECTION_RECONFIGURATION,
|
||||
CONNECTION_REESTABLISHMENT,
|
||||
HANDOVER_PREPARATION,
|
||||
HANDOVER_JOINING,
|
||||
HANDOVER_PATH_SWITCH,
|
||||
HANDOVER_LEAVING,
|
||||
NUM_STATES
|
||||
};
|
||||
|
||||
UeManager ();
|
||||
|
||||
@@ -437,6 +437,11 @@ private:
|
||||
};
|
||||
|
||||
|
||||
|
||||
class HandoverManagementSapProvider;
|
||||
class HandoverManagementSapUser;
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup lte
|
||||
*
|
||||
@@ -446,6 +451,7 @@ class LteEnbRrc : public Object
|
||||
{
|
||||
|
||||
friend class EnbRrcMemberLteEnbCmacSapUser;
|
||||
friend class EnbRrcMemberHandoverManagementSapUser;
|
||||
friend class MemberLteEnbRrcSapProvider<LteEnbRrc>;
|
||||
friend class MemberEpcEnbS1SapUser<LteEnbRrc>;
|
||||
friend class EpcX2SpecificEpcX2SapUser<LteEnbRrc>;
|
||||
@@ -498,6 +504,21 @@ public:
|
||||
LteEnbCmacSapUser* GetLteEnbCmacSapUser ();
|
||||
|
||||
|
||||
/**
|
||||
* set the Handover Management SAP this RRC should interact with
|
||||
*
|
||||
* \param s the Handover Management SAP Provider to be used by this RRC
|
||||
*/
|
||||
void SetHandoverManagementSapProvider (HandoverManagementSapProvider * s);
|
||||
|
||||
/**
|
||||
* Get the Handover Management SAP offered by this RRC
|
||||
* \return s the Handover Management SAP User interface offered to the
|
||||
* handover algorithm by this RRC
|
||||
*/
|
||||
HandoverManagementSapUser* GetHandoverManagementSapUser ();
|
||||
|
||||
|
||||
/**
|
||||
* set the RRC SAP this RRC should interact with
|
||||
*
|
||||
@@ -683,7 +704,7 @@ public:
|
||||
private:
|
||||
|
||||
|
||||
// methods forwarded from RRC SAP
|
||||
// RRC SAP methods
|
||||
|
||||
void DoCompleteSetupUe (uint16_t rnti, LteEnbRrcSapProvider::CompleteSetupUeParameters params);
|
||||
void DoRecvRrcConnectionRequest (uint16_t rnti, LteRrcSap::RrcConnectionRequest msg);
|
||||
@@ -693,11 +714,13 @@ private:
|
||||
void DoRecvRrcConnectionReestablishmentComplete (uint16_t rnti, LteRrcSap::RrcConnectionReestablishmentComplete msg);
|
||||
void DoRecvMeasurementReport (uint16_t rnti, LteRrcSap::MeasurementReport msg);
|
||||
|
||||
|
||||
// S1 SAP methods
|
||||
|
||||
void DoDataRadioBearerSetupRequest (EpcEnbS1SapUser::DataRadioBearerSetupRequestParameters params);
|
||||
void DoPathSwitchRequestAcknowledge (EpcEnbS1SapUser::PathSwitchRequestAcknowledgeParameters params);
|
||||
void DoPathSwitchRequestAcknowledge (EpcEnbS1SapUser::PathSwitchRequestAcknowledgeParameters params);
|
||||
|
||||
// X2 SAP methods
|
||||
|
||||
void DoRecvHandoverRequest (EpcX2SapUser::HandoverRequestParams params);
|
||||
void DoRecvHandoverRequestAck (EpcX2SapUser::HandoverRequestAckParams params);
|
||||
void DoRecvHandoverPreparationFailure (EpcX2SapUser::HandoverPreparationFailureParams params);
|
||||
@@ -707,12 +730,17 @@ private:
|
||||
void DoRecvResourceStatusUpdate (EpcX2SapUser::ResourceStatusUpdateParams params);
|
||||
void DoRecvUeData (EpcX2SapUser::UeDataParams params);
|
||||
|
||||
|
||||
// CMAC SAP methods
|
||||
|
||||
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);
|
||||
void DoTriggerHandover (uint16_t rnti, uint16_t targetCellId);
|
||||
|
||||
|
||||
// Internal methods
|
||||
|
||||
@@ -836,6 +864,9 @@ private:
|
||||
LteEnbCmacSapUser* m_cmacSapUser;
|
||||
LteEnbCmacSapProvider* m_cmacSapProvider;
|
||||
|
||||
HandoverManagementSapUser* m_handoverManagementSapUser;
|
||||
HandoverManagementSapProvider* m_handoverManagementSapProvider;
|
||||
|
||||
LteEnbRrcSapUser* m_rrcSapUser;
|
||||
LteEnbRrcSapProvider* m_rrcSapProvider;
|
||||
|
||||
@@ -890,8 +921,6 @@ private:
|
||||
// Handover related attributes
|
||||
bool m_admitHandoverRequest;
|
||||
bool m_admitRrcConnectionRequest;
|
||||
uint8_t m_servingCellHandoverThreshold;
|
||||
uint8_t m_neighbourCellHandoverOffset;
|
||||
|
||||
// UE measurements related attributes
|
||||
uint8_t m_rsrpFilterCoefficient;
|
||||
|
||||
@@ -173,8 +173,6 @@ LteX2HandoverMeasuresTestCase::DoRun ()
|
||||
Config::SetDefault ("ns3::UdpClient::Interval", TimeValue (m_udpClientInterval));
|
||||
Config::SetDefault ("ns3::UdpClient::MaxPackets", UintegerValue (1000000));
|
||||
Config::SetDefault ("ns3::UdpClient::PacketSize", UintegerValue (m_udpClientPktSize));
|
||||
Config::SetDefault ("ns3::LteEnbRrc::ServingCellHandoverThreshold", UintegerValue (30));
|
||||
Config::SetDefault ("ns3::LteEnbRrc::NeighbourCellHandoverOffset", UintegerValue (1));
|
||||
Config::SetDefault ("ns3::LteEnbRrc::HandoverJoiningTimeoutDuration", TimeValue (MilliSeconds (200)));
|
||||
Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (20));
|
||||
|
||||
@@ -183,8 +181,13 @@ LteX2HandoverMeasuresTestCase::DoRun ()
|
||||
|
||||
m_lteHelper = CreateObject<LteHelper> ();
|
||||
m_lteHelper->SetAttribute ("PathlossModel", StringValue ("ns3::FriisSpectrumPropagationLossModel"));
|
||||
m_lteHelper->SetSchedulerType (m_schedulerType);
|
||||
m_lteHelper->SetAttribute ("UseIdealRrc", BooleanValue (m_useIdealRrc));
|
||||
m_lteHelper->SetSchedulerType (m_schedulerType);
|
||||
m_lteHelper->SetHandoverAlgorithmType ("ns3::A2RsrqHandoverAlgorithm");
|
||||
m_lteHelper->SetHandoverAlgorithmAttribute ("ServingCellThreshold",
|
||||
UintegerValue (30));
|
||||
m_lteHelper->SetHandoverAlgorithmAttribute ("NeighbourCellOffset",
|
||||
UintegerValue (1));
|
||||
|
||||
|
||||
double distance = 1000.0; // m
|
||||
@@ -225,38 +228,6 @@ LteX2HandoverMeasuresTestCase::DoRun ()
|
||||
ueNodes.Get (i)->GetObject<ConstantVelocityMobilityModel> ()->SetVelocity (Vector (speed, 0, 0));
|
||||
}
|
||||
|
||||
// Setup pre-GSOC UE measurement configuration to the eNodeBs
|
||||
|
||||
// Event A2
|
||||
LteRrcSap::ReportConfigEutra reportConfigA2;
|
||||
reportConfigA2.triggerType = LteRrcSap::ReportConfigEutra::EVENT;
|
||||
reportConfigA2.eventId = LteRrcSap::ReportConfigEutra::EVENT_A2;
|
||||
reportConfigA2.threshold1.choice = LteRrcSap::ThresholdEutra::THRESHOLD_RSRQ;
|
||||
reportConfigA2.threshold1.range = 34;
|
||||
reportConfigA2.hysteresis = 0;
|
||||
reportConfigA2.timeToTrigger = 0;
|
||||
reportConfigA2.triggerQuantity = LteRrcSap::ReportConfigEutra::RSRQ;
|
||||
reportConfigA2.reportQuantity = LteRrcSap::ReportConfigEutra::SAME_AS_TRIGGER_QUANTITY;
|
||||
reportConfigA2.maxReportCells = LteRrcSap::MaxReportCells;
|
||||
reportConfigA2.reportInterval = LteRrcSap::ReportConfigEutra::MS240;
|
||||
reportConfigA2.reportAmount = 255;
|
||||
|
||||
// Event A4
|
||||
LteRrcSap::ReportConfigEutra reportConfigA4;
|
||||
reportConfigA4.triggerType = LteRrcSap::ReportConfigEutra::EVENT;
|
||||
reportConfigA4.eventId = LteRrcSap::ReportConfigEutra::EVENT_A4;
|
||||
reportConfigA4.threshold1.choice = LteRrcSap::ThresholdEutra::THRESHOLD_RSRQ;
|
||||
reportConfigA4.threshold1.range = 0;
|
||||
reportConfigA4.hysteresis = 0;
|
||||
reportConfigA4.timeToTrigger = 0;
|
||||
reportConfigA4.triggerQuantity = LteRrcSap::ReportConfigEutra::RSRQ;
|
||||
reportConfigA4.reportQuantity = LteRrcSap::ReportConfigEutra::SAME_AS_TRIGGER_QUANTITY;
|
||||
reportConfigA4.maxReportCells = LteRrcSap::MaxReportCells;
|
||||
reportConfigA4.reportInterval = LteRrcSap::ReportConfigEutra::MS480;
|
||||
reportConfigA4.reportAmount = 255;
|
||||
|
||||
uint8_t measId;
|
||||
|
||||
NetDeviceContainer enbDevices;
|
||||
enbDevices = m_lteHelper->InstallEnbDevice (enbNodes);
|
||||
stream += m_lteHelper->AssignStreams (enbDevices, stream);
|
||||
@@ -266,11 +237,6 @@ LteX2HandoverMeasuresTestCase::DoRun ()
|
||||
{
|
||||
Ptr<LteEnbRrc> enbRrc = (*it)->GetObject<LteEnbNetDevice> ()->GetRrc ();
|
||||
enbRrc->SetAttribute ("AdmitHandoverRequest", BooleanValue (m_admitHo));
|
||||
|
||||
measId = enbRrc->AddUeMeasReportConfig (reportConfigA2);
|
||||
NS_ASSERT (measId == 1);
|
||||
measId = enbRrc->AddUeMeasReportConfig (reportConfigA4);
|
||||
NS_ASSERT (measId == 2);
|
||||
}
|
||||
|
||||
NetDeviceContainer ueDevices;
|
||||
|
||||
@@ -98,6 +98,9 @@ def build(bld):
|
||||
'model/epc-mme.cc',
|
||||
'model/lte-asn1-header.cc',
|
||||
'model/lte-rrc-header.cc',
|
||||
'model/handover-management-sap.cc',
|
||||
'model/handover-algorithm.cc',
|
||||
'model/a2-rsrq-handover-algorithm.cc',
|
||||
]
|
||||
|
||||
module_test = bld.create_ns3_module_test_library('lte')
|
||||
@@ -243,6 +246,9 @@ def build(bld):
|
||||
'model/epc-mme.h',
|
||||
'model/lte-asn1-header.h',
|
||||
'model/lte-rrc-header.h',
|
||||
'model/handover-management-sap.h',
|
||||
'model/handover-algorithm.h',
|
||||
'model/a2-rsrq-handover-algorithm.h',
|
||||
]
|
||||
|
||||
if (bld.env['ENABLE_EXAMPLES']):
|
||||
|
||||
Reference in New Issue
Block a user