diff --git a/lib/include/srsran/adt/expected.h b/lib/include/srsran/adt/expected.h index 4842e45e1..bf6a390ce 100644 --- a/lib/include/srsran/adt/expected.h +++ b/lib/include/srsran/adt/expected.h @@ -29,7 +29,9 @@ class expected public: expected() : has_val(true), val(T{}) {} expected(T&& t) : has_val(true), val(std::forward(t)) {} + expected(const T& t) : has_val(true), val(t) {} expected(E&& e) : has_val(false), unexpected(std::forward(e)) {} + expected(const E& e) : has_val(false), unexpected(e) {} expected(const expected& other) { if (other.has_val) { diff --git a/lib/include/srsran/common/buffer_pool.h b/lib/include/srsran/common/buffer_pool.h index a05c65665..6589ceda8 100644 --- a/lib/include/srsran/common/buffer_pool.h +++ b/lib/include/srsran/common/buffer_pool.h @@ -185,11 +185,17 @@ inline unique_byte_buffer_t make_byte_buffer(const char* debug_ctxt) noexcept } namespace detail { + struct byte_buffer_pool_deleter { void operator()(void* ptr) { byte_buffer_pool::get_instance()->deallocate_node(ptr); } }; + } // namespace detail +/** + * Class to wrap objects of type T which get allocated/deallocated using the byte_buffer_pool + * @tparam T type of the object being allocated + */ template struct byte_buffer_pool_ptr { static_assert(sizeof(T) <= byte_buffer_pool::BLOCK_SIZE, "pool_bounded_vector does not fit buffer pool block size"); @@ -202,6 +208,7 @@ public: const T* operator->() const { return ptr.get(); } T& operator*() { return *ptr; } const T& operator*() const { return *ptr; } + bool has_value() const { return ptr.get() != nullptr; } template void emplace(CtorArgs&&... args) diff --git a/lib/include/srsran/common/byte_buffer.h b/lib/include/srsran/common/byte_buffer.h index dfa6dd8dd..016ced218 100644 --- a/lib/include/srsran/common/byte_buffer.h +++ b/lib/include/srsran/common/byte_buffer.h @@ -14,6 +14,7 @@ #define SRSRAN_BYTE_BUFFER_H #include "common.h" +#include "srsran/adt/span.h" #include #include diff --git a/lib/include/srsran/common/common.h b/lib/include/srsran/common/common.h index 9d690ac4f..1e3877df9 100644 --- a/lib/include/srsran/common/common.h +++ b/lib/include/srsran/common/common.h @@ -17,7 +17,6 @@ INCLUDES *******************************************************************************/ -#include "srsran/adt/span.h" #include #include #include diff --git a/lib/include/srsran/interfaces/enb_gtpu_interfaces.h b/lib/include/srsran/interfaces/enb_gtpu_interfaces.h index 8d882065e..fd1c3ace7 100644 --- a/lib/include/srsran/interfaces/enb_gtpu_interfaces.h +++ b/lib/include/srsran/interfaces/enb_gtpu_interfaces.h @@ -13,6 +13,7 @@ #ifndef SRSRAN_ENB_GTPU_INTERFACES_H #define SRSRAN_ENB_GTPU_INTERFACES_H +#include "srsran/adt/expected.h" #include "srsran/common/byte_buffer.h" namespace srsenb { @@ -35,7 +36,7 @@ public: uint32_t flush_before_teidin = 0; }; - virtual uint32_t + virtual srsran::expected 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; diff --git a/srsenb/hdr/stack/rrc/rrc_bearer_cfg.h b/srsenb/hdr/stack/rrc/rrc_bearer_cfg.h index a7d9d87b2..1e4d833b4 100644 --- a/srsenb/hdr/stack/rrc/rrc_bearer_cfg.h +++ b/srsenb/hdr/stack/rrc/rrc_bearer_cfg.h @@ -91,13 +91,13 @@ public: const asn1::unbounded_octstring* nas_pdu); // Methods to apply bearer updates - void add_gtpu_bearer(uint32_t erab_id); - uint32_t add_gtpu_bearer(uint32_t erab_id, - uint32_t teid_out, - uint32_t addr, - const gtpu_interface_rrc::bearer_props* props = nullptr); - void rem_gtpu_bearer(uint32_t erab_id); - void fill_pending_nas_info(asn1::rrc::rrc_conn_recfg_r8_ies_s* msg); + void add_gtpu_bearer(uint32_t erab_id); + srsran::expected add_gtpu_bearer(uint32_t erab_id, + uint32_t teid_out, + uint32_t addr, + const gtpu_interface_rrc::bearer_props* props = nullptr); + void rem_gtpu_bearer(uint32_t erab_id); + void fill_pending_nas_info(asn1::rrc::rrc_conn_recfg_r8_ies_s* msg); const std::map& get_erabs() const { return erabs; } const asn1::rrc::drb_to_add_mod_list_l& get_established_drbs() const { return current_drbs; } diff --git a/srsenb/hdr/stack/upper/gtpu.h b/srsenb/hdr/stack/upper/gtpu.h index d24de3902..7d25ae37e 100644 --- a/srsenb/hdr/stack/upper/gtpu.h +++ b/srsenb/hdr/stack/upper/gtpu.h @@ -39,10 +39,16 @@ class stack_interface_gtpu_lte; class gtpu_tunnel_manager { - using buffered_sdu_list = srsran::bounded_vector, 512>; + // Buffer used to store SDUs while PDCP is still getting configured during handover. + // Note: The buffer cannot be too large, otherwise it risks depleting the byte buffer pool. + const static size_t BUFFER_SIZE = 512; + using buffered_sdu_list = srsran::bounded_vector, BUFFER_SIZE>; + + static const uint32_t undefined_pdcp_sn = std::numeric_limits::max(); public: - const static size_t MAX_TUNNELS_PER_UE = 4; + // A UE should have <= 3 DRBs active, and each DRB should have two tunnels active at the same time at most + const static size_t MAX_TUNNELS_PER_UE = 6; enum class tunnel_state { pdcp_active, buffering, forward_to, forwarded_from }; @@ -105,7 +111,6 @@ public: bool remove_rnti(uint16_t rnti); private: - static const uint32_t undefined_pdcp_sn = std::numeric_limits::max(); using tunnel_list_t = srsran::static_id_obj_pool; using tunnel_ctxt_it = typename tunnel_list_t::iterator; @@ -136,15 +141,15 @@ public: void stop(); // gtpu_interface_rrc - uint32_t add_bearer(uint16_t rnti, - uint32_t lcid, - 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; + srsran::expected add_bearer(uint16_t rnti, + uint32_t lcid, + 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; // gtpu_interface_pdcp void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) override; diff --git a/srsenb/src/stack/rrc/rrc.cc b/srsenb/src/stack/rrc/rrc.cc index 253aafb46..e4e16058c 100644 --- a/srsenb/src/stack/rrc/rrc.cc +++ b/srsenb/src/stack/rrc/rrc.cc @@ -182,7 +182,6 @@ int rrc::add_user(uint16_t rnti, const sched_interface::ue_cfg_t& sched_ue_cfg) } if (rnti == SRSRAN_MRNTI) { - uint32_t teid_in = 1; for (auto& mbms_item : mcch.msg.c1().mbsfn_area_cfg_r9().pmch_info_list_r9[0].mbms_session_info_list_r9) { uint32_t lcid = mbms_item.lc_ch_id_r9; @@ -190,7 +189,7 @@ int rrc::add_user(uint16_t rnti, const sched_interface::ue_cfg_t& sched_ue_cfg) mac->ue_cfg(SRSRAN_MRNTI, NULL); rlc->add_bearer_mrb(SRSRAN_MRNTI, lcid); pdcp->add_bearer(SRSRAN_MRNTI, lcid, srsran::make_drb_pdcp_config_t(1, false)); - teid_in = gtpu->add_bearer(SRSRAN_MRNTI, lcid, 1, 1); + gtpu->add_bearer(SRSRAN_MRNTI, lcid, 1, 1); } } return SRSRAN_SUCCESS; diff --git a/srsenb/src/stack/rrc/rrc_bearer_cfg.cc b/srsenb/src/stack/rrc/rrc_bearer_cfg.cc index d9a6f3b89..e51926e17 100644 --- a/srsenb/src/stack/rrc/rrc_bearer_cfg.cc +++ b/srsenb/src/stack/rrc/rrc_bearer_cfg.cc @@ -309,32 +309,41 @@ bool bearer_cfg_handler::modify_erab(uint8_t void bearer_cfg_handler::add_gtpu_bearer(uint32_t erab_id) { auto it = erabs.find(erab_id); - if (it == erabs.end()) { - logger->error("Adding erab_id=%d to GTPU", erab_id); - return; + if (it != erabs.end()) { + srsran::expected teidin = + add_gtpu_bearer(erab_id, it->second.teid_out, it->second.address.to_number(), nullptr); + if (teidin.has_value()) { + it->second.teid_in = teidin.value(); + return; + } } - it->second.teid_in = add_gtpu_bearer(erab_id, it->second.teid_out, it->second.address.to_number(), nullptr); + logger->error("Adding erab_id=%d to GTPU", erab_id); } -uint32_t bearer_cfg_handler::add_gtpu_bearer(uint32_t erab_id, - uint32_t teid_out, - uint32_t addr, - const gtpu_interface_rrc::bearer_props* props) +srsran::expected bearer_cfg_handler::add_gtpu_bearer(uint32_t erab_id, + uint32_t teid_out, + uint32_t addr, + const gtpu_interface_rrc::bearer_props* props) { auto it = erabs.find(erab_id); if (it == erabs.end()) { logger->error("Adding erab_id=%d to GTPU", erab_id); - return 0; + return srsran::default_error_t(); } // Initialize ERAB tunnel in GTPU right-away. DRBs are only created during RRC setup/reconf erab_t& erab = it->second; erab_t::gtpu_tunnel bearer; - bearer.teid_out = teid_out; - bearer.addr = addr; - bearer.teid_in = gtpu->add_bearer(rnti, erab.id - 2, addr, teid_out, props); + bearer.teid_out = teid_out; + bearer.addr = addr; + srsran::expected teidin = gtpu->add_bearer(rnti, erab.id - 2, addr, teid_out, props); + if (teidin.is_error()) { + logger->error("Adding erab_id=%d to GTPU", erab_id); + return srsran::default_error_t(); + } + bearer.teid_in = teidin.value(); erab.tunnels.push_back(bearer); - return bearer.teid_in; + return teidin; } void bearer_cfg_handler::rem_gtpu_bearer(uint32_t erab_id) diff --git a/srsenb/src/stack/rrc/rrc_mobility.cc b/srsenb/src/stack/rrc/rrc_mobility.cc index 16a5433a0..9ba7cca19 100644 --- a/srsenb/src/stack/rrc/rrc_mobility.cc +++ b/srsenb/src/stack/rrc/rrc_mobility.cc @@ -333,7 +333,7 @@ bool rrc::ue::rrc_mobility::start_ho_preparation(uint32_t target_eci, logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); return false; } - asn1::bit_ref bref(buffer->msg, buffer->get_tailroom()); + asn1::bit_ref bref(buffer->msg, buffer->get_tailroom()); if (rrc_ue->eutra_capabilities.pack(bref) == asn1::SRSASN_ERROR_ENCODE_FAIL) { logger.error("Failed to pack UE EUTRA Capability"); return false; @@ -376,7 +376,7 @@ bool rrc::ue::rrc_mobility::start_ho_preparation(uint32_t target_eci, logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); return false; } - asn1::bit_ref bref(buffer->msg, buffer->get_tailroom()); + asn1::bit_ref bref(buffer->msg, buffer->get_tailroom()); if (hoprep.pack(bref) == asn1::SRSASN_ERROR_ENCODE_FAIL) { Error("Failed to pack HO preparation msg"); return false; @@ -782,12 +782,17 @@ void rrc::ue::rrc_mobility::handle_ho_requested(idle_st& s, const ho_req_rx_ev& fwd_erab.dl_forwarding.value == asn1::s1ap::dl_forwarding_opts::dl_forwarding_proposed) { admitted_erab.dl_g_tp_teid_present = true; gtpu_interface_rrc::bearer_props props; - props.flush_before_teidin_present = true; - props.flush_before_teidin = erab.second.teid_in; - uint32_t dl_teid_in = rrc_ue->bearer_list.add_gtpu_bearer( + props.flush_before_teidin_present = true; + props.flush_before_teidin = erab.second.teid_in; + srsran::expected 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); - srsran::uint32_to_uint8(dl_teid_in, admitted_erabs.back().dl_g_tp_teid.data()); + if (not dl_teid_in.has_value()) { + logger.error("Failed to allocate GTPU TEID"); + trigger(srsran::failure_ev{}); + return; + } + fwd_tunnels.push_back(dl_teid_in.value()); + srsran::uint32_to_uint8(dl_teid_in.value(), admitted_erabs.back().dl_g_tp_teid.data()); } } } diff --git a/srsenb/src/stack/upper/gtpu.cc b/srsenb/src/stack/upper/gtpu.cc index a18e31b26..978bfb565 100644 --- a/srsenb/src/stack/upper/gtpu.cc +++ b/srsenb/src/stack/upper/gtpu.cc @@ -414,12 +414,13 @@ void gtpu::send_pdu_to_tunnel(const gtpu_tunnel& tx_tun, srsran::unique_byte_buf } } -uint32_t gtpu::add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out, const bearer_props* props) +srsran::expected +gtpu::add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out, const bearer_props* props) { // Allocate a TEID for the incoming tunnel const gtpu_tunnel* new_tun = tunnels.add_tunnel(rnti, lcid, teid_out, addr); if (new_tun == nullptr) { - return -1; + return default_error_t(); } uint32_t teid_in = new_tun->teid_in; @@ -436,7 +437,7 @@ uint32_t gtpu::add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t if (props->forward_from_teidin_present) { if (create_dl_fwd_tunnel(props->forward_from_teidin, teid_in) != SRSRAN_SUCCESS) { rem_tunnel(teid_in); - return -1; + return default_error_t(); } } } diff --git a/srsenb/test/common/dummy_classes.h b/srsenb/test/common/dummy_classes.h index 400790bf5..681edaffb 100644 --- a/srsenb/test/common/dummy_classes.h +++ b/srsenb/test/common/dummy_classes.h @@ -148,10 +148,10 @@ public: class gtpu_dummy : public gtpu_interface_rrc { public: - uint32_t + srsran::expected add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out, const bearer_props* props) override { - return 0; + return 1; } void set_tunnel_status(uint32_t teidin, bool dl_active) override {} void rem_bearer(uint16_t rnti, uint32_t lcid) override {} diff --git a/srsenb/test/mac/sched_common_test_suite.h b/srsenb/test/mac/sched_common_test_suite.h index 2e1ecac56..05c790c28 100644 --- a/srsenb/test/mac/sched_common_test_suite.h +++ b/srsenb/test/mac/sched_common_test_suite.h @@ -15,6 +15,7 @@ #include "srsenb/hdr/stack/mac/sched_common.h" #include "srsran/adt/bounded_bitset.h" +#include "srsran/adt/span.h" #include "srsran/common/tti_point.h" #include "srsran/interfaces/sched_interface.h" diff --git a/srsenb/test/upper/gtpu_test.cc b/srsenb/test/upper/gtpu_test.cc index 16332ce6b..701cab138 100644 --- a/srsenb/test/upper/gtpu_test.cc +++ b/srsenb/test/upper/gtpu_test.cc @@ -216,8 +216,8 @@ int test_gtpu_direct_tunneling(tunnel_test_event event) tenb_gtpu.init(tenb_addr_str, sgw_addr_str, "", "", &tenb_pdcp, &tenb_stack, false); // create tunnels MME-SeNB and MME-TeNB - uint32_t senb_teid_in = senb_gtpu.add_bearer(rnti, drb1, sgw_addr, sgw_teidout1); - uint32_t tenb_teid_in = tenb_gtpu.add_bearer(rnti2, drb1, sgw_addr, sgw_teidout2); + uint32_t senb_teid_in = senb_gtpu.add_bearer(rnti, drb1, sgw_addr, sgw_teidout1).value(); + uint32_t tenb_teid_in = tenb_gtpu.add_bearer(rnti2, drb1, sgw_addr, sgw_teidout2).value(); // Buffer PDUs in SeNB PDCP for (size_t sn = 6; sn < 10; ++sn) { @@ -230,7 +230,7 @@ int test_gtpu_direct_tunneling(tunnel_test_event event) gtpu::bearer_props props; props.flush_before_teidin_present = true; props.flush_before_teidin = tenb_teid_in; - uint32_t dl_tenb_teid_in = tenb_gtpu.add_bearer(rnti2, drb1, senb_addr, 0, &props); + uint32_t dl_tenb_teid_in = tenb_gtpu.add_bearer(rnti2, drb1, senb_addr, 0, &props).value(); props = {}; props.forward_from_teidin_present = true; props.forward_from_teidin = senb_teid_in;