Refactor build of RLC NR config

master
David Rupprecht 4 years ago committed by Andre Puschmann
parent d1d8500ce5
commit 6d5391756c

@ -120,7 +120,7 @@ bool make_mac_dl_harq_cfg_nr_t(const asn1::rrc_nr::pdsch_ser
/***************************
* RLC Config
**************************/
rlc_config_t make_rlc_config_t(const asn1::rrc_nr::rlc_cfg_c& asn1_type);
int make_rlc_config_t(const asn1::rrc_nr::rlc_cfg_c& asn1_type, rlc_config_t* rlc_config_out);
/***************************
* PDCP Config

@ -110,8 +110,6 @@ struct rlc_um_nr_config_t {
***************************************************************************/
rlc_um_nr_sn_size_t sn_field_length; // Number of bits used for sequence number
uint32_t UM_Window_Size;
uint32_t mod; // Rx/Tx counter modulus
int32_t t_reassembly_ms; // Timer used by rx to detect PDU loss (ms)
};
@ -206,12 +204,8 @@ public:
cnfg.rlc_mode = rlc_mode_t::um;
if (sn_size == 6) {
cnfg.um_nr.sn_field_length = rlc_um_nr_sn_size_t::size6bits;
cnfg.um_nr.UM_Window_Size = 32;
cnfg.um_nr.mod = 64;
} else if (sn_size == 12) {
cnfg.um_nr.sn_field_length = rlc_um_nr_sn_size_t::size12bits;
cnfg.um_nr.UM_Window_Size = 2048;
cnfg.um_nr.mod = 4096;
} else {
return {};
}

@ -62,6 +62,9 @@ private:
uint32_t next_so = 0; // The segment offset for the next generated PDU
uint32_t UM_Window_Size;
uint32_t mod; // Rx counter modulus
static constexpr uint32_t head_len_full = 1; // full SDU header size is always
uint32_t head_len_first = 0, head_len_segment = 0; // are computed during configure based on SN length
@ -96,6 +99,9 @@ private:
uint32_t RX_Next_Highest = 0; // the SN following the SN of the UMD PDU with the highest SN among
// received UMD PDUs. It serves as the higher edge of the reassembly window.
uint32_t UM_Window_Size;
uint32_t mod; // Rx counter modulus
// Rx window
typedef struct {
std::map<uint32_t, rlc_umd_pdu_nr_t> segments; // Map of segments with SO as key

@ -100,26 +100,48 @@ rach_nr_cfg_t make_mac_rach_cfg(const rach_cfg_common_s& asn1_type)
return rach_nr_cfg;
};
rlc_config_t make_rlc_config_t(const rlc_cfg_c& asn1_type)
int make_rlc_config_t(const rlc_cfg_c& asn1_type, rlc_config_t* cfg_out)
{
rlc_config_t rlc_cfg = rlc_config_t::default_rlc_um_nr_config();
rlc_cfg.rat = srsran_rat_t::nr;
switch (asn1_type.type().value) {
case rlc_cfg_c::types_opts::am:
break;
asn1::log_warning("NR RLC type %s is not supported", asn1_type.type().to_string());
return SRSRAN_ERROR;
case rlc_cfg_c::types_opts::um_bi_dir:
case rlc_cfg_c::types_opts::um_uni_dir_dl:
case rlc_cfg_c::types_opts::um_uni_dir_ul:
rlc_cfg.rlc_mode = rlc_mode_t::um;
rlc_cfg.um_nr.t_reassembly_ms = asn1_type.um_bi_dir().dl_um_rlc.t_reassembly.value.to_number();
rlc_cfg.um_nr.sn_field_length = (rlc_um_nr_sn_size_t)asn1_type.um_bi_dir().dl_um_rlc.sn_field_len.value;
rlc_cfg.um_nr.mod = (rlc_cfg.um_nr.sn_field_length == rlc_um_nr_sn_size_t::size6bits) ? 64 : 4096;
rlc_cfg.um_nr.UM_Window_Size = (rlc_cfg.um_nr.sn_field_length == rlc_um_nr_sn_size_t::size6bits) ? 32 : 2048;
rlc_cfg.um_nr.t_reassembly_ms = asn1_type.um_bi_dir().dl_um_rlc.t_reassembly.to_number();
if (asn1_type.um_bi_dir().dl_um_rlc.sn_field_len_present &&
asn1_type.um_bi_dir().ul_um_rlc.sn_field_len_present &&
asn1_type.um_bi_dir().dl_um_rlc.sn_field_len != asn1_type.um_bi_dir().ul_um_rlc.sn_field_len) {
asn1::log_warning("NR RLC sequence number length is not the same in uplink and downlink");
return SRSRAN_ERROR;
}
switch (asn1_type.um_bi_dir().dl_um_rlc.sn_field_len.value) {
case asn1::rrc_nr::sn_field_len_um_opts::options::size6:
rlc_cfg.um_nr.sn_field_length = rlc_um_nr_sn_size_t::size6bits;
break;
case asn1::rrc_nr::sn_field_len_um_opts::options::size12:
rlc_cfg.um_nr.sn_field_length = rlc_um_nr_sn_size_t::size12bits;
break;
default:
break;
}
break;
case rlc_cfg_c::types_opts::um_uni_dir_dl:
asn1::log_warning("NR RLC type %s is not supported", asn1_type.type().to_string());
return SRSRAN_ERROR;
case rlc_cfg_c::types_opts::um_uni_dir_ul:
asn1::log_warning("NR RLC type %s is not supported", asn1_type.type().to_string());
return SRSRAN_ERROR;
default:
break;
}
return rlc_cfg;
*cfg_out = rlc_cfg;
return SRSRAN_SUCCESS;
}
srsran::pdcp_config_t make_drb_pdcp_config_t(const uint8_t bearer_id, bool is_ue, const pdcp_cfg_s& pdcp_cfg)

@ -14,7 +14,7 @@
#include "srsran/interfaces/ue_pdcp_interfaces.h"
#include <sstream>
#define RX_MOD_NR_BASE(x) (((x)-RX_Next_Highest - cfg.um_nr.UM_Window_Size) % cfg.um_nr.mod)
#define RX_MOD_NR_BASE(x) (((x)-RX_Next_Highest - UM_Window_Size) % mod)
namespace srsran {
@ -94,10 +94,8 @@ bool rlc_um_nr::rlc_um_nr_tx::configure(const rlc_config_t& cnfg_, std::string r
{
cfg = cnfg_;
if (cfg.um_nr.mod == 0) {
logger.error("Error configuring %s RLC UM: tx_mod==0", rb_name.c_str());
return false;
}
mod = (cfg.um_nr.sn_field_length == rlc_um_nr_sn_size_t::size6bits) ? 64 : 4096;
UM_Window_Size = (cfg.um_nr.sn_field_length == rlc_um_nr_sn_size_t::size6bits) ? 32 : 2048;
// calculate header sizes for configured SN length
rlc_um_nr_pdu_header_t header = {};
@ -188,7 +186,7 @@ uint32_t rlc_um_nr::rlc_um_nr_tx::build_data_pdu(unique_byte_buffer_t pdu, uint8
// Update SN if needed
if (header.si == rlc_nr_si_field_t::last_segment) {
TX_Next = (TX_Next + 1) % cfg.um_nr.mod;
TX_Next = (TX_Next + 1) % mod;
next_so = 0;
}
@ -229,10 +227,8 @@ rlc_um_nr::rlc_um_nr_rx::rlc_um_nr_rx(rlc_um_base* parent_) :
bool rlc_um_nr::rlc_um_nr_rx::configure(const rlc_config_t& cnfg_, std::string rb_name_)
{
if (cfg.um_nr.mod == 0) {
logger.error("Error configuring %s RLC UM: rx_mod==0", rb_name.c_str());
return false;
}
mod = (cfg.um_nr.sn_field_length == rlc_um_nr_sn_size_t::size6bits) ? 64 : 4096;
UM_Window_Size = (cfg.um_nr.sn_field_length == rlc_um_nr_sn_size_t::size6bits) ? 32 : 2048;
// check timer
if (not reassembly_timer.is_valid()) {
@ -297,7 +293,7 @@ void rlc_um_nr::rlc_um_nr_rx::timer_expired(uint32_t timeout_id)
// update RX_Next_Reassembly to the next SN that has not been reassembled yet
RX_Next_Reassembly = RX_Timer_Trigger;
while (RX_MOD_NR_BASE(RX_Next_Reassembly) < RX_MOD_NR_BASE(RX_Next_Highest)) {
RX_Next_Reassembly = (RX_Next_Reassembly + 1) % cfg.um_nr.mod;
RX_Next_Reassembly = (RX_Next_Reassembly + 1) % mod;
debug_state();
}
@ -325,14 +321,14 @@ void rlc_um_nr::rlc_um_nr_rx::timer_expired(uint32_t timeout_id)
// Sec 5.2.2.2.1
bool rlc_um_nr::rlc_um_nr_rx::sn_in_reassembly_window(const uint32_t sn)
{
return (RX_MOD_NR_BASE(RX_Next_Highest - cfg.um_nr.UM_Window_Size) <= RX_MOD_NR_BASE(sn) &&
return (RX_MOD_NR_BASE(RX_Next_Highest - UM_Window_Size) <= RX_MOD_NR_BASE(sn) &&
RX_MOD_NR_BASE(sn) < RX_MOD_NR_BASE(RX_Next_Highest));
}
// Sec 5.2.2.2.2
bool rlc_um_nr::rlc_um_nr_rx::sn_invalid_for_rx_buffer(const uint32_t sn)
{
return (RX_MOD_NR_BASE(RX_Next_Highest - cfg.um_nr.UM_Window_Size) <= RX_MOD_NR_BASE(sn) &&
return (RX_MOD_NR_BASE(RX_Next_Highest - UM_Window_Size) <= RX_MOD_NR_BASE(sn) &&
RX_MOD_NR_BASE(sn) < RX_MOD_NR_BASE(RX_Next_Reassembly));
}
@ -414,9 +410,9 @@ void rlc_um_nr::rlc_um_nr_rx::handle_rx_buffer_update(const uint32_t sn)
// find next SN in rx buffer
if (sn == RX_Next_Reassembly) {
RX_Next_Reassembly = ((RX_Next_Reassembly + 1) % cfg.um_nr.mod);
RX_Next_Reassembly = ((RX_Next_Reassembly + 1) % mod);
while (RX_MOD_NR_BASE(RX_Next_Reassembly) < RX_MOD_NR_BASE(RX_Next_Highest)) {
RX_Next_Reassembly = (RX_Next_Reassembly + 1) % cfg.um_nr.mod;
RX_Next_Reassembly = (RX_Next_Reassembly + 1) % mod;
}
logger.debug("Updating RX_Next_Reassembly=%d", RX_Next_Reassembly);
}
@ -444,7 +440,7 @@ void rlc_um_nr::rlc_um_nr_rx::handle_rx_buffer_update(const uint32_t sn)
logger.info("%s SN: %d outside rx window [%d:%d] - discarding",
rb_name.c_str(),
it->first,
RX_Next_Highest - cfg.um_nr.UM_Window_Size,
RX_Next_Highest - UM_Window_Size,
RX_Next_Highest);
it = rx_window.erase(it);
metrics.num_lost_pdus++;
@ -456,7 +452,7 @@ void rlc_um_nr::rlc_um_nr_rx::handle_rx_buffer_update(const uint32_t sn)
if (not sn_in_reassembly_window(RX_Next_Reassembly)) {
// update RX_Next_Reassembly to first SN that has not been reassembled and delivered
for (const auto& rx_pdu : rx_window) {
if (rx_pdu.first >= RX_MOD_NR_BASE(RX_Next_Highest - cfg.um_nr.UM_Window_Size)) {
if (rx_pdu.first >= RX_MOD_NR_BASE(RX_Next_Highest - UM_Window_Size)) {
RX_Next_Reassembly = rx_pdu.first;
logger.debug("Updating RX_Next_Reassembly=%d", RX_Next_Reassembly);
break;

@ -34,10 +34,10 @@ int test_rlc_config()
rlc_cfg_asn1.to_json(jw);
srslog::fetch_basic_logger("RRC").info("RLC NR Config: \n %s", jw.to_string().c_str());
rlc_config_t rlc_cfg = make_rlc_config_t(rlc_cfg_asn1);
rlc_config_t rlc_cfg;
TESTASSERT(make_rlc_config_t(rlc_cfg_asn1, &rlc_cfg) == SRSRAN_SUCCESS);
TESTASSERT(rlc_cfg.rat == srsran_rat_t::nr);
TESTASSERT(rlc_cfg.um_nr.sn_field_length == rlc_um_nr_sn_size_t::size12bits);
TESTASSERT(rlc_cfg.um_nr.UM_Window_Size == 2048);
return SRSRAN_SUCCESS;
}

@ -461,17 +461,8 @@ bool rrc_nr::apply_rlc_add_mod(const rlc_bearer_cfg_s& rlc_bearer_cfg)
}
if (rlc_bearer_cfg.rlc_cfg_present == true) {
rlc_cfg = srsran::make_rlc_config_t(rlc_bearer_cfg.rlc_cfg);
if (rlc_bearer_cfg.rlc_cfg.type() == asn1::rrc_nr::rlc_cfg_c::types::um_bi_dir) {
if (rlc_bearer_cfg.rlc_cfg.um_bi_dir().dl_um_rlc.sn_field_len_present &&
rlc_bearer_cfg.rlc_cfg.um_bi_dir().ul_um_rlc.sn_field_len_present &&
rlc_bearer_cfg.rlc_cfg.um_bi_dir().dl_um_rlc.sn_field_len !=
rlc_bearer_cfg.rlc_cfg.um_bi_dir().ul_um_rlc.sn_field_len) {
logger.warning("NR RLC sequence number length is not the same in uplink and downlink");
return false;
}
} else {
logger.warning("NR RLC type is not unacknowledged mode bidirectional");
if (srsran::make_rlc_config_t(rlc_bearer_cfg.rlc_cfg, &rlc_cfg) != SRSRAN_SUCCESS) {
logger.warning("Failed to build RLC config");
return false;
}
} else {

Loading…
Cancel
Save