From a540c5655232092bc878edb1818459ed92112065 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 19 Mar 2021 11:29:11 +0000 Subject: [PATCH] gtpu bugfix - avoid erasing indirect tunnel and causing iterator invalidation while iterating list of tunnels --- srsenb/hdr/stack/upper/gtpu.h | 2 + srsenb/src/stack/upper/gtpu.cc | 70 +++++++++++++++++----------------- 2 files changed, 38 insertions(+), 34 deletions(-) diff --git a/srsenb/hdr/stack/upper/gtpu.h b/srsenb/hdr/stack/upper/gtpu.h index aade71e50..1fe5df36a 100644 --- a/srsenb/hdr/stack/upper/gtpu.h +++ b/srsenb/hdr/stack/upper/gtpu.h @@ -134,6 +134,8 @@ private: void error_indication(in_addr_t addr, in_port_t port, uint32_t err_teid); bool end_marker(uint32_t teidin); + void handle_end_marker(tunnel& rx_tunnel); + int create_dl_fwd_tunnel(uint32_t rx_teid_in, uint32_t tx_teid_in); /**************************************************************************** diff --git a/srsenb/src/stack/upper/gtpu.cc b/srsenb/src/stack/upper/gtpu.cc index a739f8b59..74fb72c31 100644 --- a/srsenb/src/stack/upper/gtpu.cc +++ b/srsenb/src/stack/upper/gtpu.cc @@ -289,16 +289,11 @@ void gtpu::rem_tunnel(uint32_t teidin) logger.warning("Removing GTPU tunnel TEID In=0x%x", teidin); return; } - if (it->second.fwd_teid_in_present) { - // Forward End Marker to forwarding tunnel, before deleting tunnel - end_marker(it->second.fwd_teid_in); - it->second.fwd_teid_in_present = false; - } auto ue_it = ue_teidin_db.find(it->second.rnti); std::vector& lcid_tunnels = ue_it->second[it->second.lcid]; lcid_tunnels.erase(std::remove(lcid_tunnels.begin(), lcid_tunnels.end(), teidin), lcid_tunnels.end()); + logger.debug("TEID In=%d for rnti=0x%x erased", teidin, it->second.rnti); tunnels.erase(it); - logger.debug("TEID In=%d erased", teidin); } void gtpu::rem_user(uint16_t rnti) @@ -314,6 +309,39 @@ void gtpu::rem_user(uint16_t rnti) } } +void gtpu::handle_end_marker(tunnel& rx_tunnel) +{ + uint16_t rnti = rx_tunnel.rnti; + logger.info("Received GTPU End Marker for rnti=0x%x.", rnti); + + // TS 36.300, Sec 10.1.2.2.1 - Path Switch upon handover + if (rx_tunnel.fwd_teid_in_present) { + // END MARKER should be forwarded to TeNB if forwarding is activated + end_marker(rx_tunnel.fwd_teid_in); + rx_tunnel.fwd_teid_in_present = false; + + rem_tunnel(rx_tunnel.teid_in); + } else { + // TeNB switches paths, and flush PDUs that have been buffered + auto rnti_it = ue_teidin_db.find(rnti); + if (rnti_it == ue_teidin_db.end()) { + logger.error("No rnti=0x%x entry for associated TEID=%d", rnti, rx_tunnel.teid_in); + return; + } + std::vector& bearer_tunnels = rnti_it->second[rx_tunnel.lcid]; + for (uint32_t new_teidin : bearer_tunnels) { + tunnel& new_tun = tunnels.at(new_teidin); + if (new_teidin != rx_tunnel.teid_in and new_tun.prior_teid_in_present and + new_tun.prior_teid_in == rx_tunnel.teid_in) { + rem_tunnel(new_tun.prior_teid_in); + new_tun.prior_teid_in_present = false; + set_tunnel_status(new_tun.teid_in, true); + break; + } + } + } +} + void gtpu::handle_gtpu_s1u_rx_packet(srslte::unique_byte_buffer_t pdu, const sockaddr_in& addr) { logger.debug("Received %d bytes from S1-U interface", pdu->N_bytes); @@ -376,35 +404,9 @@ void gtpu::handle_gtpu_s1u_rx_packet(srslte::unique_byte_buffer_t pdu, const soc } } } break; - case GTPU_MSG_END_MARKER: { - uint16_t rnti = rx_tunnel->rnti; - logger.info("Received GTPU End Marker for rnti=0x%x.", rnti); - - // TS 36.300, Sec 10.1.2.2.1 - Path Switch upon handover - if (rx_tunnel->fwd_teid_in_present) { - // END MARKER should be forwarded to TeNB if forwarding is activated - end_marker(rx_tunnel->fwd_teid_in); - rx_tunnel->fwd_teid_in_present = false; - } else { - // TeNB switches paths, and flush PDUs that have been buffered - auto rnti_it = ue_teidin_db.find(rnti); - if (rnti_it == ue_teidin_db.end()) { - logger.error("No rnti=0x%x entry for associated TEID=%d", rnti, header.teid); - return; - } - std::vector& bearer_tunnels = rnti_it->second[rx_tunnel->lcid]; - for (uint32_t new_teidin : bearer_tunnels) { - tunnel& new_tun = tunnels.at(new_teidin); - if (new_teidin != rx_tunnel->teid_in and new_tun.prior_teid_in_present and - new_tun.prior_teid_in == rx_tunnel->teid_in) { - rem_tunnel(new_tun.prior_teid_in); - new_tun.prior_teid_in_present = false; - set_tunnel_status(new_tun.teid_in, true); - } - } - } + case GTPU_MSG_END_MARKER: + handle_end_marker(*rx_tunnel); break; - } default: logger.warning("Unhandled GTPU message type=%d", header.message_type); break;