Handover management SAP interface and A2/RSRQ-based handover algorithm

This commit is contained in:
Budiarto Herman
2013-08-07 11:42:53 +03:00
parent 5a3a2f13d5
commit d68107aa9d
15 changed files with 961 additions and 231 deletions

View File

@@ -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;

View File

@@ -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 ());

View File

@@ -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;

View 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

View 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 */

View 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

View 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 */

View 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

View 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 */

View File

@@ -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 ();
}

View File

@@ -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 */

View File

@@ -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)

View File

@@ -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;

View File

@@ -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;

View File

@@ -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']):