diff --git a/lib/include/srsran/rlc/rlc_am_data_structs.h b/lib/include/srsran/rlc/rlc_am_data_structs.h index f7d0ad131..2a5800125 100644 --- a/lib/include/srsran/rlc/rlc_am_data_structs.h +++ b/lib/include/srsran/rlc/rlc_am_data_structs.h @@ -214,4 +214,4 @@ private: } // namespace srsran -#endif // SRSRAN_BEARER_MEM_POOL_H +#endif // SRSRAN_RLC_AM_DATA_STRUCTS_H diff --git a/lib/include/srsran/rlc/rlc_am_lte_packing.h b/lib/include/srsran/rlc/rlc_am_lte_packing.h index f4d2d5ea5..19215d4e4 100644 --- a/lib/include/srsran/rlc/rlc_am_lte_packing.h +++ b/lib/include/srsran/rlc/rlc_am_lte_packing.h @@ -132,4 +132,4 @@ void log_rlc_am_status_pdu_to_string(srslog::log_channel& log_ch, } // namespace srsran -#endif // SRSRAN_RLC_AM_NR_H +#endif // SRSRAN_RLC_AM_LTE_PACKING_H diff --git a/lib/include/srsran/rlc/rlc_am_nr.h b/lib/include/srsran/rlc/rlc_am_nr.h index cd03e78cb..49d0dddc3 100644 --- a/lib/include/srsran/rlc/rlc_am_nr.h +++ b/lib/include/srsran/rlc/rlc_am_nr.h @@ -25,7 +25,113 @@ namespace srsran { -// TODO +class rlc_am_nr : public rlc_common +{ +public: + rlc_am_nr(srslog::basic_logger& logger, + uint32_t lcid_, + srsue::pdcp_interface_rlc* pdcp_, + srsue::rrc_interface_rlc* rrc_, + srsran::timer_handler* timers_); + bool configure(const rlc_config_t& cfg_) final; + void stop() final; + + rlc_mode_t get_mode() final; + uint32_t get_bearer() final; + + void reestablish() final; + void empty_queue() final; + void set_bsr_callback(bsr_callback_t callback) final; + + // PDCP interface + void write_sdu(unique_byte_buffer_t sdu) final; + void discard_sdu(uint32_t pdcp_sn) final; + bool sdu_queue_is_full() final; + + // MAC interface + bool has_data() final; + uint32_t get_buffer_state() final; + void get_buffer_state(uint32_t& tx_queue, uint32_t& prio_tx_queue) final; + uint32_t read_pdu(uint8_t* payload, uint32_t nof_bytes) final; + void write_pdu(uint8_t* payload, uint32_t nof_bytes) final; + + rlc_bearer_metrics_t get_metrics() final; + void reset_metrics() final; + +private: + // Transmitter sub-class + class rlc_am_nr_tx + { + public: + explicit rlc_am_nr_tx(rlc_am_nr* parent_); + ~rlc_am_nr_tx() = default; + + bool configure(const rlc_am_config_t& cfg_); + void stop(); + + int write_sdu(unique_byte_buffer_t sdu); + uint32_t read_pdu(uint8_t* payload, uint32_t nof_bytes); + void discard_sdu(uint32_t discard_sn); + bool sdu_queue_is_full(); + + bool has_data(); + uint32_t get_buffer_state(); + + rlc_am_nr* parent = nullptr; + srslog::basic_logger& logger; + + private: + byte_buffer_pool* pool = nullptr; + + /**************************************************************************** + * Configurable parameters + * Ref: 3GPP TS 38.322 v10.0.0 Section 7.4 + ***************************************************************************/ + rlc_am_config_t cfg = {}; + }; + + // Receiver sub-class + class rlc_am_nr_rx + { + public: + explicit rlc_am_nr_rx(rlc_am_nr* parent_); + ~rlc_am_nr_rx() = default; + + bool configure(const rlc_am_config_t& cfg_); + void stop(); + + void write_pdu(uint8_t* payload, uint32_t nof_bytes); + + rlc_am_nr* parent = nullptr; + srslog::basic_logger& logger; + + private: + byte_buffer_pool* pool = nullptr; + + /**************************************************************************** + * Configurable parameters + * Ref: 3GPP TS 38.322 v10.0.0 Section 7.4 + ***************************************************************************/ + rlc_am_config_t cfg = {}; + }; + + // Common variables needed/provided by parent class + srsue::rrc_interface_rlc* rrc = nullptr; + srslog::basic_logger& logger; + srsue::pdcp_interface_rlc* pdcp = nullptr; + srsran::timer_handler* timers = nullptr; + uint32_t lcid = 0; + rlc_config_t cfg = {}; + std::string rb_name; + + static const int poll_periodicity = 8; // After how many data PDUs a status PDU shall be requested + + // Rx and Tx objects + rlc_am_nr_tx tx; + rlc_am_nr_rx rx; + + rlc_bearer_metrics_t metrics = {}; +}; } // namespace srsran diff --git a/lib/include/srsran/rlc/rlc_am_nr_packing.h b/lib/include/srsran/rlc/rlc_am_nr_packing.h index f31aa2c42..80f55042a 100644 --- a/lib/include/srsran/rlc/rlc_am_nr_packing.h +++ b/lib/include/srsran/rlc/rlc_am_nr_packing.h @@ -72,4 +72,4 @@ int32_t rlc_am_nr_write_status_pdu(const rlc_am_nr_status_pdu_t& status_pdu, } // namespace srsran -#endif // SRSRAN_RLC_AM_NR_H +#endif // SRSRAN_RLC_AM_NR_PACKING_H diff --git a/lib/src/rlc/rlc_am_nr.cc b/lib/src/rlc/rlc_am_nr.cc index cef2d1935..4b96e5724 100644 --- a/lib/src/rlc/rlc_am_nr.cc +++ b/lib/src/rlc/rlc_am_nr.cc @@ -22,6 +22,195 @@ namespace srsran { /******************************* * RLC AM NR class ******************************/ -// TODO +rlc_am_nr::rlc_am_nr(srslog::basic_logger& logger, + uint32_t lcid_, + srsue::pdcp_interface_rlc* pdcp_, + srsue::rrc_interface_rlc* rrc_, + srsran::timer_handler* timers_) : + logger(logger), rrc(rrc_), pdcp(pdcp_), timers(timers_), lcid(lcid_), tx(this), rx(this) +{} + +// Applies new configuration. Must be just reestablished or initiated +bool rlc_am_nr::configure(const rlc_config_t& cfg_) +{ + // determine bearer name and configure Rx/Tx objects + rb_name = rrc->get_rb_name(lcid); + + // store config + cfg = cfg_; + + if (not rx.configure(cfg.am)) { + logger.error("Error configuring bearer (RX)"); + return false; + } + + if (not tx.configure(cfg.am)) { + logger.error("Error configuring bearer (TX)"); + return false; + } + + logger.info("%s configured: t_poll_retx=%d, poll_pdu=%d, poll_byte=%d, max_retx_thresh=%d, " + "t_reordering=%d, t_status_prohibit=%d", + rb_name.c_str(), + cfg.am.t_poll_retx, + cfg.am.poll_pdu, + cfg.am.poll_byte, + cfg.am.max_retx_thresh, + cfg.am.t_reordering, + cfg.am.t_status_prohibit); + return true; +} + +void rlc_am_nr::stop() {} + +rlc_mode_t rlc_am_nr::get_mode() +{ + return rlc_mode_t::am; +} + +uint32_t rlc_am_nr::get_bearer() +{ + return 0; +} + +void rlc_am_nr::reestablish() {} + +void rlc_am_nr::empty_queue() {} + +void rlc_am_nr::set_bsr_callback(bsr_callback_t callback) {} + +rlc_bearer_metrics_t rlc_am_nr::get_metrics() +{ + return {}; +} + +void rlc_am_nr::reset_metrics() {} + +/**************************************************************************** + * PDCP interface + ***************************************************************************/ +void rlc_am_nr::write_sdu(unique_byte_buffer_t sdu) +{ + if (tx.write_sdu(std::move(sdu)) == SRSRAN_SUCCESS) { + metrics.num_tx_sdus++; + } +} + +void rlc_am_nr::discard_sdu(uint32_t pdcp_sn) +{ + tx.discard_sdu(pdcp_sn); + metrics.num_lost_sdus++; +} + +bool rlc_am_nr::sdu_queue_is_full() +{ + return tx.sdu_queue_is_full(); +} + +/**************************************************************************** + * MAC interface + ***************************************************************************/ + +bool rlc_am_nr::has_data() +{ + return tx.has_data(); +} + +uint32_t rlc_am_nr::get_buffer_state() +{ + return tx.get_buffer_state(); +} + +void rlc_am_nr::get_buffer_state(uint32_t& tx_queue, uint32_t& prio_tx_queue) +{ + // TODO + tx_queue = tx.get_buffer_state(); + prio_tx_queue = 0; +} + +uint32_t rlc_am_nr::read_pdu(uint8_t* payload, uint32_t nof_bytes) +{ + uint32_t read_bytes = tx.read_pdu(payload, nof_bytes); + metrics.num_tx_pdus++; + metrics.num_tx_pdu_bytes += read_bytes; + return read_bytes; +} + +void rlc_am_nr::write_pdu(uint8_t* payload, uint32_t nof_bytes) +{ + rx.write_pdu(payload, nof_bytes); + metrics.num_rx_pdus++; + metrics.num_rx_pdu_bytes += nof_bytes; +} + +/**************************************************************************** + * Tx subclass implementation + ***************************************************************************/ +rlc_am_nr::rlc_am_nr_tx::rlc_am_nr_tx(rlc_am_nr* parent_) : + parent(parent_), logger(parent_->logger), pool(byte_buffer_pool::get_instance()) +{} + +bool rlc_am_nr::rlc_am_nr_tx::configure(const rlc_am_config_t& cfg_) +{ + /* + 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.", + cfg_.tx_queue_length, + MAX_SDUS_PER_RLC_PDU); + return false; + } + */ + cfg = cfg_; + + return true; +} + +int rlc_am_nr::rlc_am_nr_tx::write_sdu(unique_byte_buffer_t sdu) +{ + return 0; +} + +void rlc_am_nr::rlc_am_nr_tx::discard_sdu(uint32_t sn) +{ + return; +} + +bool rlc_am_nr::rlc_am_nr_tx::sdu_queue_is_full() +{ + return false; +} + +bool rlc_am_nr::rlc_am_nr_tx::has_data() +{ + return true; +} + +uint32_t rlc_am_nr::rlc_am_nr_tx::read_pdu(uint8_t* payload, uint32_t nof_bytes) +{ + return 0; +} + +uint32_t rlc_am_nr::rlc_am_nr_tx::get_buffer_state() +{ + return 0; +} + +/**************************************************************************** + * Rx subclass implementation + ***************************************************************************/ +rlc_am_nr::rlc_am_nr_rx::rlc_am_nr_rx(rlc_am_nr* parent_) : + parent(parent_), pool(byte_buffer_pool::get_instance()), logger(parent_->logger) +{} + +bool rlc_am_nr::rlc_am_nr_rx::configure(const rlc_am_config_t& cfg_) +{ + cfg = cfg_; + + return true; +} + +void rlc_am_nr::rlc_am_nr_rx::stop() {} + +void rlc_am_nr::rlc_am_nr_rx::write_pdu(uint8_t* payload, uint32_t nof_bytes) {} } // namespace srsran