lte: Handover failure test suite and related code
This commit is contained in:
committed by
Tom Henderson
parent
af1739551c
commit
0dbe96f62d
@@ -335,6 +335,7 @@ set(test_sources
|
||||
test/test-lte-antenna.cc
|
||||
test/test-lte-epc-e2e-data.cc
|
||||
test/test-lte-handover-delay.cc
|
||||
test/test-lte-handover-failure.cc
|
||||
test/test-lte-handover-target.cc
|
||||
test/test-lte-rlc-header.cc
|
||||
test/test-lte-rrc.cc
|
||||
|
||||
@@ -480,6 +480,13 @@ public:
|
||||
* \param params UE data parameters
|
||||
*/
|
||||
virtual void RecvUeData (UeDataParams params) = 0;
|
||||
|
||||
/**
|
||||
* Receive handover cancel function
|
||||
* \param params the receive handover cancel parameters
|
||||
*
|
||||
*/
|
||||
virtual void RecvHandoverCancel (HandoverCancelParams params) = 0;
|
||||
};
|
||||
|
||||
///////////////////////////////////////
|
||||
@@ -701,6 +708,13 @@ public:
|
||||
*/
|
||||
virtual void RecvUeData (UeDataParams params);
|
||||
|
||||
/**
|
||||
* Receive handover cancel function
|
||||
* \param params the receive handover cancel parameters
|
||||
*
|
||||
*/
|
||||
virtual void RecvHandoverCancel (HandoverCancelParams params);
|
||||
|
||||
private:
|
||||
EpcX2SpecificEpcX2SapUser ();
|
||||
C* m_rrc; ///< owner class
|
||||
@@ -773,6 +787,13 @@ EpcX2SpecificEpcX2SapUser<C>::RecvUeData (UeDataParams params)
|
||||
m_rrc->DoRecvUeData (params);
|
||||
}
|
||||
|
||||
template <class C>
|
||||
void
|
||||
EpcX2SpecificEpcX2SapUser<C>::RecvHandoverCancel (HandoverCancelParams params)
|
||||
{
|
||||
m_rrc->DoRecvHandoverCancel (params);
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif // EPC_X2_SAP_H
|
||||
|
||||
@@ -362,6 +362,33 @@ EpcX2::RecvFromX2cSocket (Ptr<Socket> socket)
|
||||
m_x2SapUser->RecvResourceStatusUpdate (params);
|
||||
}
|
||||
}
|
||||
else if (procedureCode == EpcX2Header::HandoverCancel)
|
||||
{
|
||||
if (messageType == EpcX2Header::SuccessfulOutcome)
|
||||
{
|
||||
NS_LOG_LOGIC("Recv X2 message: HANDOVER CANCEL");
|
||||
|
||||
EpcX2HandoverCancelHeader x2HoCancelHeader;
|
||||
packet->RemoveHeader (x2HoCancelHeader);
|
||||
|
||||
NS_LOG_INFO("X2 HandoverCancel header: " << x2HoCancelHeader);
|
||||
|
||||
EpcX2SapUser::HandoverCancelParams params;
|
||||
params.oldEnbUeX2apId = x2HoCancelHeader.GetOldEnbUeX2apId ();
|
||||
params.newEnbUeX2apId = x2HoCancelHeader.GetNewEnbUeX2apId ();
|
||||
params.sourceCellId = cellsInfo->m_localCellIds.at (0);
|
||||
params.targetCellId = cellsInfo->m_remoteCellIds.at (0);
|
||||
params.cause = x2HoCancelHeader.GetCause ();
|
||||
|
||||
NS_LOG_LOGIC("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
|
||||
NS_LOG_LOGIC("newEnbUeX2apId = " << params.newEnbUeX2apId);
|
||||
NS_LOG_LOGIC("sourceCellId = " << params.sourceCellId);
|
||||
NS_LOG_LOGIC("targetCellId = " << params.targetCellId);
|
||||
NS_LOG_LOGIC("cause = " << params.cause);
|
||||
|
||||
m_x2SapUser->RecvHandoverCancel (params);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_ASSERT_MSG (false, "ProcedureCode NOT SUPPORTED!!!");
|
||||
|
||||
@@ -571,11 +571,15 @@ void
|
||||
LteEnbRrc::DoSendReleaseDataRadioBearer (uint64_t imsi, uint16_t rnti, uint8_t bearerId)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << imsi << rnti << (uint16_t) bearerId);
|
||||
Ptr<UeManager> ueManager = GetUeManager (rnti);
|
||||
// Bearer de-activation towards UE
|
||||
ueManager->ReleaseDataRadioBearer (bearerId);
|
||||
// Bearer de-activation indication towards epc-enb application
|
||||
m_s1SapProvider->DoSendReleaseIndication (imsi,rnti,bearerId);
|
||||
|
||||
// check if the RNTI to be removed is not stale
|
||||
if (HasUeManager (rnti)) {
|
||||
Ptr<UeManager> ueManager = GetUeManager (rnti);
|
||||
// Bearer de-activation towards UE
|
||||
ueManager->ReleaseDataRadioBearer (bearerId);
|
||||
// Bearer de-activation indication towards epc-enb application
|
||||
m_s1SapProvider->DoSendReleaseIndication (imsi,rnti,bearerId);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -996,7 +1000,7 @@ UeManager::RecvHandoverPreparationFailure (uint16_t cellId)
|
||||
NS_LOG_INFO ("target eNB sent HO preparation failure, aborting HO");
|
||||
SwitchToState (CONNECTED_NORMALLY);
|
||||
break;
|
||||
case HANDOVER_LEAVING: //case added to tackle HO joining timer expiration
|
||||
case HANDOVER_LEAVING: //case added to tackle HO leaving timer expiration
|
||||
NS_ASSERT (cellId == m_targetCellId);
|
||||
NS_LOG_INFO ("target eNB sent HO preparation failure, aborting HO");
|
||||
m_handoverLeavingTimeout.Cancel ();
|
||||
@@ -1036,6 +1040,14 @@ UeManager::RecvUeContextRelease (EpcX2SapUser::UeContextReleaseParams params)
|
||||
m_handoverLeavingTimeout.Cancel ();
|
||||
}
|
||||
|
||||
void
|
||||
UeManager::RecvHandoverCancel (EpcX2SapUser::HandoverCancelParams params)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
NS_ASSERT_MSG (m_state == HANDOVER_JOINING, "method unexpected in state " << ToString (m_state));
|
||||
m_handoverJoiningTimeout.Cancel ();
|
||||
}
|
||||
|
||||
void
|
||||
UeManager::SendRrcConnectionRelease ()
|
||||
{
|
||||
@@ -2541,17 +2553,20 @@ LteEnbRrc::HandoverJoiningTimeout (uint16_t rnti)
|
||||
"HandoverJoiningTimeout in unexpected state " << ToString (GetUeManager (rnti)->GetState ()));
|
||||
m_handoverFailureJoiningTrace (GetUeManager (rnti)->GetImsi (), rnti,
|
||||
ComponentCarrierToCellId (GetUeManager (rnti)->GetComponentCarrierId ()));
|
||||
/**
|
||||
* When the handover joining timer expires at the target cell,
|
||||
* then notify the source cell to release the RRC connection and
|
||||
* delete the UE context at eNodeB and SGW/PGW. The
|
||||
* HandoverPreparationFailure message is reused to notify the source cell
|
||||
* through the X2 interface instead of creating a new message.
|
||||
*/
|
||||
Ptr<UeManager> ueManager = GetUeManager (rnti);
|
||||
EpcX2Sap::HandoverPreparationFailureParams msg = ueManager->BuildHoPrepFailMsg ();
|
||||
m_x2SapProvider->SendHandoverPreparationFailure (msg);
|
||||
RemoveUe (rnti);
|
||||
// check if the RNTI to be removed is not stale
|
||||
if (HasUeManager (rnti)) {
|
||||
/**
|
||||
* When the handover joining timer expires at the target cell,
|
||||
* then notify the source cell to release the RRC connection and
|
||||
* delete the UE context at eNodeB and SGW/PGW. The
|
||||
* HandoverPreparationFailure message is reused to notify the source cell
|
||||
* through the X2 interface instead of creating a new message.
|
||||
*/
|
||||
Ptr<UeManager> ueManager = GetUeManager (rnti);
|
||||
EpcX2Sap::HandoverPreparationFailureParams msg = ueManager->BuildHoPrepFailMsg ();
|
||||
m_x2SapProvider->SendHandoverPreparationFailure (msg);
|
||||
RemoveUe (rnti);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2562,15 +2577,18 @@ LteEnbRrc::HandoverLeavingTimeout (uint16_t rnti)
|
||||
"HandoverLeavingTimeout in unexpected state " << ToString (GetUeManager (rnti)->GetState ()));
|
||||
m_handoverFailureLeavingTrace (GetUeManager (rnti)->GetImsi (), rnti,
|
||||
ComponentCarrierToCellId (GetUeManager (rnti)->GetComponentCarrierId ()));
|
||||
/**
|
||||
* Send HO cancel msg to the target eNB and release the RRC connection
|
||||
* with the UE and also delete UE context at the source eNB and bearer
|
||||
* info at SGW and PGW.
|
||||
*/
|
||||
Ptr<UeManager> ueManager = GetUeManager (rnti);
|
||||
EpcX2Sap::HandoverCancelParams msg = ueManager->BuildHoCancelMsg ();
|
||||
m_x2SapProvider->SendHandoverCancel (msg);
|
||||
ueManager->SendRrcConnectionRelease ();
|
||||
// check if the RNTI to be removed is not stale
|
||||
if (HasUeManager (rnti)) {
|
||||
/**
|
||||
* Send HO cancel msg to the target eNB and release the RRC connection
|
||||
* with the UE and also delete UE context at the source eNB and bearer
|
||||
* info at SGW and PGW.
|
||||
*/
|
||||
Ptr<UeManager> ueManager = GetUeManager (rnti);
|
||||
EpcX2Sap::HandoverCancelParams msg = ueManager->BuildHoCancelMsg ();
|
||||
m_x2SapProvider->SendHandoverCancel (msg);
|
||||
ueManager->SendRrcConnectionRelease ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2646,25 +2664,31 @@ void
|
||||
LteEnbRrc::DoRecvIdealUeContextRemoveRequest (uint16_t rnti)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << rnti);
|
||||
Ptr<UeManager> ueManager = GetUeManager (rnti);
|
||||
|
||||
if (ueManager->GetState () == UeManager::HANDOVER_JOINING)
|
||||
// check if the RNTI to be removed is not stale
|
||||
if (HasUeManager (rnti))
|
||||
{
|
||||
m_handoverFailureMaxRachTrace (GetUeManager (rnti)->GetImsi (), rnti,
|
||||
ComponentCarrierToCellId (GetUeManager (rnti)->GetComponentCarrierId ()));
|
||||
/**
|
||||
* During the HO, when the RACH failure due to the maximum number of
|
||||
* re-attempts is reached the UE request the target eNB to deletes its
|
||||
* context. Upon which, the target eNB sends handover preparation
|
||||
* failure to the source eNB.
|
||||
*/
|
||||
EpcX2Sap::HandoverPreparationFailureParams msg = ueManager->BuildHoPrepFailMsg ();
|
||||
m_x2SapProvider->SendHandoverPreparationFailure (msg);
|
||||
Ptr<UeManager> ueManager = GetUeManager (rnti);
|
||||
|
||||
if (ueManager->GetState () == UeManager::HANDOVER_JOINING)
|
||||
{
|
||||
m_handoverFailureMaxRachTrace (GetUeManager (rnti)->GetImsi (), rnti,
|
||||
ComponentCarrierToCellId (GetUeManager (rnti)->GetComponentCarrierId ()));
|
||||
/**
|
||||
* During the HO, when the RACH failure due to the maximum number of
|
||||
* re-attempts is reached the UE request the target eNB to deletes its
|
||||
* context. Upon which, the target eNB sends handover preparation
|
||||
* failure to the source eNB.
|
||||
*/
|
||||
EpcX2Sap::HandoverPreparationFailureParams msg = ueManager->BuildHoPrepFailMsg ();
|
||||
m_x2SapProvider->SendHandoverPreparationFailure (msg);
|
||||
}
|
||||
|
||||
GetUeManager (rnti)->RecvIdealUeContextRemoveRequest (rnti);
|
||||
// delete the UE context at the eNB
|
||||
RemoveUe (rnti);
|
||||
}
|
||||
|
||||
GetUeManager (rnti)->RecvIdealUeContextRemoveRequest (rnti);
|
||||
//delete the UE context at the eNB
|
||||
RemoveUe (rnti);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2695,7 +2719,8 @@ LteEnbRrc::DoRecvHandoverRequest (EpcX2SapUser::HandoverRequestParams req)
|
||||
NS_LOG_LOGIC ("targetCellId = " << req.targetCellId);
|
||||
NS_LOG_LOGIC ("mmeUeS1apId = " << req.mmeUeS1apId);
|
||||
|
||||
if (m_admitHandoverRequest == false)
|
||||
// if no SRS index is available, then do not accept the handover
|
||||
if (m_admitHandoverRequest == false || IsMaxSrsReached())
|
||||
{
|
||||
NS_LOG_INFO ("rejecting handover request from cellId " << req.sourceCellId);
|
||||
EpcX2Sap::HandoverPreparationFailureParams res;
|
||||
@@ -2805,8 +2830,12 @@ LteEnbRrc::DoRecvHandoverPreparationFailure (EpcX2SapUser::HandoverPreparationFa
|
||||
NS_LOG_LOGIC ("criticalityDiagnostics = " << params.criticalityDiagnostics);
|
||||
|
||||
uint16_t rnti = params.oldEnbUeX2apId;
|
||||
Ptr<UeManager> ueManager = GetUeManager (rnti);
|
||||
ueManager->RecvHandoverPreparationFailure (params.targetCellId);
|
||||
|
||||
// check if the RNTI is not stale
|
||||
if (HasUeManager (rnti)) {
|
||||
Ptr<UeManager> ueManager = GetUeManager (rnti);
|
||||
ueManager->RecvHandoverPreparationFailure (params.targetCellId);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2821,8 +2850,13 @@ LteEnbRrc::DoRecvSnStatusTransfer (EpcX2SapUser::SnStatusTransferParams params)
|
||||
NS_LOG_LOGIC ("erabsSubjectToStatusTransferList size = " << params.erabsSubjectToStatusTransferList.size ());
|
||||
|
||||
uint16_t rnti = params.newEnbUeX2apId;
|
||||
Ptr<UeManager> ueManager = GetUeManager (rnti);
|
||||
ueManager->RecvSnStatusTransfer (params);
|
||||
|
||||
// check if the RNTI to receive SN transfer for is not stale
|
||||
if (HasUeManager (rnti))
|
||||
{
|
||||
Ptr<UeManager> ueManager = GetUeManager (rnti);
|
||||
ueManager->RecvSnStatusTransfer (params);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2836,8 +2870,12 @@ LteEnbRrc::DoRecvUeContextRelease (EpcX2SapUser::UeContextReleaseParams params)
|
||||
NS_LOG_LOGIC ("newEnbUeX2apId = " << params.newEnbUeX2apId);
|
||||
|
||||
uint16_t rnti = params.oldEnbUeX2apId;
|
||||
GetUeManager (rnti)->RecvUeContextRelease (params);
|
||||
RemoveUe (rnti);
|
||||
|
||||
// check if the RNTI to be removed is not stale
|
||||
if (HasUeManager (rnti)) {
|
||||
GetUeManager (rnti)->RecvUeContextRelease (params);
|
||||
RemoveUe (rnti);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2889,11 +2927,37 @@ LteEnbRrc::DoRecvUeData (EpcX2SapUser::UeDataParams params)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LteEnbRrc::DoRecvHandoverCancel (EpcX2SapUser::HandoverCancelParams params)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
NS_LOG_LOGIC ("Recv X2 message: HANDOVER CANCEL");
|
||||
|
||||
NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
|
||||
NS_LOG_LOGIC ("newEnbUeX2apId = " << params.newEnbUeX2apId);
|
||||
NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
|
||||
NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
|
||||
NS_LOG_LOGIC ("cause = " << params.cause);
|
||||
|
||||
uint16_t rnti = params.newEnbUeX2apId;
|
||||
if (HasUeManager (rnti))
|
||||
{
|
||||
Ptr<UeManager> ueManager = GetUeManager (rnti);
|
||||
ueManager->RecvHandoverCancel (params);
|
||||
GetUeManager (rnti)->RecvIdealUeContextRemoveRequest (rnti);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t
|
||||
LteEnbRrc::DoAllocateTemporaryCellRnti (uint8_t componentCarrierId)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << +componentCarrierId);
|
||||
// if no SRS index is available, then do not create a new UE context.
|
||||
if(IsMaxSrsReached())
|
||||
{
|
||||
return 0; // return 0 since new RNTI was not assigned for the received preamble
|
||||
}
|
||||
return AddUe (UeManager::INITIAL_RANDOM_ACCESS, componentCarrierId);
|
||||
}
|
||||
|
||||
@@ -3245,7 +3309,23 @@ LteEnbRrc::RemoveSrsConfigurationIndex (uint16_t srcCi)
|
||||
m_ueSrsConfigurationIndexSet.erase (it);
|
||||
}
|
||||
|
||||
uint8_t
|
||||
bool
|
||||
LteEnbRrc::IsMaxSrsReached ()
|
||||
{
|
||||
NS_ASSERT(m_srsCurrentPeriodicityId > 0);
|
||||
NS_ASSERT(m_srsCurrentPeriodicityId < SRS_ENTRIES);
|
||||
NS_LOG_DEBUG(this << " SRS p " << g_srsPeriodicity[m_srsCurrentPeriodicityId] << " set " << m_ueSrsConfigurationIndexSet.size ());
|
||||
if (m_ueSrsConfigurationIndexSet.size () >= g_srsPeriodicity[m_srsCurrentPeriodicityId])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t
|
||||
LteEnbRrc::GetLogicalChannelGroup (EpsBearer bearer)
|
||||
{
|
||||
if (bearer.IsGbr ())
|
||||
|
||||
@@ -266,6 +266,12 @@ public:
|
||||
*/
|
||||
void RecvUeContextRelease (EpcX2SapUser::UeContextReleaseParams params);
|
||||
|
||||
/**
|
||||
* Take the necessary actions in response to the reception of an X2 UE CONTEXT RELEASE message
|
||||
*
|
||||
* \param params the SN STATUS
|
||||
*/
|
||||
void RecvHandoverCancel (EpcX2SapUser::HandoverCancelParams params);
|
||||
|
||||
// METHODS FORWARDED FROM ENB RRC SAP ///////////////////////////////////////
|
||||
|
||||
@@ -1276,6 +1282,13 @@ private:
|
||||
* \param params EpcX2SapUser::UeDataParams
|
||||
*/
|
||||
void DoRecvUeData (EpcX2SapUser::UeDataParams params);
|
||||
/**
|
||||
* Receive Handover Cancel function.
|
||||
*
|
||||
* \param params EpcX2SapUser::HandoverCancelParams
|
||||
*/
|
||||
void DoRecvHandoverCancel (EpcX2SapUser::HandoverCancelParams params);
|
||||
|
||||
|
||||
// CMAC SAP methods
|
||||
|
||||
@@ -1474,7 +1487,10 @@ private:
|
||||
*/
|
||||
void RemoveSrsConfigurationIndex (uint16_t srcCi);
|
||||
|
||||
|
||||
/**
|
||||
* \return true if all the SRS indices are assigned to UEs
|
||||
*/
|
||||
bool IsMaxSrsReached();
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -299,9 +299,11 @@ LteEnbRrcProtocolIdeal::SetUeRrcSapProvider (uint16_t rnti, LteUeRrcSapProvider*
|
||||
{
|
||||
std::map<uint16_t, LteUeRrcSapProvider*>::iterator it;
|
||||
it = m_enbRrcSapProviderMap.find (rnti);
|
||||
NS_ASSERT_MSG (it != m_enbRrcSapProviderMap.end (), "Cell id " << m_cellId
|
||||
<< " could not find RNTI = " << rnti);
|
||||
it->second = p;
|
||||
// assign UE RRC only if the RNTI is found at eNB
|
||||
if (it != m_enbRrcSapProviderMap.end ())
|
||||
{
|
||||
it->second = p;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -448,7 +448,6 @@ LteEnbRrcProtocolReal::SetUeRrcSapProvider (uint16_t rnti, LteUeRrcSapProvider*
|
||||
{
|
||||
std::map<uint16_t, LteUeRrcSapProvider*>::iterator it;
|
||||
it = m_enbRrcSapProviderMap.find (rnti);
|
||||
// TODO: remove after merge of ho_failure branch
|
||||
// assign UE RRC only if the RNTI is found at eNB
|
||||
if (it != m_enbRrcSapProviderMap.end ())
|
||||
{
|
||||
|
||||
401
src/lte/test/test-lte-handover-failure.cc
Normal file
401
src/lte/test/test-lte-handover-failure.cc
Normal file
@@ -0,0 +1,401 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2013 Magister Solutions (original test-lte-handover-delay.cc)
|
||||
* Copyright (c) 2021 University of Washington (handover failure cases)
|
||||
*
|
||||
* 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: Sachin Nayak <sachinnn@uw.edu>
|
||||
*/
|
||||
|
||||
#include <ns3/test.h>
|
||||
|
||||
#include <ns3/log.h>
|
||||
#include <ns3/nstime.h>
|
||||
#include <ns3/callback.h>
|
||||
#include <ns3/config.h>
|
||||
#include <ns3/boolean.h>
|
||||
#include <ns3/simulator.h>
|
||||
|
||||
#include <ns3/node-container.h>
|
||||
#include <ns3/net-device-container.h>
|
||||
#include <ns3/ipv4-interface-container.h>
|
||||
|
||||
#include <ns3/lte-helper.h>
|
||||
#include <ns3/point-to-point-epc-helper.h>
|
||||
#include <ns3/internet-stack-helper.h>
|
||||
#include <ns3/point-to-point-helper.h>
|
||||
#include <ns3/ipv4-address-helper.h>
|
||||
#include <ns3/ipv4-static-routing-helper.h>
|
||||
#include <ns3/mobility-helper.h>
|
||||
|
||||
#include <ns3/data-rate.h>
|
||||
#include <ns3/ipv4-static-routing.h>
|
||||
#include <ns3/position-allocator.h>
|
||||
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("LteHandoverFailureTest");
|
||||
|
||||
/**
|
||||
* \ingroup lte-test
|
||||
* \ingroup tests
|
||||
*
|
||||
* \brief Verifying that a handover failure occurs due to various causes
|
||||
*
|
||||
* Handover failure cases dealt with in this test include the below.
|
||||
*
|
||||
* 1. Handover failure due to max random access channel (RACH) attempts from UE to target eNodeB
|
||||
* 2. Handover failure due to non-allocation of non-contention preamble to UE at target eNodeB
|
||||
* 3. Handover failure due to HANDOVER JOINING timeout (3 cases)
|
||||
* 4. Handover failure due to HANDOVER LEAVING timeout (3 cases)
|
||||
*
|
||||
* \sa ns3::LteHandoverFailureTestCase
|
||||
*/
|
||||
class LteHandoverFailureTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param name the name of the test case, to be displayed in the test result
|
||||
* \param useIdealRrc if true, use the ideal RRC
|
||||
* \param handoverTime the time of handover
|
||||
* \param simulationDuration duration of the simulation
|
||||
* \param numberOfRaPreambles number of random access preambles available for contention based RACH process
|
||||
* number of non-contention preambles available for handover = (64 - numberRaPreambles)
|
||||
* as numberOfRaPreambles out of the max 64 are reserved contention based RACH process
|
||||
* \param preambleTransMax maximum number of random access preamble transmissions from UE to eNodeB
|
||||
* \param raResponseWindowSize window length for reception of random access response (RAR)
|
||||
* \param handoverJoiningTimeout time before which RRC RECONFIGURATION COMPLETE must be received
|
||||
at target eNodeB after it receives a handover request
|
||||
Else, the UE context is destroyed in the RRC.
|
||||
Timeout can occur before different stages as below.
|
||||
i. Reception of RRC CONNECTION RECONFIGURATION at source eNodeB
|
||||
ii. Non-contention random access procedure from UE to target eNodeB
|
||||
iii. Reception of RRC CONNECTION RECONFIGURATION COMPLETE at target eNodeB
|
||||
* \param handoverLeavingTimeout time before which source eNodeB must receive a UE context release
|
||||
from target eNodeB or RRC CONNECTION RESTABLISHMENT from UE
|
||||
after issuing a handover request
|
||||
Else, the UE context is destroyed in the RRC.
|
||||
Timeout can occur before any of the cases in HANDOVER JOINING TIMEOUT
|
||||
* \param targeteNodeBPosition position of the target eNodeB
|
||||
*/
|
||||
LteHandoverFailureTestCase (std::string name,
|
||||
bool useIdealRrc,
|
||||
Time handoverTime,
|
||||
Time simulationDuration,
|
||||
uint8_t numberOfRaPreambles,
|
||||
uint8_t preambleTransMax,
|
||||
uint8_t raResponseWindowSize,
|
||||
Time handoverJoiningTimeout,
|
||||
Time handoverLeavingTimeout,
|
||||
uint16_t targeteNodeBPosition)
|
||||
: TestCase (name),
|
||||
m_useIdealRrc (useIdealRrc),
|
||||
m_handoverTime (handoverTime),
|
||||
m_simulationDuration (simulationDuration),
|
||||
m_numberOfRaPreambles (numberOfRaPreambles),
|
||||
m_preambleTransMax (preambleTransMax),
|
||||
m_raResponseWindowSize (raResponseWindowSize),
|
||||
m_handoverJoiningTimeout (handoverJoiningTimeout),
|
||||
m_handoverLeavingTimeout (handoverLeavingTimeout),
|
||||
m_targeteNodeBPosition (targeteNodeBPosition),
|
||||
m_hasHandoverFailureOccured (false)
|
||||
{}
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief Run a simulation of a two eNodeB network using the parameters
|
||||
* provided to the constructor function.
|
||||
*/
|
||||
void DoRun () override;
|
||||
|
||||
/**
|
||||
* \brief Called at the end of simulation and verifies that a handover
|
||||
* and a handover failure has occured in the simulation.
|
||||
*/
|
||||
void DoTeardown () override;
|
||||
|
||||
/**
|
||||
* UE handover start callback function to indicate start of handover
|
||||
* \param context the context string
|
||||
* \param imsi the IMSI
|
||||
* \param sourceCellId the source cell ID
|
||||
* \param rnti the RNTI
|
||||
* \param targetCellId the target cell ID
|
||||
*/
|
||||
void UeHandoverStartCallback (std::string context, uint64_t imsi,
|
||||
uint16_t sourceCellId, uint16_t rnti, uint16_t targetCellId);
|
||||
|
||||
/**
|
||||
* Handover failure callback due to maximum RACH transmissions reached from UE to target eNodeB
|
||||
* \param context the context string
|
||||
* \param imsi the IMSI
|
||||
* \param rnti the RNTI
|
||||
* \param targetCellId the target cell ID
|
||||
*/
|
||||
void HandoverFailureMaxRach (std::string context, uint64_t imsi,
|
||||
uint16_t rnti, uint16_t targetCellId);
|
||||
|
||||
/**
|
||||
* Handover failure callback due to non-allocation of non-contention preamble at target eNodeB
|
||||
* \param context the context string
|
||||
* \param imsi the IMSI
|
||||
* \param rnti the RNTI
|
||||
* \param targetCellId the target cell ID
|
||||
*/
|
||||
void HandoverFailureNoPreamble (std::string context, uint64_t imsi,
|
||||
uint16_t rnti, uint16_t targetCellId);
|
||||
|
||||
/**
|
||||
* Handover failure callback due to handover joining timeout at target eNodeB
|
||||
* \param context the context string
|
||||
* \param imsi the IMSI
|
||||
* \param rnti the RNTI
|
||||
* \param targetCellId the target cell ID
|
||||
*/
|
||||
void HandoverFailureJoining (std::string context, uint64_t imsi,
|
||||
uint16_t rnti, uint16_t targetCellId);
|
||||
|
||||
/**
|
||||
* Handover failure callback due to handover leaving timeout at source eNodeB
|
||||
* \param context the context string
|
||||
* \param imsi the IMSI
|
||||
* \param rnti the RNTI
|
||||
* \param targetCellId the target cell ID
|
||||
*/
|
||||
void HandoverFailureLeaving (std::string context, uint64_t imsi,
|
||||
uint16_t rnti, uint16_t targetCellId);
|
||||
|
||||
bool m_useIdealRrc; ///< use ideal RRC?
|
||||
Time m_handoverTime; ///< handover time
|
||||
Time m_simulationDuration; ///< the simulation duration
|
||||
uint8_t m_numberOfRaPreambles; ///< number of random access preambles for contention based RACH process
|
||||
uint8_t m_preambleTransMax; ///< max number of RACH preambles possible from UE to eNodeB
|
||||
uint8_t m_raResponseWindowSize; ///< window length for reception of RAR
|
||||
Time m_handoverJoiningTimeout; ///< handover joining timeout duration at target eNodeB
|
||||
Time m_handoverLeavingTimeout; ///< handover leaving timeout duration at source eNodeB
|
||||
uint16_t m_targeteNodeBPosition; ///< position of the target eNodeB
|
||||
bool m_hasHandoverFailureOccured; ///< has handover failure occured in simulation
|
||||
|
||||
}; // end of class LteHandoverFailureTestCase
|
||||
|
||||
|
||||
void
|
||||
LteHandoverFailureTestCase::DoRun ()
|
||||
{
|
||||
|
||||
NS_LOG_INFO (this << " " << GetName ());
|
||||
|
||||
/*
|
||||
* Helpers.
|
||||
*/
|
||||
auto epcHelper = CreateObject<PointToPointEpcHelper> ();
|
||||
|
||||
auto lteHelper = CreateObject<LteHelper> ();
|
||||
lteHelper->SetEpcHelper (epcHelper);
|
||||
|
||||
// Set parameters for helpers based on the test case parameters.
|
||||
lteHelper->SetAttribute ("UseIdealRrc", BooleanValue (m_useIdealRrc));
|
||||
Config::SetDefault ("ns3::LteEnbMac::NumberOfRaPreambles", UintegerValue (m_numberOfRaPreambles));
|
||||
Config::SetDefault ("ns3::LteEnbMac::PreambleTransMax", UintegerValue (m_preambleTransMax));
|
||||
Config::SetDefault ("ns3::LteEnbMac::RaResponseWindowSize", UintegerValue (m_raResponseWindowSize));
|
||||
Config::SetDefault ("ns3::LteEnbRrc::HandoverJoiningTimeoutDuration", TimeValue (m_handoverJoiningTimeout));
|
||||
Config::SetDefault ("ns3::LteEnbRrc::HandoverLeavingTimeoutDuration", TimeValue (m_handoverLeavingTimeout));
|
||||
|
||||
// Set PHY model to drastically decrease with distance.
|
||||
lteHelper->SetPathlossModelType (TypeId::LookupByName ("ns3::LogDistancePropagationLossModel"));
|
||||
lteHelper->SetPathlossModelAttribute ("Exponent", DoubleValue (3.5));
|
||||
lteHelper->SetPathlossModelAttribute ("ReferenceLoss", DoubleValue (35));
|
||||
/*
|
||||
* Physical layer.
|
||||
*
|
||||
* eNodeB 0 UE eNodeB 1
|
||||
*
|
||||
* x ----------------------- x -------------------------- x
|
||||
* 200 m m_targeteNodeBPosition
|
||||
* source target
|
||||
*/
|
||||
// Create nodes.
|
||||
NodeContainer enbNodes;
|
||||
enbNodes.Create (2);
|
||||
auto ueNode = CreateObject<Node> ();
|
||||
|
||||
// Setup mobility
|
||||
auto posAlloc = CreateObject<ListPositionAllocator> ();
|
||||
posAlloc->Add (Vector (0, 0, 0));
|
||||
posAlloc->Add (Vector (m_targeteNodeBPosition, 0, 0));
|
||||
posAlloc->Add (Vector (200, 0, 0));
|
||||
|
||||
MobilityHelper mobilityHelper;
|
||||
mobilityHelper.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
|
||||
mobilityHelper.SetPositionAllocator (posAlloc);
|
||||
mobilityHelper.Install (enbNodes);
|
||||
mobilityHelper.Install (ueNode);
|
||||
|
||||
/*
|
||||
* Link layer.
|
||||
*/
|
||||
auto enbDevs = lteHelper->InstallEnbDevice (enbNodes);
|
||||
auto ueDev = lteHelper->InstallUeDevice (ueNode).Get (0);
|
||||
|
||||
/*
|
||||
* Network layer.
|
||||
*/
|
||||
InternetStackHelper inetStackHelper;
|
||||
inetStackHelper.Install (ueNode);
|
||||
Ipv4InterfaceContainer ueIfs;
|
||||
ueIfs = epcHelper->AssignUeIpv4Address (ueDev);
|
||||
|
||||
// Setup traces.
|
||||
Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/HandoverStart",
|
||||
MakeCallback (&LteHandoverFailureTestCase::UeHandoverStartCallback, this));
|
||||
Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/HandoverFailureMaxRach",
|
||||
MakeCallback (&LteHandoverFailureTestCase::HandoverFailureMaxRach, this));
|
||||
Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/HandoverFailureNoPreamble",
|
||||
MakeCallback (&LteHandoverFailureTestCase::HandoverFailureNoPreamble, this));
|
||||
Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/HandoverFailureJoining",
|
||||
MakeCallback (&LteHandoverFailureTestCase::HandoverFailureJoining, this));
|
||||
Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/HandoverFailureLeaving",
|
||||
MakeCallback (&LteHandoverFailureTestCase::HandoverFailureLeaving, this));
|
||||
|
||||
// Prepare handover.
|
||||
lteHelper->AddX2Interface (enbNodes);
|
||||
lteHelper->Attach (ueDev, enbDevs.Get (0));
|
||||
lteHelper->HandoverRequest (m_handoverTime, ueDev, enbDevs.Get (0), enbDevs.Get (1));
|
||||
|
||||
// Run simulation.
|
||||
Simulator::Stop (m_simulationDuration);
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
|
||||
} // end of void LteHandoverFailureTestCase::DoRun ()
|
||||
|
||||
|
||||
void
|
||||
LteHandoverFailureTestCase::UeHandoverStartCallback (std::string context, uint64_t imsi,
|
||||
uint16_t sourceCellId, uint16_t rnti, uint16_t targetCellId)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << " " << context << " IMSI-" << imsi << " sourceCellID-" << sourceCellId << " RNTI-"<< rnti << " targetCellID-" << targetCellId);
|
||||
NS_LOG_INFO ("HANDOVER COMMAND received through at UE " << imsi << " to handover from " << sourceCellId << " to " << targetCellId);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LteHandoverFailureTestCase::HandoverFailureMaxRach (std::string context, uint64_t imsi,
|
||||
uint16_t rnti, uint16_t targetCellId)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << context << imsi << rnti << targetCellId);
|
||||
m_hasHandoverFailureOccured = true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LteHandoverFailureTestCase::HandoverFailureNoPreamble (std::string context, uint64_t imsi,
|
||||
uint16_t rnti, uint16_t targetCellId)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << context << imsi << rnti << targetCellId);
|
||||
m_hasHandoverFailureOccured = true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LteHandoverFailureTestCase::HandoverFailureJoining (std::string context, uint64_t imsi,
|
||||
uint16_t rnti, uint16_t targetCellId)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << context << imsi << rnti << targetCellId);
|
||||
m_hasHandoverFailureOccured = true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LteHandoverFailureTestCase::HandoverFailureLeaving (std::string context, uint64_t imsi,
|
||||
uint16_t rnti, uint16_t targetCellId)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << context << imsi << rnti << targetCellId);
|
||||
m_hasHandoverFailureOccured = true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LteHandoverFailureTestCase::DoTeardown ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
NS_TEST_ASSERT_MSG_EQ (m_hasHandoverFailureOccured, true, "Handover failure did not occur");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup lte-test
|
||||
* \ingroup tests
|
||||
*
|
||||
* \brief Lte Handover Failure Test Suite
|
||||
*/
|
||||
static class LteHandoverFailureTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
LteHandoverFailureTestSuite ()
|
||||
: TestSuite ("lte-handover-failure", TestSuite::SYSTEM)
|
||||
{
|
||||
LogLevel logLevel = (LogLevel) (LOG_PREFIX_TIME | LOG_LEVEL_INFO);
|
||||
LogComponentEnable ("LteHandoverFailureTest", logLevel);
|
||||
LogComponentEnable ("LteEnbRrc", logLevel);
|
||||
LogComponentEnable ("LteEnbMac", logLevel);
|
||||
LogComponentEnable ("LteUeRrc", logLevel);
|
||||
LogComponentEnable ("EpcX2", logLevel);
|
||||
|
||||
// Argument sequence for all test cases: useIdealRrc, handoverTime, simulationDuration, numberOfRaPreambles, preambleTransMax, raResponseWindowSize,
|
||||
// handoverJoiningTimeout, handoverLeavingTimeout
|
||||
|
||||
// Test cases for REAL RRC protocol
|
||||
AddTestCase (new LteHandoverFailureTestCase ("REAL Handover failure due to maximum RACH transmissions reached from UE to target eNodeB",
|
||||
false, Seconds (0.200), Seconds (0.300), 52, 3, 3, MilliSeconds(200), MilliSeconds(500), 2500), TestCase::QUICK);
|
||||
AddTestCase (new LteHandoverFailureTestCase ("REAL Handover failure due to non-allocation of non-contention preamble at target eNodeB due to max number reached",
|
||||
false, Seconds (0.100), Seconds (0.200), 64, 50, 3, MilliSeconds(200), MilliSeconds(500), 1500), TestCase::QUICK);
|
||||
AddTestCase (new LteHandoverFailureTestCase ("REAL Handover failure due to HANDOVER JOINING timeout before reception of RRC CONNECTION RECONFIGURATION at source eNodeB",
|
||||
false, Seconds (0.100), Seconds (0.200), 52, 50, 3, MilliSeconds(0), MilliSeconds(500), 1500), TestCase::QUICK);
|
||||
AddTestCase (new LteHandoverFailureTestCase ("REAL Handover failure due to HANDOVER JOINING timeout before completion of non-contention RACH process to target eNodeB",
|
||||
false, Seconds (0.100), Seconds (0.200), 52, 50, 3, MilliSeconds(15), MilliSeconds(500), 1500), TestCase::QUICK);
|
||||
AddTestCase (new LteHandoverFailureTestCase ("REAL Handover failure due to HANDOVER JOINING timeout before reception of RRC CONNECTION RECONFIGURATION COMPLETE at target eNodeB",
|
||||
false, Seconds (0.100), Seconds (0.200), 52, 50, 3, MilliSeconds(18), MilliSeconds(500), 500), TestCase::QUICK);
|
||||
AddTestCase (new LteHandoverFailureTestCase ("REAL Handover failure due to HANDOVER LEAVING timeout before reception of RRC CONNECTION RECONFIGURATION at source eNodeB",
|
||||
false, Seconds (0.100), Seconds (0.200), 52, 50, 3, MilliSeconds(200), MilliSeconds(0), 1500), TestCase::QUICK);
|
||||
AddTestCase (new LteHandoverFailureTestCase ("REAL Handover failure due to HANDOVER LEAVING timeout before completion of non-contention RACH process to target eNodeB",
|
||||
false, Seconds (0.100), Seconds (0.200), 52, 50, 3, MilliSeconds(200), MilliSeconds(15), 1500), TestCase::QUICK);
|
||||
AddTestCase (new LteHandoverFailureTestCase ("REAL Handover failure due to HANDOVER LEAVING timeout before reception of RRC CONNECTION RECONFIGURATION COMPLETE at target eNodeB",
|
||||
false, Seconds (0.100), Seconds (0.200), 52, 50, 3, MilliSeconds(200), MilliSeconds(18), 500), TestCase::QUICK);
|
||||
|
||||
// Test cases for IDEAL RRC protocol
|
||||
AddTestCase (new LteHandoverFailureTestCase ("IDEAL Handover failure due to maximum RACH transmissions reached from UE to target eNodeB",
|
||||
true, Seconds (0.100), Seconds (0.200), 52, 3, 3, MilliSeconds(200), MilliSeconds(500), 1500), TestCase::QUICK);
|
||||
AddTestCase (new LteHandoverFailureTestCase ("IDEAL Handover failure due to non-allocation of non-contention preamble at target eNodeB due to max number reached",
|
||||
true, Seconds (0.100), Seconds (0.200), 64, 50, 3, MilliSeconds(200), MilliSeconds(500), 1500), TestCase::QUICK);
|
||||
AddTestCase (new LteHandoverFailureTestCase ("IDEAL Handover failure due to HANDOVER JOINING timeout before reception of RRC CONNECTION RECONFIGURATION at source eNodeB",
|
||||
true, Seconds (0.100), Seconds (0.200), 52, 50, 3, MilliSeconds(0), MilliSeconds(500), 1500), TestCase::QUICK);
|
||||
AddTestCase (new LteHandoverFailureTestCase ("IDEAL Handover failure due to HANDOVER JOINING timeout before completion of non-contention RACH process to target eNodeB",
|
||||
true, Seconds (0.100), Seconds (0.200), 52, 50, 3, MilliSeconds(10), MilliSeconds(500), 1500), TestCase::QUICK);
|
||||
AddTestCase (new LteHandoverFailureTestCase ("IDEAL Handover failure due to HANDOVER JOINING timeout before reception of RRC CONNECTION RECONFIGURATION COMPLETE at target eNodeB",
|
||||
true, Seconds (0.100), Seconds (0.200), 52, 50, 3, MilliSeconds(4), MilliSeconds(500), 500), TestCase::QUICK);
|
||||
AddTestCase (new LteHandoverFailureTestCase ("IDEAL Handover failure due to HANDOVER LEAVING timeout before reception of RRC CONNECTION RECONFIGURATION at source eNodeB",
|
||||
true, Seconds (0.100), Seconds (0.200), 52, 50, 3, MilliSeconds(500), MilliSeconds(0), 1500), TestCase::QUICK);
|
||||
AddTestCase (new LteHandoverFailureTestCase ("IDEAL Handover failure due to HANDOVER LEAVING timeout before completion of non-contention RACH process to target eNodeB",
|
||||
true, Seconds (0.100), Seconds (0.200), 52, 50, 3, MilliSeconds(500), MilliSeconds(10), 1500), TestCase::QUICK);
|
||||
AddTestCase (new LteHandoverFailureTestCase ("IDEAL Handover failure due to HANDOVER LEAVING timeout before reception of RRC CONNECTION RECONFIGURATION COMPLETE at target eNodeB",
|
||||
true, Seconds (0.100), Seconds (0.200), 52, 50, 3, MilliSeconds(500), MilliSeconds(4), 500), TestCase::QUICK);
|
||||
|
||||
|
||||
}
|
||||
} g_lteHandoverFailureTestSuite; ///< end of LteHandoverFailureTestSuite ()
|
||||
Reference in New Issue
Block a user