X2 handover working on the control plane
This commit is contained in:
@@ -39,6 +39,8 @@ NS_LOG_COMPONENT_DEFINE ("EpcX2HandoverExample");
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
|
||||
Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false));
|
||||
// LogLevel logLevel = (LogLevel)(LOG_PREFIX_FUNC | LOG_PREFIX_TIME | LOG_LEVEL_ALL);
|
||||
|
||||
// LogComponentEnable ("LteHelper", logLevel);
|
||||
@@ -54,8 +56,8 @@ main (int argc, char *argv[])
|
||||
|
||||
uint16_t numberOfUes = 1;
|
||||
uint16_t numberOfEnbs = 2;
|
||||
double simTime = 2.0;
|
||||
double distance = 60.0;
|
||||
double simTime = 0.300;
|
||||
double distance = 100.0;
|
||||
|
||||
// Command line arguments
|
||||
CommandLine cmd;
|
||||
@@ -104,7 +106,7 @@ main (int argc, char *argv[])
|
||||
Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
|
||||
for (uint16_t i = 0; i < numberOfEnbs; i++)
|
||||
{
|
||||
positionAlloc->Add (Vector(distance * i, 0, 0));
|
||||
positionAlloc->Add (Vector(distance * 2*i - distance, 0, 0));
|
||||
}
|
||||
MobilityHelper mobility;
|
||||
mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
|
||||
@@ -145,12 +147,14 @@ main (int argc, char *argv[])
|
||||
lteHelper->AddX2Interface (enbNodes);
|
||||
|
||||
// X2-based Handover
|
||||
lteHelper->HandoverRequest (Seconds (1.0), ueLteDevs.Get (0), enbLteDevs.Get (0), enbLteDevs.Get (1));
|
||||
lteHelper->HandoverRequest (Seconds (0.100), ueLteDevs.Get (0), enbLteDevs.Get (0), enbLteDevs.Get (1));
|
||||
|
||||
|
||||
// Uncomment to enable PCAP tracing
|
||||
//p2ph.EnablePcapAll("lena-x2-handover");
|
||||
|
||||
lteHelper->EnableMacTraces ();
|
||||
|
||||
Simulator::Stop(Seconds(simTime));
|
||||
Simulator::Run();
|
||||
|
||||
|
||||
@@ -157,9 +157,11 @@ public:
|
||||
/**
|
||||
* Allocate a random access preamble for non-contention based random access (e.g., for handover).
|
||||
*
|
||||
* \return the newly allocated random access preamble (0 <
|
||||
* \param rnti the RNTI of the UE who will perform non-contention based random access
|
||||
*
|
||||
* \return the newly allocated random access preamble
|
||||
*/
|
||||
virtual AllocateNcRaPreambleReturnValue AllocateNcRaPreamble () = 0;
|
||||
virtual AllocateNcRaPreambleReturnValue AllocateNcRaPreamble (uint16_t rnti) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
virtual void ReleaseLc (uint16_t rnti, uint8_t lcid);
|
||||
virtual void UeUpdateConfigurationReq (UeConfig params);
|
||||
virtual RachConfig GetRachConfig ();
|
||||
virtual AllocateNcRaPreambleReturnValue AllocateNcRaPreamble ();
|
||||
virtual AllocateNcRaPreambleReturnValue AllocateNcRaPreamble (uint16_t rnti);
|
||||
|
||||
|
||||
private:
|
||||
@@ -128,9 +128,9 @@ EnbMacMemberLteEnbCmacSapProvider::GetRachConfig ()
|
||||
}
|
||||
|
||||
LteEnbCmacSapProvider::AllocateNcRaPreambleReturnValue
|
||||
EnbMacMemberLteEnbCmacSapProvider::AllocateNcRaPreamble ()
|
||||
EnbMacMemberLteEnbCmacSapProvider::AllocateNcRaPreamble (uint16_t rnti)
|
||||
{
|
||||
return m_mac->DoAllocateNcRaPreamble ();
|
||||
return m_mac->DoAllocateNcRaPreamble (rnti);
|
||||
}
|
||||
|
||||
|
||||
@@ -487,17 +487,30 @@ LteEnbMac::DoSubframeIndication (uint32_t frameNo, uint32_t subframeNo)
|
||||
it != m_receivedRachPreambleCount.end ();
|
||||
++it)
|
||||
{
|
||||
NS_LOG_LOGIC ("preambleId " << (uint32_t) it->first << ": " << it->second << " received");
|
||||
NS_LOG_INFO ("RA-RNTI " << raRnti << ", preambleId " << (uint32_t) it->first << ": " << it->second << " received");
|
||||
NS_ASSERT (it->second != 0);
|
||||
if (it->second > 1)
|
||||
{
|
||||
NS_LOG_INFO ("preambleId " << (uint32_t) it->first << ": collision");
|
||||
// we assume that no preamble is successfully received, hence no RAR is sent
|
||||
// in case of collision we assume that no preamble is
|
||||
// successfully received, hence no RAR is sent
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t rnti = m_cmacSapUser->AllocateTemporaryCellRnti ();
|
||||
NS_LOG_INFO ("preambleId " << (uint32_t) it->first << ": allocated T-C-RNTI " << (uint32_t) rnti << ", sending RAR");
|
||||
uint16_t rnti;
|
||||
std::map<uint8_t, NcRaPreambleInfo>::iterator jt = m_allocatedNcRaPreambleMap.find (it->first);
|
||||
if (jt != m_allocatedNcRaPreambleMap.end ())
|
||||
{
|
||||
rnti = jt->second.rnti;
|
||||
NS_LOG_INFO ("preambleId previously allocated for NC based RA, RNTI =" << (uint32_t) rnti << ", sending RAR");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
rnti = m_cmacSapUser->AllocateTemporaryCellRnti ();
|
||||
NS_LOG_INFO ("preambleId " << (uint32_t) it->first << ": allocated T-C-RNTI " << (uint32_t) rnti << ", sending RAR");
|
||||
}
|
||||
|
||||
RachListElement_s rachLe;
|
||||
rachLe.m_rnti = rnti;
|
||||
rachLe.m_estimatedSize = 144; // to be confirmed
|
||||
@@ -841,20 +854,24 @@ LteEnbMac::DoGetRachConfig ()
|
||||
}
|
||||
|
||||
LteEnbCmacSapProvider::AllocateNcRaPreambleReturnValue
|
||||
LteEnbMac::DoAllocateNcRaPreamble ()
|
||||
LteEnbMac::DoAllocateNcRaPreamble (uint16_t rnti)
|
||||
{
|
||||
bool found = false;
|
||||
uint8_t preambleId;
|
||||
for (preambleId = m_numberOfRaPreambles; preambleId < 64; ++preambleId)
|
||||
{
|
||||
std::map<uint8_t, Time>::iterator it = m_allocatedNcRaPreambleMap.find (preambleId);
|
||||
std::map<uint8_t, NcRaPreambleInfo>::iterator it = m_allocatedNcRaPreambleMap.find (preambleId);
|
||||
if ((it == m_allocatedNcRaPreambleMap.end ())
|
||||
|| (it->second < Simulator::Now ()))
|
||||
|| (it->second.expiryTime < Simulator::Now ()))
|
||||
{
|
||||
found = true;
|
||||
NcRaPreambleInfo preambleInfo;
|
||||
uint32_t expiryIntervalMs = (uint32_t) m_preambleTransMax * ((uint32_t) m_raResponseWindowSize + 5);
|
||||
Time expiryTime = Simulator::Now () + MilliSeconds (expiryIntervalMs);
|
||||
m_allocatedNcRaPreambleMap[preambleId] = expiryTime; // create if not exist, update otherwise
|
||||
|
||||
preambleInfo.expiryTime = Simulator::Now () + MilliSeconds (expiryIntervalMs);
|
||||
preambleInfo.rnti = rnti;
|
||||
NS_LOG_INFO ("allocated preamble for NC based RA: preamble " << preambleId << ", RNTI " << preambleInfo.rnti << ", exiryTime " << preambleInfo.expiryTime);
|
||||
m_allocatedNcRaPreambleMap[preambleId] = preambleInfo; // create if not exist, update otherwise
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ private:
|
||||
void DoReleaseLc (uint16_t rnti, uint8_t lcid);
|
||||
void DoUeUpdateConfigurationReq (LteEnbCmacSapProvider::UeConfig params);
|
||||
LteEnbCmacSapProvider::RachConfig DoGetRachConfig ();
|
||||
LteEnbCmacSapProvider::AllocateNcRaPreambleReturnValue DoAllocateNcRaPreamble ();
|
||||
LteEnbCmacSapProvider::AllocateNcRaPreambleReturnValue DoAllocateNcRaPreamble (uint16_t rnti);
|
||||
|
||||
// forwarded from LteMacSapProvider
|
||||
void DoTransmitPdu (LteMacSapProvider::TransmitPduParameters);
|
||||
@@ -238,12 +238,21 @@ private:
|
||||
uint8_t m_raResponseWindowSize;
|
||||
|
||||
/**
|
||||
* map storing as key the random acccess preamble IDs allocated for
|
||||
* non-contention based access, and as value the expiration time of
|
||||
* this allocation (so that stale preambles can be reused).
|
||||
* info associated with a preamble allocated for non-contention based RA
|
||||
*
|
||||
*/
|
||||
std::map<uint8_t, Time> m_allocatedNcRaPreambleMap;
|
||||
struct NcRaPreambleInfo
|
||||
{
|
||||
uint16_t rnti; ///< rnti previously allocated for this non-contention based RA procedure
|
||||
Time expiryTime; ///< value the expiration time of this allocation (so that stale preambles can be reused)
|
||||
};
|
||||
|
||||
/**
|
||||
* map storing as key the random acccess preamble IDs allocated for
|
||||
* non-contention based access, and as value the associated info
|
||||
*
|
||||
*/
|
||||
std::map<uint8_t, NcRaPreambleInfo> m_allocatedNcRaPreambleMap;
|
||||
|
||||
std::map<uint8_t, uint32_t> m_receivedRachPreambleCount;
|
||||
};
|
||||
|
||||
@@ -519,8 +519,10 @@ UeManager::RecvRrcConnectionReconfigurationCompleted (LteRrcSap::RrcConnectionRe
|
||||
EpcX2SapProvider::UeContextReleaseParams ueCtxReleaseParams;
|
||||
ueCtxReleaseParams.oldEnbUeX2apId = m_sourceX2apId;
|
||||
ueCtxReleaseParams.newEnbUeX2apId = m_rnti;
|
||||
ueCtxReleaseParams.sourceCellId = m_sourceCellId;
|
||||
m_rrc->m_x2SapProvider->SendUeContextRelease (ueCtxReleaseParams);
|
||||
SwitchToState (CONNECTED_NORMALLY);
|
||||
break;
|
||||
|
||||
default:
|
||||
NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
|
||||
@@ -1126,6 +1128,15 @@ LteEnbRrc::DoRecvHandoverRequest (EpcX2SapUser::HandoverRequestParams params)
|
||||
NS_ASSERT (params.targetCellId == m_cellId);
|
||||
|
||||
uint16_t rnti = AddUe (UeManager::HANDOVER_JOINING);
|
||||
LteEnbCmacSapProvider::AllocateNcRaPreambleReturnValue anrcrv = m_cmacSapProvider->AllocateNcRaPreamble (rnti);
|
||||
if (anrcrv.valid == false)
|
||||
{
|
||||
NS_LOG_INFO (this << "failed to allocate a preamble for non-contention based RA => cannot accept HO");
|
||||
RemoveUe (rnti);
|
||||
NS_FATAL_ERROR ("should trigger HO Preparation Failure, but it is not implemented");
|
||||
return;
|
||||
}
|
||||
|
||||
Ptr<UeManager> ueManager = GetUeManager (rnti);
|
||||
ueManager->SetSource (params.sourceCellId, params.oldEnbUeX2apId);
|
||||
|
||||
@@ -1139,23 +1150,16 @@ LteEnbRrc::DoRecvHandoverRequest (EpcX2SapUser::HandoverRequestParams params)
|
||||
LteRrcSap::RrcConnectionReconfiguration handoverCommand = ueManager->GetRrcConnectionReconfigurationForHandover ();
|
||||
handoverCommand.haveMobilityControlInfo = true;
|
||||
handoverCommand.mobilityControlInfo.targetPhysCellId = m_cellId;
|
||||
handoverCommand.mobilityControlInfo.haveCarrierFreq = true;
|
||||
handoverCommand.mobilityControlInfo.carrierFreq.dlCarrierFreq = m_dlEarfcn;
|
||||
handoverCommand.mobilityControlInfo.carrierFreq.ulCarrierFreq = m_ulEarfcn;
|
||||
handoverCommand.mobilityControlInfo.haveCarrierBandwidth = true;
|
||||
handoverCommand.mobilityControlInfo.carrierBandwidth.dlBandwidth = m_dlBandwidth;
|
||||
handoverCommand.mobilityControlInfo.carrierBandwidth.ulBandwidth = m_ulBandwidth;
|
||||
handoverCommand.mobilityControlInfo.newUeIdentity = rnti;
|
||||
LteEnbCmacSapProvider::AllocateNcRaPreambleReturnValue anrcrv = m_cmacSapProvider->AllocateNcRaPreamble ();
|
||||
if (anrcrv.valid == true)
|
||||
{
|
||||
handoverCommand.mobilityControlInfo.haveRachConfigDedicated = true;
|
||||
handoverCommand.mobilityControlInfo.rachConfigDedicated.raPreambleIndex = anrcrv.raPreambleId;
|
||||
handoverCommand.mobilityControlInfo.rachConfigDedicated.raPrachMaskIndex = anrcrv.raPrachMaskIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
handoverCommand.mobilityControlInfo.haveRachConfigDedicated = false;
|
||||
}
|
||||
handoverCommand.mobilityControlInfo.haveRachConfigDedicated = true;
|
||||
handoverCommand.mobilityControlInfo.rachConfigDedicated.raPreambleIndex = anrcrv.raPreambleId;
|
||||
handoverCommand.mobilityControlInfo.rachConfigDedicated.raPrachMaskIndex = anrcrv.raPrachMaskIndex;
|
||||
Ptr<Packet> encodedHandoverCommand = m_rrcSapUser->EncodeHandoverCommand (handoverCommand);
|
||||
|
||||
NS_LOG_LOGIC ("Send X2 message: HANDOVER REQUEST ACK");
|
||||
@@ -1410,11 +1414,10 @@ void
|
||||
LteEnbRrc::RemoveSrsConfigurationIndex (uint16_t srcCi)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << srcCi);
|
||||
NS_FATAL_ERROR ("I though this method was unused so far...");
|
||||
std::set<uint16_t>::iterator it = m_ueSrsConfigurationIndexSet.find (srcCi);
|
||||
NS_ASSERT_MSG (it != m_ueSrsConfigurationIndexSet.end (), "request to remove unkwown SRS CI " << srcCi);
|
||||
m_ueSrsConfigurationIndexSet.erase (it);
|
||||
NS_ASSERT (m_srsCurrentPeriodicityId > 1);
|
||||
NS_ASSERT (m_srsCurrentPeriodicityId >= 1 && m_srsCurrentPeriodicityId <= SRS_ENTRIES);
|
||||
if (m_ueSrsConfigurationIndexSet.size () < g_srsPeriodicity[m_srsCurrentPeriodicityId - 1])
|
||||
{
|
||||
// reduce the periodicity
|
||||
|
||||
@@ -755,28 +755,30 @@ LteUePhy::DoSyncronizeWithEnb (uint16_t cellId, uint16_t dlEarfcn)
|
||||
void
|
||||
LteUePhy::DoSetDlBandwidth (uint8_t dlBandwidth)
|
||||
{
|
||||
|
||||
m_dlBandwidth = dlBandwidth;
|
||||
|
||||
int Type0AllocationRbg[4] = {
|
||||
10, // RGB size 1
|
||||
26, // RGB size 2
|
||||
63, // RGB size 3
|
||||
110 // RGB size 4
|
||||
}; // see table 7.1.6.1-1 of 36.213
|
||||
for (int i = 0; i < 4; i++)
|
||||
NS_LOG_FUNCTION (this << (uint32_t) dlBandwidth);
|
||||
if (m_dlBandwidth != dlBandwidth)
|
||||
{
|
||||
if (dlBandwidth < Type0AllocationRbg[i])
|
||||
{
|
||||
m_rbgSize = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ptr<SpectrumValue> noisePsd = LteSpectrumValueHelper::CreateNoisePowerSpectralDensity (m_dlEarfcn, m_dlBandwidth, m_noiseFigure);
|
||||
m_downlinkSpectrumPhy->SetNoisePowerSpectralDensity (noisePsd);
|
||||
m_downlinkSpectrumPhy->GetChannel ()->AddRx (m_downlinkSpectrumPhy);
|
||||
m_dlBandwidth = dlBandwidth;
|
||||
|
||||
int Type0AllocationRbg[4] = {
|
||||
10, // RGB size 1
|
||||
26, // RGB size 2
|
||||
63, // RGB size 3
|
||||
110 // RGB size 4
|
||||
}; // see table 7.1.6.1-1 of 36.213
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (dlBandwidth < Type0AllocationRbg[i])
|
||||
{
|
||||
m_rbgSize = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ptr<SpectrumValue> noisePsd = LteSpectrumValueHelper::CreateNoisePowerSpectralDensity (m_dlEarfcn, m_dlBandwidth, m_noiseFigure);
|
||||
m_downlinkSpectrumPhy->SetNoisePowerSpectralDensity (noisePsd);
|
||||
m_downlinkSpectrumPhy->GetChannel ()->AddRx (m_downlinkSpectrumPhy);
|
||||
}
|
||||
m_dlConfigured = true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user