mirror of https://github.com/PentHertz/srsLTE.git
use of more space efficient sorted vector structure for lcid tunnels of a rnti
This commit is contained in:
parent
eba0edea4a
commit
c201eb7708
|
@ -246,6 +246,14 @@ private:
|
|||
size_t count = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Operates like a circular map, but automatically assigns the ID/key to inserted objects in a monotonically
|
||||
* increasing way. The assigned IDs are not necessarily contiguous, as they are selected based on the available slots
|
||||
* in the circular map
|
||||
* @tparam K type of ID/key
|
||||
* @tparam T object being inserted
|
||||
* @tparam MAX_N maximum size of pool
|
||||
*/
|
||||
template <typename K, typename T, size_t MAX_N>
|
||||
class static_id_obj_pool : private static_circular_map<K, T, MAX_N>
|
||||
{
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <unordered_map>
|
||||
|
||||
#include "common_enb.h"
|
||||
#include "srsran/adt/bounded_vector.h"
|
||||
#include "srsran/adt/circular_map.h"
|
||||
#include "srsran/common/buffer_pool.h"
|
||||
#include "srsran/common/task_scheduler.h"
|
||||
|
@ -56,14 +57,23 @@ class gtpu_tunnel_manager
|
|||
{
|
||||
public:
|
||||
const static size_t MAX_TUNNELS_PER_UE = 4;
|
||||
using lcid_teid_list = std::vector<uint32_t>;
|
||||
using ue_lcid_tunnel_list = srsran::static_circular_map<uint16_t, lcid_teid_list, MAX_TUNNELS_PER_UE>;
|
||||
struct lcid_tunnel {
|
||||
uint32_t lcid;
|
||||
uint32_t teid;
|
||||
|
||||
bool operator<(const lcid_tunnel& other) const
|
||||
{
|
||||
return lcid < other.lcid or (lcid == other.lcid and teid < other.teid);
|
||||
}
|
||||
bool operator==(const lcid_tunnel& other) const { return lcid == other.lcid and teid == other.teid; }
|
||||
};
|
||||
using ue_lcid_tunnel_list = srsran::bounded_vector<lcid_tunnel, MAX_TUNNELS_PER_UE>;
|
||||
|
||||
gtpu_tunnel_manager();
|
||||
|
||||
gtpu_tunnel* find_tunnel(uint32_t teid);
|
||||
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<lcid_tunnel> find_rnti_lcid_tunnels(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);
|
||||
|
|
|
@ -45,21 +45,28 @@ gtpu_tunnel_manager::ue_lcid_tunnel_list* gtpu_tunnel_manager::find_rnti_tunnels
|
|||
return &ue_teidin_db[rnti];
|
||||
}
|
||||
|
||||
srsran::span<uint32_t> gtpu_tunnel_manager::find_rnti_lcid_tunnels(uint16_t rnti, uint32_t lcid)
|
||||
srsran::span<gtpu_tunnel_manager::lcid_tunnel> gtpu_tunnel_manager::find_rnti_lcid_tunnels(uint16_t rnti, uint32_t lcid)
|
||||
{
|
||||
if (lcid < SRSENB_N_SRB or lcid >= SRSENB_N_RADIO_BEARERS) {
|
||||
logger.warning("Searching for bearer with invalid lcid=%d", lcid);
|
||||
return {};
|
||||
}
|
||||
auto* ue_ptr = find_rnti_tunnels(rnti);
|
||||
if (ue_ptr == nullptr or not ue_ptr->contains(lcid)) {
|
||||
if (ue_ptr == nullptr) {
|
||||
return {};
|
||||
}
|
||||
return (*ue_ptr)[lcid];
|
||||
auto lcid_it_begin = std::lower_bound(ue_ptr->begin(), ue_ptr->end(), lcid_tunnel{lcid, 0});
|
||||
auto lcid_it_end = std::lower_bound(ue_ptr->begin(), ue_ptr->end(), lcid_tunnel{lcid + 1, 0});
|
||||
|
||||
return srsran::span<lcid_tunnel>(&(*lcid_it_begin), &(*lcid_it_end));
|
||||
}
|
||||
|
||||
gtpu_tunnel* gtpu_tunnel_manager::add_tunnel(uint16_t rnti, uint32_t lcid, uint32_t teidout, uint32_t spgw_addr)
|
||||
{
|
||||
if (lcid < SRSENB_N_SRB or lcid >= SRSENB_N_RADIO_BEARERS) {
|
||||
logger.warning("Adding TEID with invalid parmaters");
|
||||
return nullptr;
|
||||
}
|
||||
auto ret_pair = tunnels.insert(gtpu_tunnel());
|
||||
if (not ret_pair) {
|
||||
logger.warning("Adding new GTPU TEID In");
|
||||
|
@ -75,10 +82,15 @@ gtpu_tunnel* gtpu_tunnel_manager::add_tunnel(uint16_t rnti, uint32_t lcid, uint3
|
|||
if (not ue_teidin_db.contains(rnti)) {
|
||||
ue_teidin_db.insert(rnti, ue_lcid_tunnel_list());
|
||||
}
|
||||
if (not ue_teidin_db[rnti].contains(lcid)) {
|
||||
ue_teidin_db[rnti].insert(lcid, std::vector<uint32_t>());
|
||||
auto& ue_tunnels = ue_teidin_db[rnti];
|
||||
|
||||
if (ue_tunnels.full()) {
|
||||
logger.error("The number of TEIDs per UE exceeded for rnti=0x%x", rnti);
|
||||
tunnels.erase(tun->teid_in);
|
||||
return nullptr;
|
||||
}
|
||||
ue_teidin_db[rnti][lcid].push_back(tun->teid_in);
|
||||
ue_tunnels.push_back(lcid_tunnel{lcid, tun->teid_in});
|
||||
std::sort(ue_tunnels.begin(), ue_tunnels.end());
|
||||
|
||||
fmt::memory_buffer str_buffer;
|
||||
srsran::gtpu_ntoa(str_buffer, htonl(spgw_addr));
|
||||
|
@ -107,10 +119,8 @@ bool gtpu_tunnel_manager::update_rnti(uint16_t old_rnti, uint16_t new_rnti)
|
|||
|
||||
// Change TEID in existing tunnels
|
||||
auto* new_rnti_ptr = find_rnti_tunnels(new_rnti);
|
||||
for (auto& bearer : *new_rnti_ptr) {
|
||||
for (uint32_t teid : bearer.second) {
|
||||
tunnels[teid].rnti = new_rnti;
|
||||
}
|
||||
for (lcid_tunnel& bearer : *new_rnti_ptr) {
|
||||
tunnels[bearer.teid].rnti = new_rnti;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -124,11 +134,11 @@ bool gtpu_tunnel_manager::remove_tunnel(uint32_t teidin)
|
|||
return false;
|
||||
}
|
||||
gtpu_tunnel& tun = it->second;
|
||||
srsran_assert(ue_teidin_db.contains(tun.rnti) or ue_teidin_db[tun.rnti].contains(tun.lcid),
|
||||
"inconsistency in internal data structs");
|
||||
|
||||
std::vector<uint32_t>& lcids = ue_teidin_db[tun.rnti][tun.lcid];
|
||||
lcids.erase(std::remove(lcids.begin(), lcids.end(), teidin), lcids.end());
|
||||
// erase keeping the relative order
|
||||
auto& ue = ue_teidin_db[tun.rnti];
|
||||
auto lcid_it = std::find(ue.begin(), ue.end(), lcid_tunnel{tun.lcid, tun.teid_in});
|
||||
ue.erase(lcid_it);
|
||||
|
||||
logger.info("TEID In=%d for rnti=0x%x erased", teidin, tun.rnti);
|
||||
tunnels.erase(it);
|
||||
|
@ -137,18 +147,16 @@ bool gtpu_tunnel_manager::remove_tunnel(uint32_t teidin)
|
|||
|
||||
bool gtpu_tunnel_manager::remove_bearer(uint16_t rnti, uint32_t lcid)
|
||||
{
|
||||
ue_lcid_tunnel_list* ue_ptr = find_rnti_tunnels(rnti);
|
||||
if (ue_ptr == nullptr or not ue_ptr->contains(lcid)) {
|
||||
logger.warning("Removing rnti=0x%x, lcid=%d", rnti, lcid);
|
||||
srsran::span<lcid_tunnel> to_rem = find_rnti_lcid_tunnels(rnti, lcid);
|
||||
if (to_rem.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
logger.info("Removing rnti=0x%x,lcid=%d", rnti, lcid);
|
||||
lcid_teid_list& lcid_list = (*ue_ptr)[lcid];
|
||||
for (uint32_t teid : lcid_list) {
|
||||
srsran_expect(tunnels.erase(teid) > 0, "Inconsistency detected between two internal data structures");
|
||||
|
||||
for (lcid_tunnel& lcid_tun : to_rem) {
|
||||
srsran_expect(tunnels.erase(lcid_tun.teid) > 0, "Inconsistency detected between two internal data structures");
|
||||
}
|
||||
ue_ptr->erase(lcid);
|
||||
ue_teidin_db[rnti].erase(to_rem.begin(), to_rem.end());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -160,10 +168,8 @@ bool gtpu_tunnel_manager::remove_rnti(uint16_t rnti)
|
|||
}
|
||||
logger.info("Removing rnti=0x%x", rnti);
|
||||
|
||||
for (auto& lcid_pair : ue_teidin_db[rnti]) {
|
||||
for (uint32_t teid : lcid_pair.second) {
|
||||
srsran_expect(tunnels.erase(teid) > 0, "Inconsistency detected between two internal data structures");
|
||||
}
|
||||
for (lcid_tunnel& ue_tuns : ue_teidin_db[rnti]) {
|
||||
srsran_expect(tunnels.erase(ue_tuns.teid) > 0, "Inconsistency detected between two internal data structures");
|
||||
}
|
||||
ue_teidin_db.erase(rnti);
|
||||
return true;
|
||||
|
@ -249,12 +255,12 @@ void gtpu::stop()
|
|||
// gtpu_interface_pdcp
|
||||
void gtpu::write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu)
|
||||
{
|
||||
srsran::span<uint32_t> teids = tunnels.find_rnti_lcid_tunnels(rnti, lcid);
|
||||
srsran::span<gtpu_tunnel_manager::lcid_tunnel> teids = tunnels.find_rnti_lcid_tunnels(rnti, lcid);
|
||||
if (teids.empty()) {
|
||||
logger.warning("The rnti=0x%x,lcid=%d does not have any active tunnel", rnti, lcid);
|
||||
return;
|
||||
}
|
||||
gtpu_tunnel& tx_tun = *tunnels.find_tunnel(teids[0]);
|
||||
gtpu_tunnel& tx_tun = *tunnels.find_tunnel(teids[0].teid);
|
||||
log_message(tx_tun, false, srsran::make_span(pdu));
|
||||
send_pdu_to_tunnel(tx_tun, std::move(pdu));
|
||||
}
|
||||
|
@ -415,10 +421,10 @@ void gtpu::handle_end_marker(gtpu_tunnel& rx_tunnel)
|
|||
rem_tunnel(rx_tunnel.teid_in);
|
||||
} else {
|
||||
// TeNB switches paths, and flushes PDUs that have been buffered
|
||||
srsran::span<uint32_t> lcid_tunnels = tunnels.find_rnti_lcid_tunnels(rnti, rx_tunnel.lcid);
|
||||
for (uint32_t new_teidin : lcid_tunnels) {
|
||||
gtpu_tunnel* new_tun = tunnels.find_tunnel(new_teidin);
|
||||
if (new_teidin != rx_tunnel.teid_in and new_tun->prior_teid_in_present and
|
||||
srsran::span<gtpu_tunnel_manager::lcid_tunnel> lcid_tunnels = tunnels.find_rnti_lcid_tunnels(rnti, rx_tunnel.lcid);
|
||||
for (auto& lcid_tun : lcid_tunnels) {
|
||||
gtpu_tunnel* new_tun = tunnels.find_tunnel(lcid_tun.teid);
|
||||
if (new_tun->teid_in != rx_tunnel.teid_in and new_tun->prior_teid_in_present and
|
||||
new_tun->prior_teid_in == rx_tunnel.teid_in) {
|
||||
rem_tunnel(new_tun->prior_teid_in);
|
||||
new_tun->prior_teid_in_present = false;
|
||||
|
|
Loading…
Reference in New Issue