bugfix,gtpu: send end marker via the forwarding tunnel, when the source enb receives ue ctxt release command. Improve GTPU unit testing

master
Francisco 4 years ago committed by Francisco Paisana
parent 8cbbebdea2
commit 048d487921

@ -138,10 +138,14 @@ bool gtpu_tunnel_manager::update_rnti(uint16_t old_rnti, uint16_t new_rnti)
srsran::bounded_vector<uint32_t, MAX_TUNNELS_PER_UE> to_remove; srsran::bounded_vector<uint32_t, MAX_TUNNELS_PER_UE> to_remove;
for (lcid_tunnel& bearer : new_rnti_obj) { for (lcid_tunnel& bearer : new_rnti_obj) {
tunnels[bearer.teid].rnti = new_rnti; tunnels[bearer.teid].rnti = new_rnti;
if (tunnels[bearer.teid].state == tunnel_state::forward_to) {
// Remove forwarding path // Remove forwarding path
if (tunnels[bearer.teid].state == tunnel_state::forward_to) {
tunnels[bearer.teid].state = tunnel_state::pdcp_active; tunnels[bearer.teid].state = tunnel_state::pdcp_active;
tunnels[bearer.teid].fwd_tunnel = nullptr; tunnels[bearer.teid].fwd_tunnel = nullptr;
logger.info("Taking down forwarding tunnel for rnti=0x%x, lcid=%d. New default " TEID_IN_FMT,
new_rnti,
bearer.lcid,
bearer.teid);
} else if (tunnels[bearer.teid].state == tunnel_state::forwarded_from) { } else if (tunnels[bearer.teid].state == tunnel_state::forwarded_from) {
to_remove.push_back(bearer.teid); to_remove.push_back(bearer.teid);
} }
@ -537,10 +541,19 @@ void gtpu::rem_tunnel(uint32_t teidin)
void gtpu::rem_user(uint16_t rnti) void gtpu::rem_user(uint16_t rnti)
{ {
if (tunnels.find_rnti_tunnels(rnti) == nullptr) { const auto* tun_lst = tunnels.find_rnti_tunnels(rnti);
if (tun_lst == nullptr) {
logger.info("Removing user - rnti=0x%x not found.", rnti); logger.info("Removing user - rnti=0x%x not found.", rnti);
return; return;
} }
for (gtpu_tunnel_manager::lcid_tunnel tun_elem : *tun_lst) {
const gtpu_tunnel* tun = tunnels.find_tunnel(tun_elem.teid);
if (tun != nullptr and tun->state == gtpu_tunnel_manager::tunnel_state::forwarded_from) {
// In case of forwarding tunnel tx endpoint, send one extra End Marker on removal
send_end_marker(tun->teid_in);
rem_tunnel(tun->teid_in);
}
}
tunnels.remove_rnti(rnti); tunnels.remove_rnti(rnti);
} }
@ -553,6 +566,7 @@ void gtpu::handle_end_marker(const gtpu_tunnel& rx_tunnel)
// TS 36.300, Sec 10.1.2.2.1 - Path Switch upon handover // TS 36.300, Sec 10.1.2.2.1 - Path Switch upon handover
// END MARKER should be forwarded to TeNB if forwarding is activated // END MARKER should be forwarded to TeNB if forwarding is activated
send_end_marker(rx_tunnel.fwd_tunnel->teid_in); send_end_marker(rx_tunnel.fwd_tunnel->teid_in);
rem_tunnel(rx_tunnel.fwd_tunnel->teid_in);
} }
// Remove tunnel that received End Marker // Remove tunnel that received End Marker

@ -205,7 +205,7 @@ void test_gtpu_tunnel_manager()
TESTASSERT(after_tun->state == gtpu_tunnel_manager::tunnel_state::pdcp_active); TESTASSERT(after_tun->state == gtpu_tunnel_manager::tunnel_state::pdcp_active);
} }
enum class tunnel_test_event { success, wait_end_marker_timeout }; enum class tunnel_test_event { success, wait_end_marker_timeout, ue_removal_no_marker, reest_senb };
int test_gtpu_direct_tunneling(tunnel_test_event event) int test_gtpu_direct_tunneling(tunnel_test_event event)
{ {
@ -330,6 +330,25 @@ int test_gtpu_direct_tunneling(tunnel_test_event event)
for (size_t i = 0; i < gtpu_args.indirect_tunnel_timeout_msec + 1; ++i) { for (size_t i = 0; i < gtpu_args.indirect_tunnel_timeout_msec + 1; ++i) {
task_sched.tic(); task_sched.tic();
} }
} else if (event == tunnel_test_event::ue_removal_no_marker) {
// TEST: EndMarker may even reach SeNB, but the SeNB receives in tandem the UEContextReleaseCommand and closes
// the user tunnels before the chance to send an EndMarker
senb_gtpu.rem_user(0x46);
tenb_gtpu.handle_gtpu_s1u_rx_packet(read_socket(tenb_rx_sockets.s1u_fd), senb_sockaddr);
} else if (event == tunnel_test_event::reest_senb) {
// TEST: UE may start a Reestablishment to the SeNB. In such case, the rnti will be updated, the forwarding tunnel
// taken down, and the previous main tunnel reestablished
senb_gtpu.mod_bearer_rnti(0x46, 0x47);
std::iota(data_vec.begin(), data_vec.end(), 0);
std::shuffle(data_vec.begin(), data_vec.end(), g);
pdu = encode_gtpu_packet(data_vec, senb_teid_in, sgw_sockaddr, senb_sockaddr);
encoded_data.assign(pdu->msg + 8u, pdu->msg + pdu->N_bytes);
senb_pdcp.last_sdu = nullptr;
senb_gtpu.handle_gtpu_s1u_rx_packet(std::move(pdu), sgw_sockaddr);
TESTASSERT(senb_pdcp.last_sdu != nullptr);
TESTASSERT(senb_pdcp.last_sdu->N_bytes == encoded_data.size() and
memcmp(senb_pdcp.last_sdu->msg, encoded_data.data(), encoded_data.size()) == 0);
return SRSRAN_SUCCESS;
} else { } else {
// TEST: EndMarker is forwarded via MME->SeNB->TeNB, and TeNB buffered PDUs are flushed // TEST: EndMarker is forwarded via MME->SeNB->TeNB, and TeNB buffered PDUs are flushed
pdu = encode_end_marker(senb_teid_in); pdu = encode_end_marker(senb_teid_in);
@ -357,6 +376,8 @@ int main(int argc, char** argv)
srsenb::test_gtpu_tunnel_manager(); srsenb::test_gtpu_tunnel_manager();
TESTASSERT(srsenb::test_gtpu_direct_tunneling(srsenb::tunnel_test_event::success) == SRSRAN_SUCCESS); TESTASSERT(srsenb::test_gtpu_direct_tunneling(srsenb::tunnel_test_event::success) == SRSRAN_SUCCESS);
TESTASSERT(srsenb::test_gtpu_direct_tunneling(srsenb::tunnel_test_event::wait_end_marker_timeout) == SRSRAN_SUCCESS); TESTASSERT(srsenb::test_gtpu_direct_tunneling(srsenb::tunnel_test_event::wait_end_marker_timeout) == SRSRAN_SUCCESS);
TESTASSERT(srsenb::test_gtpu_direct_tunneling(srsenb::tunnel_test_event::ue_removal_no_marker) == SRSRAN_SUCCESS);
TESTASSERT(srsenb::test_gtpu_direct_tunneling(srsenb::tunnel_test_event::reest_senb) == SRSRAN_SUCCESS);
srslog::flush(); srslog::flush();

Loading…
Cancel
Save