creation of static id obj pool class. Application of this class to gtpu tunnels container to avoid allocations

This commit is contained in:
Francisco 2021-03-24 11:21:41 +00:00 committed by Francisco Paisana
parent 3cf5e85b20
commit eba0edea4a
3 changed files with 71 additions and 32 deletions

View File

@ -214,6 +214,7 @@ public:
size_t size() const { return count; } size_t size() const { return count; }
bool empty() const { return count == 0; } bool empty() const { return count == 0; }
bool full() const { return count == N; } bool full() const { return count == N; }
bool has_space(K id) { return not present[id % N]; }
size_t capacity() const { return N; } size_t capacity() const { return N; }
iterator begin() { return iterator(this, 0); } iterator begin() { return iterator(this, 0); }
@ -245,6 +246,44 @@ private:
size_t count = 0; size_t count = 0;
}; };
template <typename K, typename T, size_t MAX_N>
class static_id_obj_pool : private static_circular_map<K, T, MAX_N>
{
using base_t = static_circular_map<K, T, MAX_N>;
public:
using iterator = typename base_t::iterator;
using const_iterator = typename base_t::const_iterator;
using base_t::operator[];
using base_t::begin;
using base_t::contains;
using base_t::empty;
using base_t::end;
using base_t::erase;
using base_t::find;
using base_t::full;
using base_t::size;
explicit static_id_obj_pool(K first_id = 0) : next_id(first_id) {}
template <typename U>
srsran::expected<K> insert(U&& t)
{
if (full()) {
return srsran::default_error_t{};
}
while (not base_t::has_space(next_id)) {
++next_id;
}
base_t::insert(next_id, std::forward<U>(t));
return next_id++;
}
private:
K next_id = 0;
};
} // namespace srsran } // namespace srsran
#endif // SRSRAN_ID_MAP_H #endif // SRSRAN_ID_MAP_H

View File

@ -55,8 +55,9 @@ struct gtpu_tunnel {
class gtpu_tunnel_manager class gtpu_tunnel_manager
{ {
public: public:
const static size_t MAX_TUNNELS_PER_UE = 4;
using lcid_teid_list = std::vector<uint32_t>; using lcid_teid_list = std::vector<uint32_t>;
using ue_lcid_tunnel_list = srsran::static_circular_map<uint16_t, lcid_teid_list, SRSENB_N_RADIO_BEARERS>; using ue_lcid_tunnel_list = srsran::static_circular_map<uint16_t, lcid_teid_list, MAX_TUNNELS_PER_UE>;
gtpu_tunnel_manager(); gtpu_tunnel_manager();
@ -64,7 +65,7 @@ public:
ue_lcid_tunnel_list* find_rnti_tunnels(uint16_t rnti); ue_lcid_tunnel_list* find_rnti_tunnels(uint16_t rnti);
srsran::span<uint32_t> find_rnti_lcid_tunnels(uint16_t rnti, uint32_t lcid); srsran::span<uint32_t> find_rnti_lcid_tunnels(uint16_t rnti, uint32_t lcid);
gtpu_tunnel* add_tunnel(uint32_t teid, uint16_t rnti, uint32_t lcid); gtpu_tunnel* add_tunnel(uint16_t rnti, uint32_t lcid, uint32_t teidout, uint32_t spgw_addr);
bool update_rnti(uint16_t old_rnti, uint16_t new_rnti); bool update_rnti(uint16_t old_rnti, uint16_t new_rnti);
bool remove_tunnel(uint32_t teid); bool remove_tunnel(uint32_t teid);
@ -74,7 +75,7 @@ public:
private: private:
srslog::basic_logger& logger; srslog::basic_logger& logger;
std::unordered_map<uint32_t, gtpu_tunnel> tunnels; srsran::static_id_obj_pool<uint32_t, gtpu_tunnel, SRSENB_MAX_UES * MAX_TUNNELS_PER_UE> tunnels;
srsran::static_circular_map<uint16_t, ue_lcid_tunnel_list, SRSENB_MAX_UES> ue_teidin_db; srsran::static_circular_map<uint16_t, ue_lcid_tunnel_list, SRSENB_MAX_UES> ue_teidin_db;
}; };
@ -160,7 +161,7 @@ private:
// Socket file descriptor // Socket file descriptor
int fd = -1; int fd = -1;
void send_pdu_to_tunnel(gtpu_tunnel& tx_tun, srsran::unique_byte_buffer_t pdu, int pdcp_sn = -1); void send_pdu_to_tunnel(const gtpu_tunnel& tx_tun, srsran::unique_byte_buffer_t pdu, int pdcp_sn = -1);
void echo_response(in_addr_t addr, in_port_t port, uint16_t seq); void echo_response(in_addr_t addr, in_port_t port, uint16_t seq);
void error_indication(in_addr_t addr, in_port_t port, uint32_t err_teid); void error_indication(in_addr_t addr, in_port_t port, uint32_t err_teid);
@ -175,8 +176,6 @@ private:
/**************************************************************************** /****************************************************************************
* TEID to RNIT/LCID helper functions * TEID to RNIT/LCID helper functions
***************************************************************************/ ***************************************************************************/
uint32_t next_teid_in = 0;
void log_message(const gtpu_tunnel& tun, bool is_rx, srsran::span<uint8_t> pdu, int pdcp_sn = -1); void log_message(const gtpu_tunnel& tun, bool is_rx, srsran::span<uint8_t> pdu, int pdcp_sn = -1);
}; };

View File

@ -58,13 +58,19 @@ srsran::span<uint32_t> gtpu_tunnel_manager::find_rnti_lcid_tunnels(uint16_t rnti
return (*ue_ptr)[lcid]; return (*ue_ptr)[lcid];
} }
gtpu_tunnel* gtpu_tunnel_manager::add_tunnel(uint32_t teidin, uint16_t rnti, uint32_t lcid) gtpu_tunnel* gtpu_tunnel_manager::add_tunnel(uint16_t rnti, uint32_t lcid, uint32_t teidout, uint32_t spgw_addr)
{ {
auto ret_pair = tunnels.emplace(teidin, gtpu_tunnel()); auto ret_pair = tunnels.insert(gtpu_tunnel());
if (not ret_pair.second) { if (not ret_pair) {
logger.warning("Adding GTPU TEID In=0x%x", teidin); logger.warning("Adding new GTPU TEID In");
return nullptr; return nullptr;
} }
gtpu_tunnel* tun = &tunnels[ret_pair.value()];
tun->teid_in = ret_pair.value();
tun->rnti = rnti;
tun->lcid = lcid;
tun->teid_out = teidout;
tun->spgw_addr = spgw_addr;
if (not ue_teidin_db.contains(rnti)) { if (not ue_teidin_db.contains(rnti)) {
ue_teidin_db.insert(rnti, ue_lcid_tunnel_list()); ue_teidin_db.insert(rnti, ue_lcid_tunnel_list());
@ -72,9 +78,18 @@ gtpu_tunnel* gtpu_tunnel_manager::add_tunnel(uint32_t teidin, uint16_t rnti, uin
if (not ue_teidin_db[rnti].contains(lcid)) { if (not ue_teidin_db[rnti].contains(lcid)) {
ue_teidin_db[rnti].insert(lcid, std::vector<uint32_t>()); ue_teidin_db[rnti].insert(lcid, std::vector<uint32_t>());
} }
ue_teidin_db[rnti][lcid].push_back(teidin); ue_teidin_db[rnti][lcid].push_back(tun->teid_in);
return &ret_pair.first->second; fmt::memory_buffer str_buffer;
srsran::gtpu_ntoa(str_buffer, htonl(spgw_addr));
logger.info("New tunnel teid_in=0x%x, teid_out=0x%x, rnti=0x%x, lcid=%d, addr=%s",
tun->teid_in,
teidout,
rnti,
lcid,
srsran::to_c_str(str_buffer));
return tun;
} }
bool gtpu_tunnel_manager::update_rnti(uint16_t old_rnti, uint16_t new_rnti) bool gtpu_tunnel_manager::update_rnti(uint16_t old_rnti, uint16_t new_rnti)
@ -244,7 +259,7 @@ void gtpu::write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t
send_pdu_to_tunnel(tx_tun, std::move(pdu)); send_pdu_to_tunnel(tx_tun, std::move(pdu));
} }
void gtpu::send_pdu_to_tunnel(gtpu_tunnel& tx_tun, srsran::unique_byte_buffer_t pdu, int pdcp_sn) void gtpu::send_pdu_to_tunnel(const gtpu_tunnel& tx_tun, srsran::unique_byte_buffer_t pdu, int pdcp_sn)
{ {
// Check valid IP version // Check valid IP version
struct iphdr* ip_pkt = (struct iphdr*)pdu->msg; struct iphdr* ip_pkt = (struct iphdr*)pdu->msg;
@ -286,25 +301,11 @@ void gtpu::send_pdu_to_tunnel(gtpu_tunnel& tx_tun, srsran::unique_byte_buffer_t
uint32_t gtpu::add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out, const bearer_props* props) 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 // Allocate a TEID for the incoming tunnel
uint32_t teid_in = ++next_teid_in; gtpu_tunnel* new_tun = tunnels.add_tunnel(rnti, lcid, teid_out, addr);
gtpu_tunnel* new_tun = tunnels.add_tunnel(teid_in, rnti, lcid);
if (new_tun == nullptr) { if (new_tun == nullptr) {
return -1; return -1;
} }
new_tun->teid_in = teid_in; uint32_t teid_in = new_tun->teid_in;
new_tun->rnti = rnti;
new_tun->lcid = lcid;
new_tun->spgw_addr = addr;
new_tun->teid_out = teid_out;
fmt::memory_buffer str_buffer;
srsran::gtpu_ntoa(str_buffer, htonl(addr));
logger.info("New tunnel teid_in=0x%x, teid_out=0x%x, rnti=0x%x, lcid=%d, addr=%s",
teid_in,
teid_out,
rnti,
lcid,
srsran::to_c_str(str_buffer));
if (props != nullptr) { if (props != nullptr) {
if (props->flush_before_teidin_present) { if (props->flush_before_teidin_present) {
@ -489,7 +490,7 @@ void gtpu::handle_msg_data_pdu(const gtpu_header_t& header, gtpu_tunnel& rx_tunn
if (rx_tunnel.fwd_teid_in_present) { if (rx_tunnel.fwd_teid_in_present) {
// Forward SDU to direct/indirect tunnel during Handover // Forward SDU to direct/indirect tunnel during Handover
gtpu_tunnel* tx_tun_ptr = tunnels.find_tunnel(rx_tunnel.fwd_teid_in); const gtpu_tunnel* tx_tun_ptr = tunnels.find_tunnel(rx_tunnel.fwd_teid_in);
if (tx_tun_ptr == nullptr) { if (tx_tun_ptr == nullptr) {
logger.error("Forwarding tunnel TEID=%d does not exist", rx_tunnel.fwd_teid_in); logger.error("Forwarding tunnel TEID=%d does not exist", rx_tunnel.fwd_teid_in);
return; return;