diff --git a/lib/include/srslte/interfaces/enb_interfaces.h b/lib/include/srslte/interfaces/enb_interfaces.h index 1c62d3b81..cf3b84a27 100644 --- a/lib/include/srslte/interfaces/enb_interfaces.h +++ b/lib/include/srslte/interfaces/enb_interfaces.h @@ -478,6 +478,7 @@ public: virtual uint32_t add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out, const bearer_props* props = nullptr) = 0; + virtual void set_tunnel_status(uint32_t teidin, bool dl_active) = 0; virtual void rem_bearer(uint16_t rnti, uint32_t lcid) = 0; virtual void mod_bearer_rnti(uint16_t old_rnti, uint16_t new_rnti) = 0; virtual void rem_user(uint16_t rnti) = 0; diff --git a/srsenb/hdr/stack/rrc/rrc_mobility.h b/srsenb/hdr/stack/rrc/rrc_mobility.h index 18d642731..479a6720c 100644 --- a/srsenb/hdr/stack/rrc/rrc_mobility.h +++ b/srsenb/hdr/stack/rrc/rrc_mobility.h @@ -97,7 +97,9 @@ private: void enter(rrc_mobility* f, const ho_meas_report_ev& meas_report); }; - struct s1_target_ho_st {}; + struct s1_target_ho_st { + std::vector pending_tunnels; + }; struct wait_recfg_comp {}; struct s1_source_ho_st : public subfsm_t { struct ho_cmd_msg { @@ -166,7 +168,7 @@ protected: // +----------------+-------------------+---------------------+----------------------------+-------------------------+ row< idle_st, s1_source_ho_st, ho_meas_report_ev, nullptr, &fsm::needs_s1_ho >, row< idle_st, intraenb_ho_st, ho_meas_report_ev, nullptr, &fsm::needs_intraenb_ho >, - row< idle_st, s1_target_ho_st, ho_req_rx_ev, &fsm::handle_ho_requested >, + row< idle_st, s1_target_ho_st, ho_req_rx_ev, &fsm::handle_ho_requested >, // +----------------+-------------------+---------------------+----------------------------+-------------------------+ upd< intraenb_ho_st, user_crnti_upd_ev, &fsm::handle_crnti_ce >, row< intraenb_ho_st, idle_st, recfg_complete_ev, &fsm::handle_recfg_complete >, diff --git a/srsenb/hdr/stack/upper/gtpu.h b/srsenb/hdr/stack/upper/gtpu.h index 09c0d192e..8765153bb 100644 --- a/srsenb/hdr/stack/upper/gtpu.h +++ b/srsenb/hdr/stack/upper/gtpu.h @@ -46,6 +46,7 @@ public: uint32_t addr, uint32_t teid_out, const bearer_props* props = nullptr) override; + void set_tunnel_status(uint32_t teidin, bool dl_active) override; void rem_bearer(uint16_t rnti, uint32_t lcid) override; void mod_bearer_rnti(uint16_t old_rnti, uint16_t new_rnti) override; void rem_user(uint16_t rnti) override; @@ -100,6 +101,7 @@ private: m1u_handler m1u; struct tunnel { + bool dl_enabled = true; bool fwd_teid_in_present = false; bool prior_teid_in_present = false; uint16_t rnti = SRSLTE_INVALID_RNTI; diff --git a/srsenb/src/stack/rrc/rrc_mobility.cc b/srsenb/src/stack/rrc/rrc_mobility.cc index ef0e582ea..5a7ab0240 100644 --- a/srsenb/src/stack/rrc/rrc_mobility.cc +++ b/srsenb/src/stack/rrc/rrc_mobility.cc @@ -75,7 +75,8 @@ uint16_t compute_mac_i(uint16_t crnti, } uint32_t N_bytes = bref.distance_bytes(); - printf("Encoded varShortMAC: cellId=0x%x, PCI=%d, rnti=0x%x (%d bytes)", cellid, pci, crnti, N_bytes); + srslte::logmap::get("RRC")->info( + "Encoded varShortMAC: cellId=0x%x, PCI=%d, rnti=0x%x (%d bytes)", cellid, pci, crnti, N_bytes); // Compute MAC-I switch (integ_algo) { @@ -731,6 +732,7 @@ void rrc::ue::rrc_mobility::handle_ho_requested(idle_st& s, const ho_req_rx_ev& // Set admitted E-RABs std::vector admitted_erabs; + auto& fwd_tunnels = get_state()->pending_tunnels; for (auto& erab : rrc_ue->bearer_list.get_erabs()) { admitted_erabs.emplace_back(); asn1::s1ap::erab_admitted_item_s& admitted_erab = admitted_erabs.back(); @@ -759,6 +761,7 @@ void rrc::ue::rrc_mobility::handle_ho_requested(idle_st& s, const ho_req_rx_ev& props.flush_before_teidin = erab.second.teid_in; uint32_t dl_teid_in = rrc_ue->bearer_list.add_gtpu_bearer( erab.second.id, erab.second.teid_out, erab.second.address.to_number(), &props); + fwd_tunnels.push_back(dl_teid_in); srslte::uint32_to_uint8(dl_teid_in, admitted_erabs.back().dl_g_tp_teid.data()); } } @@ -888,6 +891,11 @@ void rrc::ue::rrc_mobility::handle_status_transfer(s1_target_ho_st& s, const sta rrc_enb->pdcp->set_bearer_state(rrc_ue->rnti, drb_it->lc_ch_id, drb_state); } + // Enable forwarding of GTPU SDUs to PDCP + for (uint32_t teid : s.pending_tunnels) { + rrc_enb->gtpu->set_tunnel_status(teid, true); + } + // Check if there is any pending Reconfiguration Complete. If there is, self-trigger if (pending_recfg_complete.crit_exts.type().value != rrc_conn_recfg_complete_s::crit_exts_c_::types_opts::nulltype) { trigger(pending_recfg_complete); diff --git a/srsenb/src/stack/upper/gtpu.cc b/srsenb/src/stack/upper/gtpu.cc index e12b83d2a..9a4461699 100644 --- a/srsenb/src/stack/upper/gtpu.cc +++ b/srsenb/src/stack/upper/gtpu.cc @@ -160,7 +160,11 @@ uint32_t gtpu::add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t if (props != nullptr) { if (props->flush_before_teidin_present) { + // GTPU should wait for the bearer ctxt to arrive before sending SDUs from DL tunnel to PDCP + new_tun.dl_enabled = false; + // GTPU should not forward SDUs from main tunnel until the SeNB-TeNB tunnel has been flushed tunnel& after_tun = tunnels.at(props->flush_before_teidin); + after_tun.dl_enabled = false; after_tun.prior_teid_in_present = true; after_tun.prior_teid_in = teid_in; } @@ -177,6 +181,22 @@ uint32_t gtpu::add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t return teid_in; } +void gtpu::set_tunnel_status(uint32_t teidin, bool dl_active) +{ + auto tun_it = tunnels.find(teidin); + if (tun_it == tunnels.end()) { + logger.warning("Setting TEID=%d status", teidin); + return; + } + 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)); + } + tun_it->second.buffer.clear(); + } +} + void gtpu::rem_bearer(uint16_t rnti, uint32_t lcid) { auto ue_it = ue_teidin_db.find(rnti); @@ -298,7 +318,7 @@ 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 (rx_tun.prior_teid_in_present) { + } else if (not rx_tun.dl_enabled) { rx_tun.buffer.push_back(std::move(pdu)); } else { uint32_t pdcp_sn = -1; @@ -328,6 +348,7 @@ void gtpu::handle_gtpu_s1u_rx_packet(srslte::unique_byte_buffer_t pdu, const soc 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(); } @@ -501,7 +522,7 @@ void gtpu::log_message(tunnel& tun, bool is_rx, srslte::span pdu, int p if (is_rx) { dir = "Rx"; fmt::format_to(strbuf2, "{}:0x{:0x} > ", srslte::gtpu_ntoa(htonl(tun.spgw_addr)), tun.teid_in); - if (tun.prior_teid_in_present) { + if (not tun.dl_enabled) { fmt::format_to(strbuf2, "DL (buffered), "); } else if (tun.fwd_teid_in_present) { tunnel& tx_tun = tunnels.at(tun.fwd_teid_in); diff --git a/srsenb/test/common/dummy_classes.h b/srsenb/test/common/dummy_classes.h index c29d1cc93..aecc432f4 100644 --- a/srsenb/test/common/dummy_classes.h +++ b/srsenb/test/common/dummy_classes.h @@ -139,6 +139,7 @@ public: { return 0; } + void set_tunnel_status(uint32_t teidin, bool dl_active) override {} void rem_bearer(uint16_t rnti, uint32_t lcid) override {} void mod_bearer_rnti(uint16_t old_rnti, uint16_t new_rnti) override {} void rem_user(uint16_t rnti) override {}