gtpu - added comments, updated expected construct, handled in rrc the case a gtpu teid fails to allocate

master
Francisco 4 years ago committed by Francisco Paisana
parent 82b34f3b3f
commit 5eccfad05b

@ -29,7 +29,9 @@ class expected
public:
expected() : has_val(true), val(T{}) {}
expected(T&& t) : has_val(true), val(std::forward<T>(t)) {}
expected(const T& t) : has_val(true), val(t) {}
expected(E&& e) : has_val(false), unexpected(std::forward<E>(e)) {}
expected(const E& e) : has_val(false), unexpected(e) {}
expected(const expected& other)
{
if (other.has_val) {

@ -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 <typename T>
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 <typename... CtorArgs>
void emplace(CtorArgs&&... args)

@ -14,6 +14,7 @@
#define SRSRAN_BYTE_BUFFER_H
#include "common.h"
#include "srsran/adt/span.h"
#include <chrono>
#include <cstdint>

@ -17,7 +17,6 @@
INCLUDES
*******************************************************************************/
#include "srsran/adt/span.h"
#include <chrono>
#include <memory>
#include <stdint.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<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;

@ -91,13 +91,13 @@ public:
const asn1::unbounded_octstring<true>* 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<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);
const std::map<uint8_t, erab_t>& get_erabs() const { return erabs; }
const asn1::rrc::drb_to_add_mod_list_l& get_established_drbs() const { return current_drbs; }

@ -39,10 +39,16 @@ class stack_interface_gtpu_lte;
class gtpu_tunnel_manager
{
using buffered_sdu_list = srsran::bounded_vector<std::pair<uint32_t, srsran::unique_byte_buffer_t>, 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<std::pair<uint32_t, srsran::unique_byte_buffer_t>, BUFFER_SIZE>;
static const uint32_t undefined_pdcp_sn = std::numeric_limits<uint32_t>::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<uint32_t>::max();
using tunnel_list_t = srsran::static_id_obj_pool<uint32_t, tunnel, SRSENB_MAX_UES * MAX_TUNNELS_PER_UE>;
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<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;
// gtpu_interface_pdcp
void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) override;

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

@ -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<uint32_t> 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<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)
{
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<uint32_t> 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)

@ -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<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);
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());
}
}
}

@ -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<uint32_t>
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();
}
}
}

@ -148,10 +148,10 @@ public:
class gtpu_dummy : public gtpu_interface_rrc
{
public:
uint32_t
srsran::expected<uint32_t>
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 {}

@ -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"

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

Loading…
Cancel
Save