diff --git a/lib/include/srsran/asn1/rrc_nr_utils.h b/lib/include/srsran/asn1/rrc_nr_utils.h index c3a3d6237..398f79f8c 100644 --- a/lib/include/srsran/asn1/rrc_nr_utils.h +++ b/lib/include/srsran/asn1/rrc_nr_utils.h @@ -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 diff --git a/lib/include/srsran/interfaces/rlc_interface_types.h b/lib/include/srsran/interfaces/rlc_interface_types.h index 11c124ca5..e19766e0c 100644 --- a/lib/include/srsran/interfaces/rlc_interface_types.h +++ b/lib/include/srsran/interfaces/rlc_interface_types.h @@ -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 {}; } diff --git a/lib/include/srsran/upper/rlc_um_nr.h b/lib/include/srsran/upper/rlc_um_nr.h index 6c5e4936e..11c6bd55c 100644 --- a/lib/include/srsran/upper/rlc_um_nr.h +++ b/lib/include/srsran/upper/rlc_um_nr.h @@ -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 segments; // Map of segments with SO as key diff --git a/lib/src/asn1/rrc_nr_utils.cc b/lib/src/asn1/rrc_nr_utils.cc index ca5021b80..d6cbd9165 100644 --- a/lib/src/asn1/rrc_nr_utils.cc +++ b/lib/src/asn1/rrc_nr_utils.cc @@ -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) diff --git a/lib/src/upper/rlc_um_nr.cc b/lib/src/upper/rlc_um_nr.cc index 1cf1aa4af..32fc1948d 100644 --- a/lib/src/upper/rlc_um_nr.cc +++ b/lib/src/upper/rlc_um_nr.cc @@ -14,7 +14,7 @@ #include "srsran/interfaces/ue_pdcp_interfaces.h" #include -#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; diff --git a/lib/test/asn1/rrc_nr_utils_test.cc b/lib/test/asn1/rrc_nr_utils_test.cc index 7bea15aff..82c1431ff 100644 --- a/lib/test/asn1/rrc_nr_utils_test.cc +++ b/lib/test/asn1/rrc_nr_utils_test.cc @@ -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; } diff --git a/srsue/src/stack/rrc/rrc_nr.cc b/srsue/src/stack/rrc/rrc_nr.cc index 01a5bb5c5..18ee3375a 100644 --- a/srsue/src/stack/rrc/rrc_nr.cc +++ b/srsue/src/stack/rrc/rrc_nr.cc @@ -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 {