diff --git a/src/lte/model/lte-enb-rrc.cc b/src/lte/model/lte-enb-rrc.cc index a1037a2a2..8129f36e0 100644 --- a/src/lte/model/lte-enb-rrc.cc +++ b/src/lte/model/lte-enb-rrc.cc @@ -555,6 +555,7 @@ UeManager::ReleaseDataRadioBearer (uint8_t drbid) void LteEnbRrc::DoSendReleaseDataRadioBearer (uint64_t imsi, uint16_t rnti, uint8_t bearerId) { + NS_LOG_FUNCTION (this << imsi << rnti << (uint16_t) bearerId); Ptr ueManager = GetUeManager (rnti); // Bearer de-activation towards UE ueManager->ReleaseDataRadioBearer (bearerId); @@ -724,6 +725,28 @@ UeManager::GetRrcConnectionReconfigurationForHandover () return BuildRrcConnectionReconfiguration (); } +void +UeManager::SendPacket (uint8_t bid, Ptr p) +{ + NS_LOG_FUNCTION (this << p << (uint16_t) bid); + LtePdcpSapProvider::TransmitPdcpSduParameters params; + params.pdcpSdu = p; + params.rnti = m_rnti; + params.lcid = Bid2Lcid (bid); + uint8_t drbid = Bid2Drbid (bid); + // Transmit PDCP sdu only if DRB ID found in drbMap + std::map >::iterator it = m_drbMap.find (drbid); + if (it != m_drbMap.end ()) + { + Ptr bearerInfo = GetDataRadioBearerInfo (drbid); + if (bearerInfo != NULL) + { + LtePdcpSapProvider* pdcpSapProvider = bearerInfo->m_pdcp->GetLtePdcpSapProvider (); + pdcpSapProvider->TransmitPdcpSdu (params); + } + } +} + void UeManager::SendData (uint8_t bid, Ptr p) { @@ -740,26 +763,18 @@ UeManager::SendData (uint8_t bid, Ptr p) case CONNECTION_RECONFIGURATION: case CONNECTION_REESTABLISHMENT: case HANDOVER_PREPARATION: - case HANDOVER_JOINING: case HANDOVER_PATH_SWITCH: { NS_LOG_LOGIC ("queueing data on PDCP for transmission over the air"); - LtePdcpSapProvider::TransmitPdcpSduParameters params; - params.pdcpSdu = p; - params.rnti = m_rnti; - params.lcid = Bid2Lcid (bid); - uint8_t drbid = Bid2Drbid (bid); - //Transmit PDCP sdu only if DRB ID found in drbMap - std::map >::iterator it = m_drbMap.find (drbid); - if (it != m_drbMap.end ()) - { - Ptr bearerInfo = GetDataRadioBearerInfo (drbid); - if (bearerInfo != NULL) - { - LtePdcpSapProvider* pdcpSapProvider = bearerInfo->m_pdcp->GetLtePdcpSapProvider (); - pdcpSapProvider->TransmitPdcpSdu (params); - } - } + SendPacket (bid, p); + } + break; + + case HANDOVER_JOINING: + { + // Buffer data until RRC Connection Reconfiguration Complete message is received + NS_LOG_LOGIC ("buffering data"); + m_packetBuffer.push_back (std::make_pair (bid, p)); } break; @@ -1005,6 +1020,20 @@ UeManager::RecvRrcConnectionReconfigurationCompleted (LteRrcSap::RrcConnectionRe case HANDOVER_JOINING: { m_handoverJoiningTimeout.Cancel (); + + while (!m_packetBuffer.empty ()) + { + NS_LOG_LOGIC ("dequeueing data from buffer"); + std::pair > bidPacket = m_packetBuffer.front (); + uint8_t bid = bidPacket.first; + Ptr p = bidPacket.second; + + NS_LOG_LOGIC ("queueing data on PDCP for transmission over the air"); + SendPacket (bid, p); + + m_packetBuffer.pop_front (); + } + NS_LOG_INFO ("Send PATH SWITCH REQUEST to the MME"); EpcEnbS1SapProvider::PathSwitchRequestParameters params; params.rnti = m_rnti; diff --git a/src/lte/model/lte-enb-rrc.h b/src/lte/model/lte-enb-rrc.h index 44380fdb1..a5d935f4f 100644 --- a/src/lte/model/lte-enb-rrc.h +++ b/src/lte/model/lte-enb-rrc.h @@ -218,9 +218,14 @@ public: */ LteRrcSap::RrcConnectionReconfiguration GetRrcConnectionReconfigurationForHandover (); - /** - * Send a data packet over the appropriate Data Radio Bearer - * + /** + * Send a data packet over the appropriate Data Radio Bearer. + * If state is HANDOVER_JOINING (i.e. target eNB has received the + * Handover Request), the packet is buffered. + * If state is HANDOVER_LEAVING (i.e. source eNB has received the + * RRC Connection Reconfiguration, the packet is sent through the + * X2 interface. + * * \param bid the corresponding EPS Bearer ID * \param p the packet */ @@ -469,6 +474,17 @@ private: */ uint8_t Bid2Drbid (uint8_t bid); + /** + * Send a data packet over the appropriate Data Radio Bearer. + * It is called by SendData if the UE is in a connected state + * or when the RRC Connection Reconfiguration Complete message + * is received and the packets are debuffered. + * + * \param bid the corresponding EPS Bearer ID + * \param p the packet + */ + void SendPacket (uint8_t bid, Ptr p); + /** * Switch the UeManager to the given state * @@ -572,6 +588,18 @@ private: /// Pending start data radio bearers bool m_pendingStartDataRadioBearers; + + /** + * Packet buffer for when UE is doing the handover. + * The packets are stored with the bid (bearer ID). + * + * Source eNB starts forwarding data to target eNB through the X2 interface + * when it sends RRC Connection Reconfiguration to the UE. + * Target eNB buffers data until it receives RRC Connection Reconfiguration + * Complete from the UE. + */ + std::list > > m_packetBuffer; + }; // end of `class UeManager`