stack lte: create an gtpu-pdcp adapter class that correctly converts lcids to eps bearers and vice-versa

master
Francisco Paisana 3 years ago
parent 4b2f079581
commit 2ade4628ca

@ -49,6 +49,8 @@ public:
struct radio_bearer_t { struct radio_bearer_t {
srsran::srsran_rat_t rat; srsran::srsran_rat_t rat;
uint32_t lcid; uint32_t lcid;
uint32_t eps_bearer_id;
bool is_valid() const { return rat != srsran_rat_t::nulltype; }
}; };
/// Single user interface (for UE) /// Single user interface (for UE)
@ -69,6 +71,8 @@ public:
// Stack interface to retrieve active RB // Stack interface to retrieve active RB
radio_bearer_t get_radio_bearer(uint32_t eps_bearer_id); radio_bearer_t get_radio_bearer(uint32_t eps_bearer_id);
radio_bearer_t get_lcid_bearer(uint16_t rnti, uint32_t lcid);
/// Multi-user interface (see comments above) /// Multi-user interface (see comments above)
void add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid); void add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid);
void remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id); void remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id);
@ -81,10 +85,14 @@ private:
srslog::basic_logger& logger; srslog::basic_logger& logger;
typedef std::map<uint32_t, radio_bearer_t> eps_rb_map_t; typedef std::map<uint32_t, radio_bearer_t> eps_rb_map_t;
std::map<uint16_t, eps_rb_map_t> users_map; struct user_bearers {
eps_rb_map_t bearers;
std::map<uint32_t, uint32_t> lcid_to_eps_bearer_id;
};
std::map<uint16_t, user_bearers> users_map;
const uint16_t default_key = 0xffff; // dummy RNTI used for public interface without explicit RNTI const uint16_t default_key = 0xffff; // dummy RNTI used for public interface without explicit RNTI
radio_bearer_t invalid_rb = {srsran::srsran_rat_t::nulltype, 0}; radio_bearer_t invalid_rb = {srsran::srsran_rat_t::nulltype, 0, 0};
}; };
} // namespace srsran } // namespace srsran

@ -31,7 +31,7 @@ struct gtpu_args_t {
class gtpu_interface_pdcp class gtpu_interface_pdcp
{ {
public: public:
virtual void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) = 0; virtual void write_pdu(uint16_t rnti, uint32_t bearer_id, srsran::unique_byte_buffer_t pdu) = 0;
}; };
// GTPU interface for RRC // GTPU interface for RRC
@ -45,12 +45,15 @@ public:
uint32_t flush_before_teidin = 0; uint32_t flush_before_teidin = 0;
}; };
virtual srsran::expected<uint32_t> virtual srsran::expected<uint32_t> add_bearer(uint16_t rnti,
add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out, const bearer_props* props = nullptr) = 0; uint32_t eps_bearer_id,
virtual void set_tunnel_status(uint32_t teidin, bool dl_active) = 0; uint32_t addr,
virtual void rem_bearer(uint16_t rnti, uint32_t lcid) = 0; uint32_t teid_out,
virtual void mod_bearer_rnti(uint16_t old_rnti, uint16_t new_rnti) = 0; const bearer_props* props = nullptr) = 0;
virtual void rem_user(uint16_t rnti) = 0; virtual void set_tunnel_status(uint32_t teidin, bool dl_active) = 0;
virtual void rem_bearer(uint16_t rnti, uint32_t eps_bearer_id) = 0;
virtual void mod_bearer_rnti(uint16_t old_rnti, uint16_t new_rnti) = 0;
virtual void rem_user(uint16_t rnti) = 0;
}; };
} // namespace srsenb } // namespace srsenb

@ -32,19 +32,20 @@ void bearer_manager::add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t
void bearer_manager::add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) void bearer_manager::add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid)
{ {
srsran::rwlock_write_guard rw_lock(rwlock); srsran::rwlock_write_guard rw_lock(rwlock);
auto user_it = users_map.find(rnti); auto user_it = users_map.find(rnti);
if (user_it == users_map.end()) { if (user_it == users_map.end()) {
// add empty bearer map // add empty bearer map
users_map.emplace(rnti, eps_rb_map_t{}); auto p = users_map.emplace(rnti, user_bearers{});
user_it = users_map.find(rnti); user_it = p.first;
} }
auto bearer_it = user_it->second.find(eps_bearer_id); auto bearer_it = user_it->second.bearers.find(eps_bearer_id);
if (bearer_it != user_it->second.end()) { if (bearer_it != user_it->second.bearers.end()) {
logger.error("EPS bearer ID %d already registered", eps_bearer_id); logger.error("EPS bearer ID %d already registered", eps_bearer_id);
return; return;
} }
user_it->second.emplace(eps_bearer_id, radio_bearer_t{rat, lcid}); user_it->second.bearers.emplace(eps_bearer_id, radio_bearer_t{rat, lcid, eps_bearer_id});
user_it->second.lcid_to_eps_bearer_id.emplace(lcid, eps_bearer_id);
logger.info("Registered EPS bearer ID %d for lcid=%d over %s-PDCP", eps_bearer_id, lcid, to_string(rat).c_str()); logger.info("Registered EPS bearer ID %d for lcid=%d over %s-PDCP", eps_bearer_id, lcid, to_string(rat).c_str());
} }
@ -63,12 +64,14 @@ void bearer_manager::remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id)
return; return;
} }
auto bearer_it = user_it->second.find(eps_bearer_id); auto bearer_it = user_it->second.bearers.find(eps_bearer_id);
if (bearer_it == user_it->second.end()) { if (bearer_it == user_it->second.bearers.end()) {
logger.error("Can't remove EPS bearer ID %d", eps_bearer_id); logger.error("Can't remove EPS bearer ID %d", eps_bearer_id);
return; return;
} }
user_it->second.erase(bearer_it); uint32_t lcid = bearer_it->second.lcid;
user_it->second.bearers.erase(bearer_it);
user_it->second.lcid_to_eps_bearer_id.erase(lcid);
logger.info("Removed mapping for EPS bearer ID %d", eps_bearer_id); logger.info("Removed mapping for EPS bearer ID %d", eps_bearer_id);
} }
@ -87,7 +90,8 @@ void bearer_manager::reset(uint16_t rnti)
return; return;
} }
user_it->second.clear(); user_it->second.lcid_to_eps_bearer_id.clear();
user_it->second.bearers.clear();
logger.info("Reset EPS bearer manager"); logger.info("Reset EPS bearer manager");
} }
@ -106,7 +110,7 @@ bool bearer_manager::has_active_radio_bearer(uint16_t rnti, uint32_t eps_bearer_
return false; return false;
} }
return user_it->second.find(eps_bearer_id) != user_it->second.end(); return user_it->second.bearers.find(eps_bearer_id) != user_it->second.bearers.end();
} }
// Stack interface // Stack interface
@ -115,6 +119,22 @@ bearer_manager::radio_bearer_t bearer_manager::get_radio_bearer(uint32_t eps_bea
return get_radio_bearer(default_key, eps_bearer_id); return get_radio_bearer(default_key, eps_bearer_id);
} }
bearer_manager::radio_bearer_t bearer_manager::get_lcid_bearer(uint16_t rnti, uint32_t lcid)
{
srsran::rwlock_read_guard rw_lock(rwlock);
auto user_it = users_map.find(rnti);
if (user_it == users_map.end()) {
return invalid_rb;
}
auto lcid_it = user_it->second.lcid_to_eps_bearer_id.find(lcid);
if (lcid_it != user_it->second.lcid_to_eps_bearer_id.end()) {
return user_it->second.bearers.at(lcid_it->second);
}
return invalid_rb;
}
bearer_manager::radio_bearer_t bearer_manager::get_radio_bearer(uint16_t rnti, uint32_t eps_bearer_id) bearer_manager::radio_bearer_t bearer_manager::get_radio_bearer(uint16_t rnti, uint32_t eps_bearer_id)
{ {
srsran::rwlock_read_guard rw_lock(rwlock); srsran::rwlock_read_guard rw_lock(rwlock);
@ -124,10 +144,10 @@ bearer_manager::radio_bearer_t bearer_manager::get_radio_bearer(uint16_t rnti, u
return invalid_rb; return invalid_rb;
} }
if (user_it->second.find(eps_bearer_id) != user_it->second.end()) { if (user_it->second.bearers.find(eps_bearer_id) != user_it->second.bearers.end()) {
return user_it->second.at(eps_bearer_id); return user_it->second.bearers.at(eps_bearer_id);
} }
return invalid_rb; return invalid_rb;
} }
} // namespace srsue } // namespace srsran

@ -36,6 +36,8 @@
namespace srsenb { namespace srsenb {
class gtpu_pdcp_adapter;
class enb_stack_lte final : public enb_stack_base, class enb_stack_lte final : public enb_stack_base,
public stack_interface_phy_lte, public stack_interface_phy_lte,
public stack_interface_phy_nr, public stack_interface_phy_nr,
@ -178,6 +180,10 @@ private:
srsran::task_scheduler task_sched; srsran::task_scheduler task_sched;
srsran::task_queue_handle enb_task_queue, sync_task_queue, metrics_task_queue; srsran::task_queue_handle enb_task_queue, sync_task_queue, metrics_task_queue;
// bearer management
srsran::bearer_manager bearers; // helper to manage mapping between EPS and radio bearers
std::unique_ptr<gtpu_pdcp_adapter> gtpu_adapter;
srsenb::mac mac; srsenb::mac mac;
srsenb::rlc rlc; srsenb::rlc rlc;
srsenb::pdcp pdcp; srsenb::pdcp pdcp;
@ -191,10 +197,8 @@ private:
srsenb::pdcp pdcp_nr; srsenb::pdcp pdcp_nr;
srsenb::rrc_nr rrc_nr; srsenb::rrc_nr rrc_nr;
srsran::bearer_manager bearers; // helper to manage mapping between EPS and radio bearers
// RAT-specific interfaces // RAT-specific interfaces
phy_interface_stack_lte* phy = nullptr; phy_interface_stack_lte* phy = nullptr;
phy_interface_stack_nr* phy_nr = nullptr; phy_interface_stack_nr* phy_nr = nullptr;
// state // state

@ -22,6 +22,23 @@ using namespace srsran;
namespace srsenb { namespace srsenb {
class gtpu_pdcp_adapter : public gtpu_interface_pdcp
{
public:
gtpu_pdcp_adapter(gtpu* gtpu_, srsran::bearer_manager& bearers_) : gtpu_obj(gtpu_), bearers(&bearers_) {}
/// Converts LCID to EPS-BearerID and sends corresponding PDU to GTPU
void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu)
{
auto bearer = bearers->get_lcid_bearer(rnti, lcid);
gtpu_obj->write_pdu(rnti, bearer.eps_bearer_id, std::move(pdu));
}
private:
gtpu* gtpu_obj = nullptr;
srsran::bearer_manager* bearers = nullptr;
};
enb_stack_lte::enb_stack_lte(srslog::sink& log_sink) : enb_stack_lte::enb_stack_lte(srslog::sink& log_sink) :
thread("STACK"), thread("STACK"),
mac_logger(srslog::fetch_basic_logger("MAC", log_sink)), mac_logger(srslog::fetch_basic_logger("MAC", log_sink)),
@ -145,13 +162,16 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_)
// add sync queue // add sync queue
sync_task_queue = task_sched.make_task_queue(args.sync_queue_size); sync_task_queue = task_sched.make_task_queue(args.sync_queue_size);
// setup bearer managers
gtpu_adapter.reset(new gtpu_pdcp_adapter(&gtpu, bearers));
// Init all LTE layers // Init all LTE layers
if (!mac.init(args.mac, rrc_cfg.cell_list, phy, &rlc, &rrc)) { if (!mac.init(args.mac, rrc_cfg.cell_list, phy, &rlc, &rrc)) {
stack_logger.error("Couldn't initialize MAC"); stack_logger.error("Couldn't initialize MAC");
return SRSRAN_ERROR; return SRSRAN_ERROR;
} }
rlc.init(&pdcp, &rrc, &mac, task_sched.get_timer_handler()); rlc.init(&pdcp, &rrc, &mac, task_sched.get_timer_handler());
pdcp.init(&rlc, &rrc, &gtpu); pdcp.init(&rlc, &rrc, gtpu_adapter.get());
if (rrc.init(rrc_cfg, phy, &mac, &rlc, &pdcp, &s1ap, &gtpu, &rrc_nr) != SRSRAN_SUCCESS) { if (rrc.init(rrc_cfg, phy, &mac, &rlc, &pdcp, &s1ap, &gtpu, &rrc_nr) != SRSRAN_SUCCESS) {
stack_logger.error("Couldn't initialize RRC"); stack_logger.error("Couldn't initialize RRC");
return SRSRAN_ERROR; return SRSRAN_ERROR;
@ -281,16 +301,14 @@ void enb_stack_lte::run_thread()
void enb_stack_lte::write_sdu(uint16_t rnti, uint32_t eps_bearer_id, srsran::unique_byte_buffer_t sdu, int pdcp_sn) void enb_stack_lte::write_sdu(uint16_t rnti, uint32_t eps_bearer_id, srsran::unique_byte_buffer_t sdu, int pdcp_sn)
{ {
auto bearer = bearers.get_radio_bearer(rnti, eps_bearer_id); auto bearer = bearers.get_radio_bearer(rnti, eps_bearer_id);
auto task = [this, rnti, eps_bearer_id, bearer, pdcp_sn](srsran::unique_byte_buffer_t& sdu) { // route SDU to PDCP entity
// route SDU to PDCP entity if (bearer.rat == srsran_rat_t::lte) {
if (bearer.rat == srsran_rat_t::lte) { pdcp.write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn);
pdcp.write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); } else if (bearer.rat == srsran_rat_t::nr) {
} else if (bearer.rat == srsran_rat_t::nr) { pdcp_nr.write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn);
pdcp_nr.write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); } else {
} else { stack_logger.warning("Can't deliver SDU for EPS bearer %d. Dropping it.", eps_bearer_id);
stack_logger.warning("Can't deliver SDU for EPS bearer %d. Dropping it.", eps_bearer_id); }
}
};
} }
std::map<uint32_t, srsran::unique_byte_buffer_t> enb_stack_lte::get_buffered_pdus(uint16_t rnti, uint32_t lcid) std::map<uint32_t, srsran::unique_byte_buffer_t> enb_stack_lte::get_buffered_pdus(uint16_t rnti, uint32_t lcid)

@ -394,7 +394,7 @@ srsran::expected<uint32_t> bearer_cfg_handler::add_gtpu_bearer(uint32_t
erab_t::gtpu_tunnel bearer; erab_t::gtpu_tunnel bearer;
bearer.teid_out = teid_out; bearer.teid_out = teid_out;
bearer.addr = addr; bearer.addr = addr;
srsran::expected<uint32_t> teidin = gtpu->add_bearer(rnti, erab.lcid, addr, teid_out, props); srsran::expected<uint32_t> teidin = gtpu->add_bearer(rnti, erab.id, addr, teid_out, props);
if (teidin.is_error()) { if (teidin.is_error()) {
logger->error("Adding erab_id=%d to GTPU", erab_id); logger->error("Adding erab_id=%d to GTPU", erab_id);
return srsran::default_error_t(); return srsran::default_error_t();
@ -411,7 +411,7 @@ void bearer_cfg_handler::rem_gtpu_bearer(uint32_t erab_id)
logger->warning("Removing erab_id=%d from GTPU", erab_id); logger->warning("Removing erab_id=%d from GTPU", erab_id);
return; return;
} }
gtpu->rem_bearer(rnti, it->second.lcid); gtpu->rem_bearer(rnti, it->second.id);
} }
void bearer_cfg_handler::fill_pending_nas_info(asn1::rrc::rrc_conn_recfg_r8_ies_s* msg) void bearer_cfg_handler::fill_pending_nas_info(asn1::rrc::rrc_conn_recfg_r8_ies_s* msg)

@ -29,35 +29,35 @@ static const size_t PDU_HEADER_SIZE = 20;
class pdcp_tester : public pdcp_dummy class pdcp_tester : public pdcp_dummy
{ {
public: public:
void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu, int pdcp_sn) override void write_sdu(uint16_t rnti, uint32_t eps_bearer_id, srsran::unique_byte_buffer_t sdu, int pdcp_sn) override
{ {
last_sdu = std::move(sdu); last_sdu = std::move(sdu);
last_pdcp_sn = pdcp_sn; last_pdcp_sn = pdcp_sn;
last_rnti = rnti; last_rnti = rnti;
last_lcid = lcid; last_eps_bearer_id = eps_bearer_id;
} }
std::map<uint32_t, srsran::unique_byte_buffer_t> get_buffered_pdus(uint16_t rnti, uint32_t lcid) override std::map<uint32_t, srsran::unique_byte_buffer_t> get_buffered_pdus(uint16_t rnti, uint32_t eps_bearer_id) override
{ {
return std::move(buffered_pdus); return std::move(buffered_pdus);
} }
void send_status_report(uint16_t rnti) override {} void send_status_report(uint16_t rnti) override {}
void send_status_report(uint16_t rnti, uint32_t lcid) override {} void send_status_report(uint16_t rnti, uint32_t eps_bearer_id) override {}
void push_buffered_pdu(uint32_t sn, srsran::unique_byte_buffer_t pdu) { buffered_pdus[sn] = std::move(pdu); } void push_buffered_pdu(uint32_t sn, srsran::unique_byte_buffer_t pdu) { buffered_pdus[sn] = std::move(pdu); }
void clear() void clear()
{ {
last_sdu = nullptr; last_sdu = nullptr;
last_pdcp_sn = -1; last_pdcp_sn = -1;
last_lcid = 0; last_eps_bearer_id = 0;
last_rnti = SRSRAN_INVALID_RNTI; last_rnti = SRSRAN_INVALID_RNTI;
} }
std::map<uint32_t, srsran::unique_byte_buffer_t> buffered_pdus; std::map<uint32_t, srsran::unique_byte_buffer_t> buffered_pdus;
srsran::unique_byte_buffer_t last_sdu; srsran::unique_byte_buffer_t last_sdu;
int last_pdcp_sn = -1; int last_pdcp_sn = -1;
uint16_t last_rnti = SRSRAN_INVALID_RNTI; uint16_t last_rnti = SRSRAN_INVALID_RNTI;
uint32_t last_lcid = 0; uint32_t last_eps_bearer_id = 0;
}; };
struct dummy_socket_manager : public srsran::socket_manager_itf { struct dummy_socket_manager : public srsran::socket_manager_itf {
@ -153,44 +153,44 @@ void test_gtpu_tunnel_manager()
const char* sgw_addr_str = "127.0.0.1"; const char* sgw_addr_str = "127.0.0.1";
struct sockaddr_in sgw_sockaddr = {}; struct sockaddr_in sgw_sockaddr = {};
srsran::net_utils::set_sockaddr(&sgw_sockaddr, sgw_addr_str, GTPU_PORT); srsran::net_utils::set_sockaddr(&sgw_sockaddr, sgw_addr_str, GTPU_PORT);
uint32_t sgw_addr = ntohl(sgw_sockaddr.sin_addr.s_addr); uint32_t sgw_addr = ntohl(sgw_sockaddr.sin_addr.s_addr);
const uint32_t drb1_lcid = 3; const uint32_t drb1_eps_bearer_id = 5;
srsran::task_scheduler task_sched; srsran::task_scheduler task_sched;
gtpu_args_t gtpu_args = {}; gtpu_args_t gtpu_args = {};
gtpu_tunnel_manager tunnels(&task_sched, srslog::fetch_basic_logger("GTPU")); gtpu_tunnel_manager tunnels(&task_sched, srslog::fetch_basic_logger("GTPU"));
tunnels.init(gtpu_args, nullptr); tunnels.init(gtpu_args, nullptr);
TESTASSERT(tunnels.find_tunnel(0) == nullptr); TESTASSERT(tunnels.find_tunnel(0) == nullptr);
TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_lcid).empty()); TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_eps_bearer_id).empty());
TESTASSERT(tunnels.find_rnti_tunnels(0x46) == nullptr); TESTASSERT(tunnels.find_rnti_tunnels(0x46) == nullptr);
// Creation of tunnels for different users and lcids // Creation of tunnels for different users and bearers
const gtpu_tunnel* tun = tunnels.add_tunnel(0x46, drb1_lcid, 5, sgw_addr); const gtpu_tunnel* tun = tunnels.add_tunnel(0x46, drb1_eps_bearer_id, 5, sgw_addr);
TESTASSERT(tun != nullptr); TESTASSERT(tun != nullptr);
TESTASSERT(tunnels.find_tunnel(tun->teid_in) == tun); TESTASSERT(tunnels.find_tunnel(tun->teid_in) == tun);
const gtpu_tunnel* tun2 = tunnels.add_tunnel(0x47, drb1_lcid, 6, sgw_addr); const gtpu_tunnel* tun2 = tunnels.add_tunnel(0x47, drb1_eps_bearer_id, 6, sgw_addr);
TESTASSERT(tun2 != nullptr); TESTASSERT(tun2 != nullptr);
TESTASSERT(tunnels.find_tunnel(tun2->teid_in) == tun2); TESTASSERT(tunnels.find_tunnel(tun2->teid_in) == tun2);
tun2 = tunnels.add_tunnel(0x47, drb1_lcid + 1, 7, sgw_addr); tun2 = tunnels.add_tunnel(0x47, drb1_eps_bearer_id + 1, 7, sgw_addr);
TESTASSERT(tun2 != nullptr); TESTASSERT(tun2 != nullptr);
TESTASSERT(tunnels.find_tunnel(tun2->teid_in) == tun2); TESTASSERT(tunnels.find_tunnel(tun2->teid_in) == tun2);
TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_lcid).size() == 1); TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_eps_bearer_id).size() == 1);
TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x47, drb1_lcid).size() == 1); TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x47, drb1_eps_bearer_id).size() == 1);
TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x47, drb1_lcid + 1).size() == 1); TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x47, drb1_eps_bearer_id + 1).size() == 1);
// TEST: Creation/Removal of indirect tunnel // TEST: Creation/Removal of indirect tunnel
const gtpu_tunnel* fwd_tun = tunnels.add_tunnel(0x46, drb1_lcid, 8, sgw_addr); const gtpu_tunnel* fwd_tun = tunnels.add_tunnel(0x46, drb1_eps_bearer_id, 8, sgw_addr);
TESTASSERT(fwd_tun != nullptr); TESTASSERT(fwd_tun != nullptr);
TESTASSERT(tunnels.find_tunnel(fwd_tun->teid_in) == fwd_tun); TESTASSERT(tunnels.find_tunnel(fwd_tun->teid_in) == fwd_tun);
tunnels.setup_forwarding(tun->teid_in, fwd_tun->teid_in); tunnels.setup_forwarding(tun->teid_in, fwd_tun->teid_in);
TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_lcid).size() == 2); TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_eps_bearer_id).size() == 2);
// Removing a tunnel also clears any associated forwarding tunnel // Removing a tunnel also clears any associated forwarding tunnel
TESTASSERT(tunnels.remove_tunnel(tun->teid_in)); TESTASSERT(tunnels.remove_tunnel(tun->teid_in));
TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_lcid).empty()); TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_eps_bearer_id).empty());
// TEST: Prioritization of one TEID over another // TEST: Prioritization of one TEID over another
const gtpu_tunnel* before_tun = tunnels.add_tunnel(0x46, drb1_lcid, 7, sgw_addr); const gtpu_tunnel* before_tun = tunnels.add_tunnel(0x46, drb1_eps_bearer_id, 7, sgw_addr);
const gtpu_tunnel* after_tun = tunnels.add_tunnel(0x46, drb1_lcid, 8, sgw_addr); const gtpu_tunnel* after_tun = tunnels.add_tunnel(0x46, drb1_eps_bearer_id, 8, sgw_addr);
TESTASSERT(before_tun != nullptr and after_tun != nullptr); TESTASSERT(before_tun != nullptr and after_tun != nullptr);
tunnels.set_tunnel_priority(before_tun->teid_in, after_tun->teid_in); tunnels.set_tunnel_priority(before_tun->teid_in, after_tun->teid_in);
for (uint32_t i = 0; i < 1000; ++i) { for (uint32_t i = 0; i < 1000; ++i) {
@ -200,9 +200,9 @@ void test_gtpu_tunnel_manager()
tunnels.handle_rx_pdcp_sdu(before_tun->teid_in); tunnels.handle_rx_pdcp_sdu(before_tun->teid_in);
} }
// Removing active TEID, will automatically switch TEID paths // Removing active TEID, will automatically switch TEID paths
TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_lcid).size() == 2); TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_eps_bearer_id).size() == 2);
tunnels.remove_tunnel(before_tun->teid_in); tunnels.remove_tunnel(before_tun->teid_in);
TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_lcid).size() == 1); TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_eps_bearer_id).size() == 1);
TESTASSERT(after_tun->state == gtpu_tunnel_manager::tunnel_state::pdcp_active); TESTASSERT(after_tun->state == gtpu_tunnel_manager::tunnel_state::pdcp_active);
} }
@ -215,7 +215,7 @@ int test_gtpu_direct_tunneling(tunnel_test_event event)
srslog::basic_logger& logger = srslog::fetch_basic_logger("TEST"); srslog::basic_logger& logger = srslog::fetch_basic_logger("TEST");
logger.info("\n\n**** Test GTPU Direct Tunneling ****\n"); logger.info("\n\n**** Test GTPU Direct Tunneling ****\n");
uint16_t rnti = 0x46, rnti2 = 0x50; uint16_t rnti = 0x46, rnti2 = 0x50;
uint32_t drb1 = 3; uint32_t drb1_bearer_id = 5;
uint32_t sgw_teidout1 = 1, sgw_teidout2 = 2; uint32_t sgw_teidout1 = 1, sgw_teidout2 = 2;
const char * sgw_addr_str = "127.0.0.1", *senb_addr_str = "127.0.1.1", *tenb_addr_str = "127.0.1.2"; const char * sgw_addr_str = "127.0.0.1", *senb_addr_str = "127.0.1.1", *tenb_addr_str = "127.0.1.2";
struct sockaddr_in senb_sockaddr = {}, sgw_sockaddr = {}, tenb_sockaddr = {}; struct sockaddr_in senb_sockaddr = {}, sgw_sockaddr = {}, tenb_sockaddr = {};
@ -246,8 +246,8 @@ int test_gtpu_direct_tunneling(tunnel_test_event event)
tenb_gtpu.init(gtpu_args, &tenb_pdcp); tenb_gtpu.init(gtpu_args, &tenb_pdcp);
// create tunnels MME-SeNB and MME-TeNB // create tunnels MME-SeNB and MME-TeNB
uint32_t senb_teid_in = senb_gtpu.add_bearer(rnti, drb1, sgw_addr, sgw_teidout1).value(); uint32_t senb_teid_in = senb_gtpu.add_bearer(rnti, drb1_bearer_id, sgw_addr, sgw_teidout1).value();
uint32_t tenb_teid_in = tenb_gtpu.add_bearer(rnti2, drb1, sgw_addr, sgw_teidout2).value(); uint32_t tenb_teid_in = tenb_gtpu.add_bearer(rnti2, drb1_bearer_id, sgw_addr, sgw_teidout2).value();
// Buffer PDUs in SeNB PDCP // Buffer PDUs in SeNB PDCP
for (size_t sn = 6; sn < 10; ++sn) { for (size_t sn = 6; sn < 10; ++sn) {
@ -260,11 +260,11 @@ int test_gtpu_direct_tunneling(tunnel_test_event event)
gtpu::bearer_props props; gtpu::bearer_props props;
props.flush_before_teidin_present = true; props.flush_before_teidin_present = true;
props.flush_before_teidin = tenb_teid_in; props.flush_before_teidin = tenb_teid_in;
uint32_t dl_tenb_teid_in = tenb_gtpu.add_bearer(rnti2, drb1, senb_addr, 0, &props).value(); uint32_t dl_tenb_teid_in = tenb_gtpu.add_bearer(rnti2, drb1_bearer_id, senb_addr, 0, &props).value();
props = {}; props = {};
props.forward_from_teidin_present = true; props.forward_from_teidin_present = true;
props.forward_from_teidin = senb_teid_in; props.forward_from_teidin = senb_teid_in;
senb_gtpu.add_bearer(rnti, drb1, tenb_addr, dl_tenb_teid_in, &props); senb_gtpu.add_bearer(rnti, drb1_bearer_id, tenb_addr, dl_tenb_teid_in, &props);
std::vector<uint8_t> data_vec(10); std::vector<uint8_t> data_vec(10);
std::iota(data_vec.begin(), data_vec.end(), 0); std::iota(data_vec.begin(), data_vec.end(), 0);
@ -280,7 +280,7 @@ int test_gtpu_direct_tunneling(tunnel_test_event event)
pdu_view = srsran::make_span(tenb_pdcp.last_sdu); pdu_view = srsran::make_span(tenb_pdcp.last_sdu);
TESTASSERT(std::count(pdu_view.begin() + PDU_HEADER_SIZE, pdu_view.end(), 7) == 10); TESTASSERT(std::count(pdu_view.begin() + PDU_HEADER_SIZE, pdu_view.end(), 7) == 10);
TESTASSERT(tenb_pdcp.last_rnti == rnti2); TESTASSERT(tenb_pdcp.last_rnti == rnti2);
TESTASSERT(tenb_pdcp.last_lcid == drb1); TESTASSERT(tenb_pdcp.last_eps_bearer_id == drb1_bearer_id);
TESTASSERT(tenb_pdcp.last_pdcp_sn == (int)7); TESTASSERT(tenb_pdcp.last_pdcp_sn == (int)7);
// TEST: verify that PDCP buffered SNs have been forwarded through SeNB->TeNB tunnel // TEST: verify that PDCP buffered SNs have been forwarded through SeNB->TeNB tunnel
@ -289,7 +289,7 @@ int test_gtpu_direct_tunneling(tunnel_test_event event)
pdu_view = srsran::make_span(tenb_pdcp.last_sdu); pdu_view = srsran::make_span(tenb_pdcp.last_sdu);
TESTASSERT(std::count(pdu_view.begin() + PDU_HEADER_SIZE, pdu_view.end(), sn) == 10); TESTASSERT(std::count(pdu_view.begin() + PDU_HEADER_SIZE, pdu_view.end(), sn) == 10);
TESTASSERT(tenb_pdcp.last_rnti == rnti2); TESTASSERT(tenb_pdcp.last_rnti == rnti2);
TESTASSERT(tenb_pdcp.last_lcid == drb1); TESTASSERT(tenb_pdcp.last_eps_bearer_id == drb1_bearer_id);
TESTASSERT(tenb_pdcp.last_pdcp_sn == (int)sn); TESTASSERT(tenb_pdcp.last_pdcp_sn == (int)sn);
} }
@ -302,7 +302,7 @@ int test_gtpu_direct_tunneling(tunnel_test_event event)
pdu_view = srsran::make_span(tenb_pdcp.last_sdu); pdu_view = srsran::make_span(tenb_pdcp.last_sdu);
TESTASSERT(pdu_view.size() == encoded_data.size() and TESTASSERT(pdu_view.size() == encoded_data.size() and
std::equal(pdu_view.begin(), pdu_view.end(), encoded_data.begin())); std::equal(pdu_view.begin(), pdu_view.end(), encoded_data.begin()));
TESTASSERT(tenb_pdcp.last_rnti == rnti2 and tenb_pdcp.last_lcid == drb1); TESTASSERT(tenb_pdcp.last_rnti == rnti2 and tenb_pdcp.last_eps_bearer_id == drb1_bearer_id);
// TEST: verify that MME->TeNB packets are buffered until SeNB->TeNB tunnel is closed // TEST: verify that MME->TeNB packets are buffered until SeNB->TeNB tunnel is closed
tenb_pdcp.clear(); tenb_pdcp.clear();
@ -361,7 +361,7 @@ int test_gtpu_direct_tunneling(tunnel_test_event event)
if (event != tunnel_test_event::ue_removal_no_marker) { if (event != tunnel_test_event::ue_removal_no_marker) {
// The User is removed in SeNB in case it hasn't and there was no reestablishment // The User is removed in SeNB in case it hasn't and there was no reestablishment
if (std::uniform_int_distribution<uint32_t>{0, 1}(g) > 0) { if (std::uniform_int_distribution<uint32_t>{0, 1}(g) > 0) {
senb_gtpu.rem_bearer(0x46, 3); senb_gtpu.rem_bearer(0x46, drb1_bearer_id);
} }
senb_gtpu.rem_user(0x46); senb_gtpu.rem_user(0x46);
} }

Loading…
Cancel
Save