gtpu bugfix - avoid erasing indirect tunnel and causing iterator invalidation while iterating list of tunnels

master
Francisco 4 years ago committed by Francisco Paisana
parent 977c194cbc
commit a540c56552

@ -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);
/****************************************************************************

@ -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<uint32_t>& 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<uint32_t>& 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<uint32_t>& 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;

Loading…
Cancel
Save