From b312048df08ff6dabd1de5a51ebc602fbd6e8df6 Mon Sep 17 00:00:00 2001 From: Nicola Baldo Date: Fri, 7 Dec 2012 19:57:21 +0100 Subject: [PATCH] LteEnbRrc send/recv X2 sn status transfer --- src/lte/model/lte-enb-rrc.cc | 96 +++++++++++++++++++++++++++--------- src/lte/model/lte-enb-rrc.h | 17 ++++--- src/lte/model/lte-pdcp.cc | 16 ++++++ src/lte/model/lte-pdcp.h | 24 +++++++++ 4 files changed, 122 insertions(+), 31 deletions(-) diff --git a/src/lte/model/lte-enb-rrc.cc b/src/lte/model/lte-enb-rrc.cc index 419c41a51..3cff7a346 100644 --- a/src/lte/model/lte-enb-rrc.cc +++ b/src/lte/model/lte-enb-rrc.cc @@ -469,17 +469,50 @@ UeManager::PrepareHandover (uint16_t cellId) } - void -UeManager::SendHandoverCommand (LteRrcSap::RrcConnectionReconfiguration rcr) +UeManager::RecvHandoverRequestAck (EpcX2SapUser::HandoverRequestAckParams params) { NS_LOG_FUNCTION (this); - m_rrc->m_rrcSapUser->SendRrcConnectionReconfiguration (m_rnti, rcr); + + NS_ASSERT_MSG (params.notAdmittedBearers.empty (), "not admission of some bearers upon handover is not supported"); + // NS_ASSERT_MSG (params.admittedBearers.size () == m_drbMap.size (), "not enough bearers in admittedBearers"); + + // note: the Handover command from the target eNB to the source eNB + // is expected to be sent transparently to the UE; however, here we + // decode the message and eventually reencode it. This way we can + // support both a real RRC protocol implementation and an ideal one + // without actual RRC protocol encoding. + + Ptr encodedHandoverCommand = params.rrcContext; + LteRrcSap::RrcConnectionReconfiguration handoverCommand = m_rrc->m_rrcSapUser->DecodeHandoverCommand (encodedHandoverCommand); + m_rrc->m_rrcSapUser->SendRrcConnectionReconfiguration (m_rnti, handoverCommand); SwitchToState (HANDOVER_LEAVING); - NS_ASSERT (rcr.haveMobilityControlInfo); - m_rrc->m_handoverStartTrace (m_imsi, m_rrc->m_cellId, m_rnti, rcr.mobilityControlInfo.targetPhysCellId); + NS_ASSERT (handoverCommand.haveMobilityControlInfo); + m_rrc->m_handoverStartTrace (m_imsi, m_rrc->m_cellId, m_rnti, handoverCommand.mobilityControlInfo.targetPhysCellId); + + EpcX2SapProvider::SnStatusTransferParams sst; + sst.oldEnbUeX2apId = params.oldEnbUeX2apId; + sst.newEnbUeX2apId = params.newEnbUeX2apId; + sst.sourceCellId = params.sourceCellId; + sst.targetCellId = params.targetCellId; + for ( std::map >::iterator drbIt = m_drbMap.begin (); + drbIt != m_drbMap.end (); + ++drbIt) + { + // SN status transfer is only for AM RLC + if (0 != drbIt->second->m_rlc->GetObject ()) + { + LtePdcp::Status status = drbIt->second->m_pdcp->GetStatus (); + EpcX2Sap::ErabsSubjectToStatusTransferItem i; + i.dlPdcpSn = status.txSn; + i.ulPdcpSn = status.rxSn; + sst.erabsSubjectToStatusTransferList.push_back (i); + } + } + m_rrc->m_x2SapProvider->SendSnStatusTransfer (sst); } + LteRrcSap::RadioResourceConfigDedicated UeManager::GetRadioResourceConfigForHandoverPreparationInfo () { @@ -568,6 +601,25 @@ UeManager::RecvHandoverPreparationFailure (uint16_t cellId) } } +void +UeManager::RecvSnStatusTransfer (EpcX2SapUser::SnStatusTransferParams params) +{ + NS_LOG_FUNCTION (this); + for (std::vector::iterator erabIt + = params.erabsSubjectToStatusTransferList.begin (); + erabIt != params.erabsSubjectToStatusTransferList.end (); + ++erabIt) + { + // LtePdcp::Status status; + // status.txSn = erabIt->dlPdcpSn; + // status.rxSn = erabIt->ulPdcpSn; + // uint8_t drbId = Bid2Drbid (erabIt->erabId); + // std::map >::iterator drbIt = m_drbMap.find (drbId); + // NS_ASSERT_MSG (drbIt != m_drbMap.end (), "could not find DRBID " << (uint32_t) drbId); + // drbIt->second->m_pdcp->SetStatus (status); + } +} + // methods forwarded from RRC SAP void @@ -1290,11 +1342,20 @@ LteEnbRrc::DoRecvHandoverRequest (EpcX2SapUser::HandoverRequestParams req) ueManager->SetSource (req.sourceCellId, req.oldEnbUeX2apId); ueManager->SetImsi (req.mmeUeS1apId); + EpcX2SapProvider::HandoverRequestAckParams ackParams; + ackParams.oldEnbUeX2apId = req.oldEnbUeX2apId; + ackParams.newEnbUeX2apId = rnti; + ackParams.sourceCellId = req.sourceCellId; + ackParams.targetCellId = req.targetCellId; + for (std::vector ::iterator it = req.bearers.begin (); it != req.bearers.end (); ++it) { ueManager->SetupDataRadioBearer (it->erabLevelQosParameters, it->erabId, it->gtpTeid, it->transportLayerAddress); + // EpcX2Sap::ErabAdmittedItem i; + // i.erabId = it->erabId; + //ackParams.admittedBearers.push_back (i); } LteRrcSap::RrcConnectionReconfiguration handoverCommand = ueManager->GetRrcConnectionReconfigurationForHandover (); @@ -1312,15 +1373,10 @@ LteEnbRrc::DoRecvHandoverRequest (EpcX2SapUser::HandoverRequestParams req) handoverCommand.mobilityControlInfo.rachConfigDedicated.raPrachMaskIndex = anrcrv.raPrachMaskIndex; Ptr encodedHandoverCommand = m_rrcSapUser->EncodeHandoverCommand (handoverCommand); - NS_LOG_LOGIC ("Send X2 message: HANDOVER REQUEST ACK"); - - EpcX2SapProvider::HandoverRequestAckParams ackParams; - ackParams.oldEnbUeX2apId = req.oldEnbUeX2apId; - ackParams.newEnbUeX2apId = rnti; - ackParams.sourceCellId = req.sourceCellId; - ackParams.targetCellId = req.targetCellId; ackParams.rrcContext = encodedHandoverCommand; + NS_LOG_LOGIC ("Send X2 message: HANDOVER REQUEST ACK"); + NS_LOG_LOGIC ("oldEnbUeX2apId = " << ackParams.oldEnbUeX2apId); NS_LOG_LOGIC ("newEnbUeX2apId = " << ackParams.newEnbUeX2apId); NS_LOG_LOGIC ("sourceCellId = " << ackParams.sourceCellId); @@ -1343,17 +1399,7 @@ LteEnbRrc::DoRecvHandoverRequestAck (EpcX2SapUser::HandoverRequestAckParams para uint16_t rnti = params.oldEnbUeX2apId; Ptr ueManager = GetUeManager (rnti); - - // note: the Handover command from the target eNB to the source eNB - // is expected to be sent transparently to the UE; however, here we - // decode the message and eventually reencode it. This way we can - // support both a real RRC protocol implementation and an ideal one - // without actual RRC protocol encoding. - - Ptr encodedHandoverCommand = params.rrcContext; - LteRrcSap::RrcConnectionReconfiguration handoverCommand = m_rrcSapUser->DecodeHandoverCommand (encodedHandoverCommand); - ueManager->SendHandoverCommand (handoverCommand); - + ueManager->RecvHandoverRequestAck (params); } void @@ -1385,7 +1431,9 @@ LteEnbRrc::DoRecvSnStatusTransfer (EpcX2SapUser::SnStatusTransferParams params) NS_LOG_LOGIC ("newEnbUeX2apId = " << params.newEnbUeX2apId); NS_LOG_LOGIC ("erabsSubjectToStatusTransferList size = " << params.erabsSubjectToStatusTransferList.size ()); - NS_ASSERT ("Processing of SN STATUS TRANSFER X2 message IS NOT IMPLEMENTED"); + uint16_t rnti = params.newEnbUeX2apId; + Ptr ueManager = GetUeManager (rnti); + ueManager->RecvSnStatusTransfer (params); } void diff --git a/src/lte/model/lte-enb-rrc.h b/src/lte/model/lte-enb-rrc.h index bd5cbfd57..b6a250f66 100644 --- a/src/lte/model/lte-enb-rrc.h +++ b/src/lte/model/lte-enb-rrc.h @@ -157,15 +157,11 @@ public: void PrepareHandover (uint16_t cellId); /** - * In the X2-based handover procedure, at the source eNB, trigger - * handover by sending to the UE a RRC Connection - * Reconfiguration message including Mobility Control Info + * take the necessary actions in response to the reception of an X2 HANDOVER REQUEST ACK message * - * \param rcr the RrcConnectionReconfiguration message including the - * Mobility Control Info. The content of this struct shall be - * provided by the target eNB. + * \param params */ - void SendHandoverCommand (LteRrcSap::RrcConnectionReconfiguration rcr); + void RecvHandoverRequestAck (EpcX2SapUser::HandoverRequestAckParams params); /** * @@ -213,6 +209,13 @@ public: * \param cellId id of the target cell */ void RecvHandoverPreparationFailure (uint16_t cellId); + + /** + * Take the necessary actions in response to the reception of an X2 SN STATUS TRANSFER message + * + * \param params the SN STATUS + */ + void RecvSnStatusTransfer (EpcX2SapUser::SnStatusTransferParams params); // methods forwarded from RRC SAP diff --git a/src/lte/model/lte-pdcp.cc b/src/lte/model/lte-pdcp.cc index c0d639aa6..6bd3cdee5 100644 --- a/src/lte/model/lte-pdcp.cc +++ b/src/lte/model/lte-pdcp.cc @@ -142,6 +142,22 @@ LtePdcp::GetLteRlcSapUser () return m_rlcSapUser; } +LtePdcp::Status +LtePdcp::GetStatus () +{ + Status s; + s.txSn = m_txSequenceNumber; + s.rxSn = m_rxSequenceNumber; + return s; +} + +void +LtePdcp::SetStatus (Status s) +{ + m_txSequenceNumber = s.txSn; + m_rxSequenceNumber = s.rxSn; +} + //////////////////////////////////////// void diff --git a/src/lte/model/lte-pdcp.h b/src/lte/model/lte-pdcp.h index dfc49a5a4..068b8bff5 100644 --- a/src/lte/model/lte-pdcp.h +++ b/src/lte/model/lte-pdcp.h @@ -87,6 +87,30 @@ public: */ LteRlcSapUser* GetLteRlcSapUser (); + static const uint16_t MAX_PDCP_SN = 4096; + + /** + * Status variables of the PDCP + * + */ + struct Status + { + uint16_t txSn; ///< TX sequence number + uint16_t rxSn; ///< RX sequence number + }; + + /** + * + * \return the current status of the PDCP + */ + Status GetStatus (); + + /** + * Set the status of the PDCP + * + * \param s + */ + void SetStatus (Status s); protected: // Interface provided to upper RRC entity