diff --git a/lib/include/srsran/interfaces/rlc_interface_types.h b/lib/include/srsran/interfaces/rlc_interface_types.h index fdad4e3ce..dbef7b071 100644 --- a/lib/include/srsran/interfaces/rlc_interface_types.h +++ b/lib/include/srsran/interfaces/rlc_interface_types.h @@ -87,6 +87,26 @@ struct rlc_am_config_t { int32_t t_status_prohibit; // Timer used by rx to prohibit tx of status PDU (ms) }; +struct rlc_am_nr_config_t { + /**************************************************************************** + * Configurable parameters + * Ref: 3GPP TS 38.322 Section 7 + ***************************************************************************/ + + rlc_am_nr_sn_size_t tx_sn_field_length; // Number of bits used for tx (UL) sequence number + rlc_am_nr_sn_size_t rx_sn_field_length; // Number of bits used for rx (DL) sequence number + + // Timers Ref: 3GPP TS 38.322 Section 7.3 + int32_t t_poll_retx; // Poll retx timeout (ms) + int32_t t_reassambly; // Timer used by rx to detect PDU loss (ms) + int32_t t_status_prohibit; // Timer used by rx to prohibit tx of status PDU (ms) + + // Configurable Parameters. Ref: 3GPP TS 38.322 Section 7.4 + uint32_t max_retx_thresh; // Max number of retx + int32_t poll_pdu; // Insert poll bit after this many PDUs + int32_t poll_byte; // Insert poll bit after this much data (KB) +}; + struct rlc_um_config_t { /**************************************************************************** * Configurable parameters @@ -122,12 +142,13 @@ public: srsran_rat_t rat; rlc_mode_t rlc_mode; rlc_am_config_t am; + rlc_am_nr_config_t am_nr; rlc_um_config_t um; rlc_um_nr_config_t um_nr; uint32_t tx_queue_length; rlc_config_t() : - rat(srsran_rat_t::lte), rlc_mode(rlc_mode_t::tm), am(), um(), um_nr(), tx_queue_length(RLC_TX_QUEUE_LEN){}; + rat(srsran_rat_t::lte), rlc_mode(rlc_mode_t::tm), am(), am_nr(), um(), um_nr(), tx_queue_length(RLC_TX_QUEUE_LEN){}; // Factory for MCH static rlc_config_t mch_config() diff --git a/lib/include/srsran/rlc/rlc_am_nr.h b/lib/include/srsran/rlc/rlc_am_nr.h index f841e14ba..0969f0e67 100644 --- a/lib/include/srsran/rlc/rlc_am_nr.h +++ b/lib/include/srsran/rlc/rlc_am_nr.h @@ -70,7 +70,7 @@ private: * Configurable parameters * Ref: 3GPP TS 38.322 v10.0.0 Section 7.4 ***************************************************************************/ - rlc_am_config_t cfg = {}; + rlc_am_nr_config_t cfg = {}; /**************************************************************************** * Tx state variables diff --git a/lib/src/asn1/rrc_nr_utils.cc b/lib/src/asn1/rrc_nr_utils.cc index f345d84db..e68706dc4 100644 --- a/lib/src/asn1/rrc_nr_utils.cc +++ b/lib/src/asn1/rrc_nr_utils.cc @@ -108,8 +108,25 @@ int make_rlc_config_t(const rlc_cfg_c& asn1_type, uint8_t bearer_id, rlc_config_ rlc_cfg.rat = srsran_rat_t::nr; switch (asn1_type.type().value) { case rlc_cfg_c::types_opts::am: - asn1::log_warning("NR RLC type %s is not supported", asn1_type.type().to_string()); - return SRSRAN_ERROR; + if (asn1_type.am().dl_am_rlc.sn_field_len_present && asn1_type.am().ul_am_rlc.sn_field_len_present && + asn1_type.am().dl_am_rlc.sn_field_len != asn1_type.am().ul_am_rlc.sn_field_len) { + asn1::log_warning("NR RLC sequence number length is not the same in uplink and downlink"); + return SRSRAN_ERROR; + } + rlc_cfg.rlc_mode = rlc_mode_t::am; + switch (asn1_type.am().dl_am_rlc.sn_field_len.value) { + case asn1::rrc_nr::sn_field_len_am_opts::options::size12: + rlc_cfg.am_nr.tx_sn_field_length = rlc_am_nr_sn_size_t::size12bits; + rlc_cfg.am_nr.rx_sn_field_length = rlc_am_nr_sn_size_t::size12bits; + break; + case asn1::rrc_nr::sn_field_len_am_opts::options::size18: + rlc_cfg.am_nr.tx_sn_field_length = rlc_am_nr_sn_size_t::size18bits; + rlc_cfg.am_nr.rx_sn_field_length = rlc_am_nr_sn_size_t::size18bits; + break; + default: + break; + } + break; case rlc_cfg_c::types_opts::um_bi_dir: 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.to_number(); diff --git a/lib/src/rlc/rlc.cc b/lib/src/rlc/rlc.cc index 46ce05ee8..145ceb06c 100644 --- a/lib/src/rlc/rlc.cc +++ b/lib/src/rlc/rlc.cc @@ -12,7 +12,7 @@ #include "srsran/rlc/rlc.h" #include "srsran/common/rwlock_guard.h" -#include "srsran/rlc/rlc_am_lte.h" +#include "srsran/rlc/rlc_am_base.h" #include "srsran/rlc/rlc_tm.h" #include "srsran/rlc/rlc_um_lte.h" #include "srsran/rlc/rlc_um_nr.h" @@ -398,6 +398,9 @@ int rlc::add_bearer(uint32_t lcid, const rlc_config_t& cnfg) case srsran_rat_t::lte: rlc_entity = std::unique_ptr(new rlc_am(cnfg.rat, logger, lcid, pdcp, rrc, timers)); break; + case srsran_rat_t::nr: + rlc_entity = std::unique_ptr(new rlc_am(cnfg.rat, logger, lcid, pdcp, rrc, timers)); + break; default: logger.error("AM not supported for this RAT"); return SRSRAN_ERROR; diff --git a/lib/src/rlc/rlc_am_base.cc b/lib/src/rlc/rlc_am_base.cc index bd2143f17..8805d966f 100644 --- a/lib/src/rlc/rlc_am_base.cc +++ b/lib/src/rlc/rlc_am_base.cc @@ -207,7 +207,7 @@ int rlc_am::rlc_am_base_tx::write_sdu(unique_byte_buffer_t sdu) } if (sdu.get() == nullptr) { - srslog::fetch_basic_logger("RLC").warning("NULL SDU pointer in write_sdu()"); + logger->warning("NULL SDU pointer in write_sdu()"); return SRSRAN_ERROR; } @@ -219,16 +219,15 @@ int rlc_am::rlc_am_base_tx::write_sdu(unique_byte_buffer_t sdu) uint32_t nof_bytes = sdu->N_bytes; srsran::error_type ret = tx_sdu_queue.try_write(std::move(sdu)); if (ret) { - srslog::fetch_basic_logger("RLC").info( - msg_ptr, nof_bytes, "%s Tx SDU (%d B, tx_sdu_queue_len=%d)", rb_name, nof_bytes, tx_sdu_queue.size()); + logger->info(msg_ptr, nof_bytes, "%s Tx SDU (%d B, tx_sdu_queue_len=%d)", rb_name, nof_bytes, tx_sdu_queue.size()); } else { // in case of fail, the try_write returns back the sdu - srslog::fetch_basic_logger("RLC").warning(ret.error()->msg, - ret.error()->N_bytes, - "[Dropped SDU] %s Tx SDU (%d B, tx_sdu_queue_len=%d)", - rb_name, - ret.error()->N_bytes, - tx_sdu_queue.size()); + logger->warning(ret.error()->msg, + ret.error()->N_bytes, + "[Dropped SDU] %s Tx SDU (%d B, tx_sdu_queue_len=%d)", + rb_name, + ret.error()->N_bytes, + tx_sdu_queue.size()); return SRSRAN_ERROR; } @@ -247,6 +246,7 @@ void rlc_am::rlc_am_base_tx::set_bsr_callback(bsr_callback_t callback) *******************************************************/ void rlc_am::rlc_am_base_rx::write_pdu(uint8_t* payload, const uint32_t nof_bytes) { + logger->info("Rx PDU -- N bytes %d", nof_bytes); if (nof_bytes < 1) { return; } diff --git a/lib/src/rlc/rlc_am_nr.cc b/lib/src/rlc/rlc_am_nr.cc index be0d1930c..95481abdc 100644 --- a/lib/src/rlc/rlc_am_nr.cc +++ b/lib/src/rlc/rlc_am_nr.cc @@ -41,6 +41,13 @@ rlc_am_nr_tx::rlc_am_nr_tx(rlc_am* parent_) : parent(parent_), rlc_am_base_tx(&p bool rlc_am_nr_tx::configure(const rlc_config_t& cfg_) { + cfg = cfg_.am_nr; + + if (cfg.tx_sn_field_length != rlc_am_nr_sn_size_t::size12bits) { + logger->warning("RLC AM NR only supporst 12 bit SN length."); + return false; + } + /* if (cfg_.tx_queue_length > MAX_SDUS_PER_RLC_PDU) { logger.error("Configuring Tx queue length of %d PDUs too big. Maximum value is %d.", @@ -49,8 +56,6 @@ bool rlc_am_nr_tx::configure(const rlc_config_t& cfg_) return false; } */ - cfg = cfg_.am; - tx_enabled = true; return true; @@ -72,13 +77,12 @@ uint32_t rlc_am_nr_tx::read_pdu(uint8_t* payload, uint32_t nof_bytes) logger->debug("MAC opportunity - %d bytes", nof_bytes); // logger.debug("tx_window size - %zu PDUs", tx_window.size()); - // Build a PDU from SDU - unique_byte_buffer_t tx_pdu = srsran::make_byte_buffer(); - // Tx STATUS if requested if (do_status() /*&& not status_prohibit_timer.is_running()*/) { + unique_byte_buffer_t tx_pdu = srsran::make_byte_buffer(); build_status_pdu(tx_pdu.get(), nof_bytes); memcpy(payload, tx_pdu->msg, tx_pdu->N_bytes); + logger->debug("Status PDU built - %d bytes", tx_pdu->N_bytes); return tx_pdu->N_bytes; } @@ -94,17 +98,23 @@ uint32_t rlc_am_nr_tx::read_pdu(uint8_t* payload, uint32_t nof_bytes) tx_sdu = tx_sdu_queue.read(); } while (tx_sdu == nullptr && tx_sdu_queue.size() != 0); + if (tx_sdu != nullptr) { + logger->debug("Read RLC SDU - %d bytes", tx_sdu->N_bytes); + } + uint16_t hdr_size = 2; if (tx_sdu->N_bytes + hdr_size > nof_bytes) { logger->warning("Segmentation not supported yet"); return 0; } + rlc_am_nr_pdu_header_t hdr = {}; hdr.dc = RLC_DC_FIELD_DATA_PDU; hdr.p = 1; // FIXME hdr.si = rlc_nr_si_field_t::full_sdu; hdr.sn_size = rlc_am_nr_sn_size_t::size12bits; hdr.sn = st.tx_next; + log_rlc_am_nr_pdu_header_to_string(logger->info, hdr); uint32_t len = rlc_am_nr_write_data_pdu_header(hdr, tx_sdu.get()); if (len > nof_bytes) { @@ -115,6 +125,8 @@ uint32_t rlc_am_nr_tx::read_pdu(uint8_t* payload, uint32_t nof_bytes) st.tx_next = (st.tx_next + 1) % MOD; memcpy(payload, tx_sdu->msg, tx_sdu->N_bytes); + logger->debug("Wrote RLC PDU - %d bytes", tx_sdu->N_bytes); + return tx_sdu->N_bytes; }