From c4a50b7de079328c80de27966172e27e0f9b3673 Mon Sep 17 00:00:00 2001 From: Francisco Date: Tue, 2 Feb 2021 22:16:25 +0000 Subject: [PATCH] avoid loss of pdcp sdus' SNs buffered in gtpu during handover --- srsenb/hdr/stack/upper/gtpu.h | 3 ++- srsenb/src/stack/upper/gtpu.cc | 23 ++++++++++++----------- srsenb/test/upper/gtpu_test.cc | 17 ++++++++++++++++- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/srsenb/hdr/stack/upper/gtpu.h b/srsenb/hdr/stack/upper/gtpu.h index 8765153bb..73318a873 100644 --- a/srsenb/hdr/stack/upper/gtpu.h +++ b/srsenb/hdr/stack/upper/gtpu.h @@ -100,6 +100,7 @@ private: }; m1u_handler m1u; + const uint32_t undefined_pdcp_sn = std::numeric_limits::max(); struct tunnel { bool dl_enabled = true; bool fwd_teid_in_present = false; @@ -111,7 +112,7 @@ private: uint32_t spgw_addr = 0; uint32_t fwd_teid_in = 0; ///< forward Rx SDUs to this TEID uint32_t prior_teid_in = 0; ///< buffer bearer SDUs until this TEID receives an End Marker - std::vector buffer; + std::multimap buffer; }; std::unordered_map tunnels; std::map, SRSENB_N_RADIO_BEARERS> > ue_teidin_db; diff --git a/srsenb/src/stack/upper/gtpu.cc b/srsenb/src/stack/upper/gtpu.cc index 9a4461699..0da992cbb 100644 --- a/srsenb/src/stack/upper/gtpu.cc +++ b/srsenb/src/stack/upper/gtpu.cc @@ -190,8 +190,11 @@ void gtpu::set_tunnel_status(uint32_t teidin, bool dl_active) } tun_it->second.dl_enabled = dl_active; if (dl_active) { - for (auto& sdu : tun_it->second.buffer) { - pdcp->write_sdu(tun_it->second.rnti, tun_it->second.lcid, std::move(sdu)); + for (auto& sdu_it : tun_it->second.buffer) { + pdcp->write_sdu(tun_it->second.rnti, + tun_it->second.lcid, + std::move(sdu_it.second), + sdu_it.first == undefined_pdcp_sn ? -1 : sdu_it.first); } tun_it->second.buffer.clear(); } @@ -318,14 +321,16 @@ void gtpu::handle_gtpu_s1u_rx_packet(srslte::unique_byte_buffer_t pdu, const soc if (rx_tun.fwd_teid_in_present) { tunnel& tx_tun = tunnels.at(rx_tun.fwd_teid_in); send_pdu_to_tunnel(tx_tun, std::move(pdu)); - } else if (not rx_tun.dl_enabled) { - rx_tun.buffer.push_back(std::move(pdu)); } else { - uint32_t pdcp_sn = -1; + uint32_t pdcp_sn = undefined_pdcp_sn; if (header.flags & GTPU_FLAGS_EXTENDED_HDR and header.next_ext_hdr_type == GTPU_EXT_HEADER_PDCP_PDU_NUMBER) { pdcp_sn = (header.ext_buffer[1] << 8u) + header.ext_buffer[2]; } - pdcp->write_sdu(rnti, lcid, std::move(pdu), pdcp_sn); + if (not rx_tun.dl_enabled) { + rx_tun.buffer.insert(std::make_pair(pdcp_sn, std::move(pdu))); + } else { + pdcp->write_sdu(rnti, lcid, std::move(pdu), pdcp_sn == undefined_pdcp_sn ? -1 : pdcp_sn); + } } } break; case GTPU_MSG_END_MARKER: { @@ -345,12 +350,8 @@ void gtpu::handle_gtpu_s1u_rx_packet(srslte::unique_byte_buffer_t pdu, const soc tunnel& new_tun = tunnels.at(new_teidin); if (new_teidin != old_tun.teid_in and new_tun.prior_teid_in_present and new_tun.prior_teid_in == old_tun.teid_in) { - for (srslte::unique_byte_buffer_t& sdu : new_tun.buffer) { - pdcp->write_sdu(new_tun.rnti, new_tun.lcid, std::move(sdu)); - } - new_tun.dl_enabled = true; new_tun.prior_teid_in_present = false; - new_tun.buffer.clear(); + set_tunnel_status(new_tun.teid_in, true); } } } diff --git a/srsenb/test/upper/gtpu_test.cc b/srsenb/test/upper/gtpu_test.cc index 08672be89..cd3e31407 100644 --- a/srsenb/test/upper/gtpu_test.cc +++ b/srsenb/test/upper/gtpu_test.cc @@ -183,8 +183,20 @@ int test_gtpu_direct_tunneling() std::vector encoded_data; srslte::span pdu_view{}; + // TEST: GTPU buffers incoming PDCP buffered SNs until the TEID is explicitly activated + tenb_gtpu.handle_gtpu_s1u_rx_packet(read_socket(tenb_stack.s1u_fd), senb_sockaddr); + TESTASSERT(tenb_pdcp.last_sdu == nullptr); + tenb_gtpu.handle_gtpu_s1u_rx_packet(read_socket(tenb_stack.s1u_fd), senb_sockaddr); + TESTASSERT(tenb_pdcp.last_sdu == nullptr); + tenb_gtpu.set_tunnel_status(dl_tenb_teid_in, true); + pdu_view = srslte::make_span(tenb_pdcp.last_sdu); + TESTASSERT(std::count(pdu_view.begin() + PDU_HEADER_SIZE, pdu_view.end(), 7) == 10); + TESTASSERT(tenb_pdcp.last_rnti == rnti2); + TESTASSERT(tenb_pdcp.last_lcid == drb1); + TESTASSERT(tenb_pdcp.last_pdcp_sn == (int)7); + // TEST: verify that PDCP buffered SNs have been forwarded through SeNB->TeNB tunnel - for (size_t sn = 6; sn < 10; ++sn) { + for (size_t sn = 8; sn < 10; ++sn) { tenb_gtpu.handle_gtpu_s1u_rx_packet(read_socket(tenb_stack.s1u_fd), senb_sockaddr); pdu_view = srslte::make_span(tenb_pdcp.last_sdu); TESTASSERT(std::count(pdu_view.begin() + PDU_HEADER_SIZE, pdu_view.end(), sn) == 10); @@ -249,4 +261,7 @@ int main() srslte::logmap::set_default_log_level(srslte::LOG_LEVEL_DEBUG); srslte::logmap::set_default_hex_limit(100000); TESTASSERT(srsenb::test_gtpu_direct_tunneling() == SRSLTE_SUCCESS); + + srslog::flush(); + srslte::console("Success"); }