srsue, nr: Add SDAP to the UE. Supports only UL header

master
Ismael Gomez 3 years ago
parent a4f26fa5d6
commit bfe69deccc

@ -59,6 +59,13 @@ public:
virtual bool is_lcid_enabled(uint32_t lcid) = 0;
};
// SDAP interface
class pdcp_interface_sdap_nr
{
public:
virtual void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t pdu) = 0;
};
// STACK interface for GW (based on EPS-bearer IDs)
class stack_interface_gw
{

@ -0,0 +1,47 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
/******************************************************************************
* File: ue_sdap_interfaces.h
* Description: Abstract base class interfaces for SDAP layer
*****************************************************************************/
#ifndef SRSRAN_UE_SDAP_INTERFACES_H
#define SRSRAN_UE_SDAP_INTERFACES_H
/*****************************
* SDAP INTERFACES
****************************/
class sdap_interface_pdcp_nr
{
public:
virtual void write_pdu(uint32_t lcid, srsran::unique_byte_buffer_t pdu) = 0;
};
class sdap_interface_gw_nr
{
public:
virtual void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t pdu) = 0;
};
class sdap_interface_rrc
{
public:
struct bearer_cfg_t {
bool is_data;
bool add_downlink_header;
bool add_uplink_header;
uint32_t qfi;
};
virtual bool set_bearer_cfg(uint32_t lcid, const bearer_cfg_t& cfg) = 0;
};
#endif // SRSRAN_UE_SDAP_INTERFACES_H

@ -28,6 +28,7 @@
#include "srsran/interfaces/ue_nas_interfaces.h"
#include "srsran/interfaces/ue_nr_interfaces.h"
#include "srsran/interfaces/ue_rrc_interfaces.h"
#include "srsran/interfaces/ue_sdap_interfaces.h"
#include "srsue/hdr/stack/upper/gw.h"
namespace srsue {
@ -52,6 +53,7 @@ public:
mac_interface_rrc_nr* mac_,
rlc_interface_rrc* rlc_,
pdcp_interface_rrc* pdcp_,
sdap_interface_rrc* sdap_,
gw_interface_rrc* gw_,
nas_5g_interface_rrc_nr* nas_,
rrc_eutra_interface_rrc_nr* rrc_eutra_,
@ -170,6 +172,7 @@ private:
mac_interface_rrc_nr* mac = nullptr;
rlc_interface_rrc* rlc = nullptr;
pdcp_interface_rrc* pdcp = nullptr;
sdap_interface_rrc* sdap = nullptr;
gw_interface_rrc* gw = nullptr;
nas_5g_interface_rrc_nr* nas = nullptr;
rrc_eutra_interface_rrc_nr* rrc_eutra = nullptr;

@ -36,6 +36,7 @@
#include "ue_stack_base.h"
#include "upper/nas.h"
#include "upper/nas_5g.h"
#include "upper/sdap.h"
#include "upper/usim.h"
#include <functional>
#include <pthread.h>
@ -46,6 +47,28 @@ namespace srsue {
class phy_interface_stack_lte;
class sdap_pdcp_adapter : public pdcp_interface_sdap_nr, public gw_interface_pdcp
{
public:
sdap_pdcp_adapter(pdcp* parent_pdcp_, sdap* parent_sdap_) : parent_pdcp(parent_pdcp_), parent_sdap(parent_sdap_) {}
void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t pdu) final
{
parent_pdcp->write_sdu(lcid, std::move(pdu));
}
void write_pdu(uint32_t lcid, srsran::unique_byte_buffer_t pdu) final
{
parent_sdap->write_pdu(lcid, std::move(pdu));
}
void write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t pdu) final
{
// not implemented
}
private:
pdcp* parent_pdcp;
sdap* parent_sdap;
};
class ue_stack_lte final : public ue_stack_base,
public stack_interface_phy_lte,
public stack_interface_phy_nr,
@ -231,6 +254,10 @@ private:
srsue::nas_5g nas_5g;
std::unique_ptr<usim_base> usim;
// SDAP only applies to NR
srsue::sdap sdap;
sdap_pdcp_adapter sdap_pdcp;
ue_bearer_manager bearers; // helper to manage mapping between EPS and radio bearers
// Metrics helper

@ -23,6 +23,7 @@
#include "srsran/rlc/rlc.h"
#include "srsran/upper/pdcp.h"
#include "upper/nas.h"
#include "upper/sdap.h"
#include "upper/usim.h"
#include "srsran/common/buffer_pool.h"
@ -135,6 +136,7 @@ private:
std::unique_ptr<rrc_nr> rrc;
std::unique_ptr<srsran::rlc> rlc;
std::unique_ptr<srsran::pdcp> pdcp;
std::unique_ptr<srsue::sdap> sdap;
// RAT-specific interfaces
phy_interface_stack_nr* phy = nullptr;

@ -0,0 +1,56 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSUE_SDAP_H
#define SRSUE_SDAP_H
#include "srsran/common/buffer_pool.h"
#include "srsran/common/common.h"
#include "srsran/common/common_nr.h"
#include "srsran/interfaces/ue_gw_interfaces.h"
#include "srsran/interfaces/ue_pdcp_interfaces.h"
#include "srsran/interfaces/ue_sdap_interfaces.h"
namespace srsue {
class sdap final : public sdap_interface_pdcp_nr, public sdap_interface_gw_nr, public sdap_interface_rrc
{
public:
explicit sdap(const char* logname);
bool init(pdcp_interface_sdap_nr* pdcp_, srsue::gw_interface_pdcp* gw_);
void stop();
// Interface for GW
void write_pdu(uint32_t lcid, srsran::unique_byte_buffer_t pdu) final;
// Interface for PDCP
void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t pdu) final;
// Interface for RRC
bool set_bearer_cfg(uint32_t lcid, const sdap_interface_rrc::bearer_cfg_t& cfg) final;
private:
pdcp_interface_sdap_nr* m_pdcp = nullptr;
gw_interface_pdcp* m_gw = nullptr;
// state
bool running = false;
// configuration
std::array<sdap_interface_rrc::bearer_cfg_t, srsran::MAX_NR_NOF_BEARERS> bearers = {};
srslog::basic_logger& logger;
};
} // namespace srsue
#endif // SRSUE_SDAP_H

@ -45,6 +45,7 @@ int rrc_nr::init(phy_interface_rrc_nr* phy_,
mac_interface_rrc_nr* mac_,
rlc_interface_rrc* rlc_,
pdcp_interface_rrc* pdcp_,
sdap_interface_rrc* sdap_,
gw_interface_rrc* gw_,
nas_5g_interface_rrc_nr* nas_,
rrc_eutra_interface_rrc_nr* rrc_eutra_,
@ -56,6 +57,7 @@ int rrc_nr::init(phy_interface_rrc_nr* phy_,
phy = phy_;
rlc = rlc_;
pdcp = pdcp_;
sdap = sdap_;
gw = gw_;
nas = nas_;
mac = mac_;
@ -1896,12 +1898,18 @@ bool rrc_nr::apply_drb_add_mod(const drb_to_add_mod_s& drb_cfg)
stack->add_eps_bearer(eps_bearer_id, srsran::srsran_rat_t::nr, lcid);
} else if (drb_cfg.cn_assoc.type() == drb_to_add_mod_s::cn_assoc_c_::types_opts::sdap_cfg) {
const auto& sdap_cfg = drb_cfg.cn_assoc.sdap_cfg();
if (sdap_cfg.sdap_hdr_dl == asn1::rrc_nr::sdap_cfg_s::sdap_hdr_dl_opts::present ||
sdap_cfg.sdap_hdr_ul == asn1::rrc_nr::sdap_cfg_s::sdap_hdr_ul_opts::present) {
logger.error("SDAP currently not supported.");
// return false;
sdap_interface_rrc::bearer_cfg_t sdap_bearer_cfg = {};
sdap_bearer_cfg.add_downlink_header = sdap_cfg.sdap_hdr_dl.value == sdap_cfg_s::sdap_hdr_dl_opts::present;
sdap_bearer_cfg.add_uplink_header = sdap_cfg.sdap_hdr_ul.value == sdap_cfg_s::sdap_hdr_ul_opts::present;
sdap_bearer_cfg.is_data = true;
sdap_bearer_cfg.qfi = sdap_cfg.mapped_qos_flows_to_add[0];
if (not sdap->set_bearer_cfg(lcid, sdap_bearer_cfg)) {
logger.error("Configuring SDAP");
return false;
}
// TODO: configure SDAP accordingly
uint32_t pdu_session_id = drb_cfg.cn_assoc.sdap_cfg().pdu_session;
// Register PDU session as "EPS bearer" in bearer manager
stack->add_eps_bearer(pdu_session_id, srsran::srsran_rat_t::nr, lcid);

@ -93,6 +93,13 @@ class dummy_pdcp : public pdcp_interface_rrc
void send_status_report(uint32_t lcid){};
};
class dummy_sdap : public sdap_interface_pdcp_nr, public sdap_interface_gw_nr, public sdap_interface_rrc
{
void write_pdu(uint32_t lcid, srsran::unique_byte_buffer_t pdu) final{};
void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t pdu) final{};
bool set_bearer_cfg(uint32_t lcid, const sdap_interface_rrc::bearer_cfg_t& cfg) final { return true; };
};
class dummy_gw : public gw_interface_rrc
{
void add_mch_port(uint32_t lcid, uint32_t port){};
@ -143,6 +150,7 @@ int rrc_nr_cap_request_test()
dummy_mac dummy_mac;
dummy_rlc dummy_rlc;
dummy_pdcp dummy_pdcp;
dummy_sdap dummy_sdap;
dummy_gw dummy_gw;
dummy_nas dummy_nas;
dummy_eutra dummy_eutra;
@ -157,6 +165,7 @@ int rrc_nr_cap_request_test()
&dummy_mac,
&dummy_rlc,
&dummy_pdcp,
&dummy_sdap,
&dummy_gw,
&dummy_nas,
&dummy_eutra,
@ -183,6 +192,7 @@ int rrc_nsa_reconfig_tdd_test()
dummy_mac dummy_mac;
dummy_rlc dummy_rlc;
dummy_pdcp dummy_pdcp;
dummy_sdap dummy_sdap;
dummy_gw dummy_gw;
dummy_nas dummy_nas;
dummy_eutra dummy_eutra;
@ -193,6 +203,7 @@ int rrc_nsa_reconfig_tdd_test()
&dummy_mac,
&dummy_rlc,
&dummy_pdcp,
&dummy_sdap,
&dummy_gw,
&dummy_nas,
&dummy_eutra,
@ -284,6 +295,7 @@ int rrc_nsa_reconfig_fdd_test()
dummy_mac dummy_mac;
dummy_rlc dummy_rlc;
dummy_pdcp dummy_pdcp;
dummy_sdap dummy_sdap;
dummy_gw dummy_gw;
dummy_nas dummy_nas;
dummy_eutra dummy_eutra;
@ -294,6 +306,7 @@ int rrc_nsa_reconfig_fdd_test()
&dummy_mac,
&dummy_rlc,
&dummy_pdcp,
&dummy_sdap,
&dummy_gw,
&dummy_nas,
&dummy_eutra,
@ -386,6 +399,7 @@ int rrc_nr_setup_request_test()
dummy_mac dummy_mac;
dummy_rlc dummy_rlc;
dummy_pdcp dummy_pdcp;
dummy_sdap dummy_sdap;
dummy_gw dummy_gw;
dummy_nas dummy_nas;
dummy_eutra dummy_eutra;
@ -399,6 +413,7 @@ int rrc_nr_setup_request_test()
&dummy_mac,
&dummy_rlc,
&dummy_pdcp,
&dummy_sdap,
&dummy_gw,
&dummy_nas,
&dummy_eutra,
@ -428,6 +443,7 @@ int rrc_nr_sib1_decoding_test()
dummy_mac dummy_mac;
dummy_rlc dummy_rlc;
dummy_pdcp dummy_pdcp;
dummy_sdap dummy_sdap;
dummy_gw dummy_gw;
dummy_nas dummy_nas;
dummy_eutra dummy_eutra;
@ -438,6 +454,7 @@ int rrc_nr_sib1_decoding_test()
&dummy_mac,
&dummy_rlc,
&dummy_pdcp,
&dummy_sdap,
&dummy_gw,
&dummy_nas,
&dummy_eutra,
@ -475,6 +492,7 @@ int rrc_nr_setup_test()
dummy_mac dummy_mac;
dummy_rlc dummy_rlc;
dummy_pdcp dummy_pdcp;
dummy_sdap dummy_sdap;
dummy_gw dummy_gw;
dummy_nas dummy_nas;
dummy_eutra dummy_eutra;
@ -485,6 +503,7 @@ int rrc_nr_setup_test()
&dummy_mac,
&dummy_rlc,
&dummy_pdcp,
&dummy_sdap,
&dummy_gw,
&dummy_nas,
&dummy_eutra,
@ -528,6 +547,7 @@ int rrc_nr_reconfig_test()
dummy_mac dummy_mac;
dummy_rlc dummy_rlc;
dummy_pdcp dummy_pdcp;
dummy_sdap dummy_sdap;
dummy_gw dummy_gw;
dummy_nas dummy_nas;
dummy_eutra dummy_eutra;
@ -538,6 +558,7 @@ int rrc_nr_reconfig_test()
&dummy_mac,
&dummy_rlc,
&dummy_pdcp,
&dummy_sdap,
&dummy_gw,
&dummy_nas,
&dummy_eutra,

@ -47,6 +47,8 @@ ue_stack_lte::ue_stack_lte() :
rrc_nr(&task_sched),
pdcp(&task_sched, "PDCP"),
pdcp_nr(&task_sched, "PDCP-NR"),
sdap("SDAP-NR"),
sdap_pdcp(&pdcp_nr, &sdap),
nas(srslog::fetch_basic_logger("NAS", false), &task_sched),
nas_5g(srslog::fetch_basic_logger("NAS5G", false), &task_sched),
thread("STACK"),
@ -208,9 +210,15 @@ int ue_stack_lte::init(const stack_args_t& args_)
mac.init(phy, &rlc, &rrc);
rlc.init(&pdcp, &rrc, task_sched.get_timer_handler(), 0 /* RB_ID_SRB0 */);
pdcp.init(&rlc, &rrc, gw);
nas.init(usim.get(), &rrc, gw, args.nas);
if (!args.sa_mode) {
pdcp.init(&rlc, &rrc, gw);
} else {
pdcp.init(&rlc, &rrc, &sdap_pdcp);
sdap.init(&sdap_pdcp, gw);
}
mac_nr_args_t mac_nr_args = {};
mac_nr.init(mac_nr_args, phy_nr, &rlc_nr, &rrc_nr);
rlc_nr.init(&pdcp_nr, &rrc_nr, task_sched.get_timer_handler(), 0 /* RB_ID_SRB0 */);
@ -219,6 +227,7 @@ int ue_stack_lte::init(const stack_args_t& args_)
&mac_nr,
&rlc_nr,
&pdcp_nr,
&sdap,
gw,
&nas_5g,
args.sa_mode ? nullptr : &rrc,
@ -400,12 +409,17 @@ void ue_stack_lte::remove_eps_bearer(uint8_t eps_bearer_id)
void ue_stack_lte::write_sdu(uint32_t eps_bearer_id, srsran::unique_byte_buffer_t sdu)
{
auto bearer = bearers.get_radio_bearer(eps_bearer_id);
auto task = [this, eps_bearer_id, bearer](srsran::unique_byte_buffer_t& sdu) {
// route SDU to PDCP entity
if (bearer.rat == srsran_rat_t::lte) {
pdcp.write_sdu(bearer.lcid, std::move(sdu));
} else if (bearer.rat == srsran_rat_t::nr) {
pdcp_nr.write_sdu(bearer.lcid, std::move(sdu));
if (args.sa_mode) {
sdap.write_sdu(bearer.lcid, std::move(sdu));
} else {
pdcp_nr.write_sdu(bearer.lcid, std::move(sdu));
}
} else {
stack_logger.warning("Can't deliver SDU for EPS bearer %d. Dropping it.", eps_bearer_id);
}

@ -80,6 +80,7 @@ int ue_stack_nr::init(const stack_args_t& args_)
mac.get(),
rlc.get(),
pdcp.get(),
sdap.get(),
gw,
nullptr,
nullptr,

@ -8,7 +8,7 @@
add_subdirectory(test)
set(SOURCES nas.cc nas_emm_state.cc nas_idle_procedures.cc gw.cc usim_base.cc usim.cc tft_packet_filter.cc nas_base.cc nas_5g_procedures.cc nas_5g.cc nas_5gmm_state.cc)
set(SOURCES nas.cc nas_emm_state.cc nas_idle_procedures.cc gw.cc usim_base.cc usim.cc tft_packet_filter.cc nas_base.cc nas_5g_procedures.cc nas_5g.cc nas_5gmm_state.cc sdap.cc)
if(HAVE_PCSC)
list(APPEND SOURCES "pcsc_usim.cc")

@ -0,0 +1,76 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srsue/hdr/stack/upper/sdap.h"
namespace srsue {
sdap::sdap(const char* logname) : logger(srslog::fetch_basic_logger(logname)) {}
bool sdap::init(pdcp_interface_sdap_nr* pdcp_, srsue::gw_interface_pdcp* gw_)
{
m_pdcp = pdcp_;
m_gw = gw_;
running = true;
return true;
}
void sdap::stop()
{
if (running) {
running = false;
}
}
void sdap::write_pdu(uint32_t lcid, srsran::unique_byte_buffer_t pdu)
{
if (!running) {
return;
}
m_gw->write_pdu(lcid, std::move(pdu));
}
void sdap::write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t pdu)
{
if (!running) {
return;
}
if (lcid < bearers.size()) {
if (bearers[lcid].add_uplink_header) {
if (pdu->get_headroom() > 1) {
pdu->msg -= 1;
pdu->N_bytes += 1;
pdu->msg[0] = ((bearers[lcid].is_data ? 1 : 0) << 7) | (bearers[lcid].qfi & 0x3f);
} else {
logger.error("Not enough headroom in PDU to add header\n");
}
}
}
m_pdcp->write_sdu(lcid, std::move(pdu));
}
bool sdap::set_bearer_cfg(uint32_t lcid, const sdap_interface_rrc::bearer_cfg_t& cfg)
{
if (lcid >= bearers.size()) {
logger.error("Error setting configuration: invalid lcid=%d\n", lcid);
return false;
}
if (cfg.add_downlink_header) {
logger.error("Error setting configuration: downlink header not supported\n");
return false;
}
bearers[lcid] = cfg;
return true;
}
} // namespace srsue
Loading…
Cancel
Save