diff --git a/lib/include/srsran/interfaces/mac_interface_types.h b/lib/include/srsran/interfaces/mac_interface_types.h index 964b8ef34..e5ec84609 100644 --- a/lib/include/srsran/interfaces/mac_interface_types.h +++ b/lib/include/srsran/interfaces/mac_interface_types.h @@ -87,6 +87,13 @@ struct ul_harq_cfg_t { } }; +/// NR specific config for DL HARQ with configurable number of processes +struct dl_harq_cfg_nr_t { + uint8_t nof_procs; // Number of HARQ processes used in the DL + dl_harq_cfg_nr_t() { reset(); } + void reset() { nof_procs = SRSRAN_DEFAULT_HARQ_PROC_DL_NR; } +}; + struct rach_cfg_t { bool enabled; uint32_t nof_preambles; @@ -145,7 +152,7 @@ struct sr_cfg_item_nr_t { #define SRSRAN_MAX_MAX_NR_OF_SR_CFG_PER_CELL_GROUP (8) struct sr_cfg_nr_t { - bool enabled; + bool enabled; uint8_t num_items; sr_cfg_item_nr_t item[SRSRAN_MAX_MAX_NR_OF_SR_CFG_PER_CELL_GROUP]; }; diff --git a/lib/include/srsran/interfaces/ue_nr_interfaces.h b/lib/include/srsran/interfaces/ue_nr_interfaces.h index 0ba59cb61..5e003d33a 100644 --- a/lib/include/srsran/interfaces/ue_nr_interfaces.h +++ b/lib/include/srsran/interfaces/ue_nr_interfaces.h @@ -33,13 +33,31 @@ public: class mac_interface_phy_nr { public: + /// For DL, PDU buffer is allocated and passed to MAC in tb_decoded() + typedef struct { + bool enabled; /// Whether or not PHY should attempt to decode PDSCH + srsran_softbuffer_rx_t* softbuffer; /// Pointer to softbuffer to use + } tb_dl_t; + + /// Struct provided by MAC with all necessary information for PHY + typedef struct { + tb_dl_t tb; // only single TB in DL + } tb_action_dl_t; + typedef struct { - srsran::unique_byte_buffer_t tb[SRSRAN_MAX_TB]; - uint32_t pid; uint16_t rnti; uint32_t tti; + uint8_t pid; // HARQ process ID + uint8_t rv; // Redundancy Version + uint8_t ndi; // Raw new data indicator extracted from DCI + uint32_t tbs; // Transport block size in Bytes } mac_nr_grant_dl_t; + typedef struct { + srsran::unique_byte_buffer_t payload; // TB when decoded successfully, nullptr otherwise + bool ack; // HARQ information + } tb_action_dl_result_t; + // UL grant as conveyed between PHY and MAC typedef struct { uint16_t rnti; @@ -74,8 +92,25 @@ public: virtual sched_rnti_t get_dl_sched_rnti_nr(const uint32_t tti) = 0; virtual sched_rnti_t get_ul_sched_rnti_nr(const uint32_t tti) = 0; - /// Indicate succussfully received TB to MAC. The TB buffer is allocated in the PHY and handed as unique_ptr to MAC - virtual void tb_decoded(const uint32_t cc_idx, mac_nr_grant_dl_t& grant) = 0; + /** + * @brief Indicate reception of DL grant to MAC + * + * The TB buffer is allocated in the PHY and handed as unique_ptr to MAC. + * + * @param cc_idx The carrier index on which the grant has been received + * @param grant Reference to the grant + * @param action Pointer to the TB action to be filled by MAC + */ + virtual void new_grant_dl(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_t* action) = 0; + + /** + * Indicate decoding of PDSCH + * + * @param cc_idx The index of the carrier for which the PDSCH has been decoded + * @param grant The original DL grant + * @param result Payload (if any) and ack information + */ + virtual void tb_decoded(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_result_t result) = 0; /** * @brief Indicate reception of UL grant to MAC diff --git a/lib/src/common/basic_vnf.cc b/lib/src/common/basic_vnf.cc index 69a020e47..81170e633 100644 --- a/lib/src/common/basic_vnf.cc +++ b/lib/src/common/basic_vnf.cc @@ -182,12 +182,14 @@ int srsran_basic_vnf::handle_dl_ind(basic_vnf_api::dl_ind_msg_t* msg) } for (uint32_t i = 0; i < msg->nof_pdus; ++i) { - dl_grant.tb[i] = srsran::make_byte_buffer(); - if (dl_grant.tb[i] && dl_grant.tb[i]->get_tailroom() >= msg->pdus[i].length) { - memcpy(dl_grant.tb[i]->msg, msg->pdus[i].data, msg->pdus[i].length); - dl_grant.tb[i]->N_bytes = msg->pdus[i].length; + srsue::stack_interface_phy_nr::tb_action_dl_result_t result = {}; + result.payload = srsran::make_byte_buffer(); + if (result.payload != nullptr && result.payload->get_tailroom() >= msg->pdus[i].length) { + result.ack = true; + memcpy(result.payload->msg, msg->pdus[i].data, msg->pdus[i].length); + result.payload->N_bytes = msg->pdus[i].length; if (msg->pdus[i].type == basic_vnf_api::PDSCH) { - m_ue_stack->tb_decoded(cc_idx, dl_grant); + m_ue_stack->tb_decoded(cc_idx, dl_grant, std::move(result)); } } else { logger.error("TB too big to fit into buffer (%d)", msg->pdus[i].length); diff --git a/lib/src/phy/phch/ra_nr.c b/lib/src/phy/phch/ra_nr.c index 9387df894..bbe8fbbf2 100644 --- a/lib/src/phy/phch/ra_nr.c +++ b/lib/src/phy/phch/ra_nr.c @@ -677,6 +677,8 @@ int srsran_ra_dl_dci_to_grant_nr(const srsran_carrier_nr_t* carrier, pdsch_grant->rnti_type = dci_dl->ctx.rnti_type; pdsch_grant->tb[0].rv = dci_dl->rv; pdsch_grant->tb[0].mcs = dci_dl->mcs; + pdsch_grant->tb[0].ndi = dci_dl->ndi; + pdsch_grant->tb[0].pid = dci_dl->pid; // 5.1.4 PDSCH resource mapping if (ra_dl_resource_mapping(carrier, slot, pdsch_hl_cfg, pdsch_cfg) < SRSRAN_SUCCESS) { diff --git a/lib/src/upper/pdcp_entity_lte.cc b/lib/src/upper/pdcp_entity_lte.cc index 8401e8180..631a9e62d 100644 --- a/lib/src/upper/pdcp_entity_lte.cc +++ b/lib/src/upper/pdcp_entity_lte.cc @@ -719,7 +719,7 @@ void pdcp_entity_lte::notify_delivery(const pdcp_sn_vector_t& pdcp_sns) } // Find undelivered PDU info if (not undelivered_sdus->has_sdu(sn)) { - logger.warning("Could not find PDU for delivery notification. Notified SN=%d", sn); + logger.info("Could not find PDU for delivery notification. Notified SN=%d", sn); } else { // Metrics auto& sdu = (*undelivered_sdus)[sn]; diff --git a/srsue/hdr/phy/nr/cc_worker.h b/srsue/hdr/phy/nr/cc_worker.h index 80002d8b7..84b7f7c6d 100644 --- a/srsue/hdr/phy/nr/cc_worker.h +++ b/srsue/hdr/phy/nr/cc_worker.h @@ -51,9 +51,6 @@ private: srsran_ue_ul_nr_t ue_ul = {}; srslog::basic_logger& logger; - // Temporal attributes - srsran_softbuffer_rx_t softbuffer_rx = {}; - // Methods for DL... void decode_pdcch_ul(); void decode_pdcch_dl(); diff --git a/srsue/hdr/stack/mac_nr/demux_nr.h b/srsue/hdr/stack/mac_nr/demux_nr.h new file mode 100644 index 000000000..d14d24999 --- /dev/null +++ b/srsue/hdr/stack/mac_nr/demux_nr.h @@ -0,0 +1,60 @@ +/** + * + * \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 SRSLTE_DEMUX_NR_H +#define SRSLTE_DEMUX_NR_H + +#include "mac_nr_interfaces.h" +#include "srsran/common/block_queue.h" +#include "srsran/interfaces/ue_rlc_interfaces.h" + +namespace srsue { + +/** + * @brief Logical Channel Demultiplexing and MAC CE dissassemble according to TS 38.321 + * + * Currently only SDU handling for SCH PDU processing is implemented. + * Downlink CE are parsed but not handled. + * + * PDUs can be pushed by multiple HARQ processes in parallel. + * Handling of the PDUs is done from Stack thread which reads the enqueued PDUs + * from the thread-safe queue. + */ +class demux_nr : public demux_interface_harq_nr +{ +public: + demux_nr(srslog::basic_logger& logger_); + ~demux_nr(); + + int32_t init(rlc_interface_mac* rlc_); + + void process_pdus(); /// Called by MAC to process received PDUs + + // HARQ interface + void push_pdu(srsran::unique_byte_buffer_t pdu, uint32_t tti); + +private: + // internal helpers + void handle_pdu(srsran::unique_byte_buffer_t pdu); + + srslog::basic_logger& logger; + rlc_interface_mac* rlc = nullptr; + + ///< currently only DCH PDUs supported (add BCH, PCH, etc) + srsran::block_queue pdu_queue; + + srsran::mac_sch_pdu_nr rx_pdu; +}; + +} // namespace srsue + +#endif // SRSLTE_DEMUX_NR_H diff --git a/srsue/hdr/stack/mac_nr/dl_harq_nr.h b/srsue/hdr/stack/mac_nr/dl_harq_nr.h new file mode 100644 index 000000000..308834842 --- /dev/null +++ b/srsue/hdr/stack/mac_nr/dl_harq_nr.h @@ -0,0 +1,103 @@ +/** + * + * \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 SRSLTE_DL_HARQ_NR_H +#define SRSLTE_DL_HARQ_NR_H + +#include "srsran/interfaces/mac_interface_types.h" +#include "srsran/interfaces/ue_nr_interfaces.h" +#include "srsran/srslog/logger.h" +#include "srsue/hdr/stack/mac_nr/mac_nr_interfaces.h" +#include + +namespace srsue { + +/** + * @brief Downlink HARQ entity as defined in 5.3.2 of 38.321 + * + * The class supports a configurable number of HARQ processes (up to 16). + * + * The class is configured (init and reset) by the MAC class from the + * Stack thread context. Main functionality, however, is carried + * out from a PHY worker context. + * + * Concurrent access from threads is protected through rwlocks. + * + */ +class dl_harq_entity_nr +{ + using mac_nr_grant_dl_t = mac_interface_phy_nr::mac_nr_grant_dl_t; + +public: + dl_harq_entity_nr(uint8_t cc_idx_, mac_interface_harq_nr* mac_, demux_interface_harq_nr* demux_unit_); + ~dl_harq_entity_nr(); + + int32_t set_config(const srsran::dl_harq_cfg_nr_t& cfg_); + void reset(); + + /// PHY->MAC interface for DL processes + void new_grant_dl(const mac_nr_grant_dl_t& grant, mac_interface_phy_nr::tb_action_dl_t* action); + void tb_decoded(const mac_nr_grant_dl_t& grant, mac_interface_phy_nr::tb_action_dl_result_t result); + + float get_average_retx(); + +private: + class dl_harq_process_nr + { + public: + dl_harq_process_nr(dl_harq_entity_nr* parent); + ~dl_harq_process_nr(); + bool init(int pid); + void reset(void); + uint8_t get_ndi(); + + void + new_grant_dl(const mac_nr_grant_dl_t& grant, const bool& ndi_toggled, mac_interface_phy_nr::tb_action_dl_t* action); + void tb_decoded(const mac_nr_grant_dl_t& grant, mac_interface_phy_nr::tb_action_dl_result_t result); + + private: + dl_harq_entity_nr* harq_entity = nullptr; + srslog::basic_logger& logger; + + bool is_first_tb = true; + + bool is_bcch = false; + uint32_t pid = 0; // HARQ Proccess ID + bool acked = false; + uint32_t n_retx = 0; + + mac_nr_grant_dl_t current_grant = {}; + std::unique_ptr softbuffer_rx; + }; + + // Private members of dl_harq_entity_nr + mac_interface_harq_nr* mac = nullptr; + srsran::dl_harq_cfg_nr_t cfg = {}; + std::array, SRSRAN_MAX_HARQ_PROC_DL_NR> harq_procs; + dl_harq_process_nr bcch_proc; + demux_interface_harq_nr* demux_unit = nullptr; + srslog::basic_logger& logger; + uint16_t last_temporal_crnti = SRSRAN_INVALID_RNTI; + + float average_retx = 0.0; + uint64_t nof_pkts = 0; + uint8_t cc_idx = 0; + + pthread_rwlock_t rwlock; +}; + +typedef std::unique_ptr dl_harq_entity_nr_ptr; +typedef std::array dl_harq_entity_nr_vector; + +} // namespace srsue + +#endif // SRSLTE_DL_HARQ_NR_H diff --git a/srsue/hdr/stack/mac_nr/mac_nr.h b/srsue/hdr/stack/mac_nr/mac_nr.h index 354499434..c6dc63d13 100644 --- a/srsue/hdr/stack/mac_nr/mac_nr.h +++ b/srsue/hdr/stack/mac_nr/mac_nr.h @@ -13,16 +13,17 @@ #ifndef SRSUE_MAC_NR_H #define SRSUE_MAC_NR_H +#include "dl_harq_nr.h" #include "mac_nr_interfaces.h" #include "proc_bsr_nr.h" #include "proc_ra_nr.h" #include "proc_sr_nr.h" -#include "srsran/common/block_queue.h" #include "srsran/common/mac_pcap.h" #include "srsran/interfaces/mac_interface_types.h" #include "srsran/interfaces/ue_nr_interfaces.h" #include "srsran/srslog/srslog.h" #include "srsue/hdr/stack/mac_common/mac_common.h" +#include "srsue/hdr/stack/mac_nr/demux_nr.h" #include "srsue/hdr/stack/mac_nr/mux_nr.h" #include "srsue/hdr/stack/ue_stack_base.h" #include "ul_harq_nr.h" @@ -44,7 +45,7 @@ public: mac_nr(srsran::ext_task_sched_handle task_sched_); ~mac_nr(); - int init(const mac_nr_args_t& args_, phy_interface_mac_nr* phy, rlc_interface_mac* rlc, rrc_interface_mac* rrc_); + int init(const mac_nr_args_t& args_, phy_interface_mac_nr* phy_, rlc_interface_mac* rlc_, rrc_interface_mac* rrc_); void stop(); void reset(); @@ -59,7 +60,8 @@ public: sched_rnti_t get_ul_sched_rnti_nr(const uint32_t tti); int sf_indication(const uint32_t tti); - void tb_decoded(const uint32_t cc_idx, mac_nr_grant_dl_t& grant); + void tb_decoded(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_result_t result); + void new_grant_dl(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_t* action); void new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant, tb_action_ul_t* action); void prach_sent(const uint32_t tti, const uint32_t s_id, @@ -111,7 +113,9 @@ public: static bool is_in_window(uint32_t tti, int* start, int* len); private: - void write_pcap(const uint32_t cc_idx, mac_nr_grant_dl_t& grant); // If PCAPs are enabled for this MAC + void write_pcap(const uint32_t cc_idx, + const mac_nr_grant_dl_t& grant, + tb_action_dl_result_t& tb); // If PCAPs are enabled for this MAC void handle_pdu(srsran::unique_byte_buffer_t pdu); void get_ul_data(const mac_nr_grant_ul_t& grant, srsran::byte_buffer_t* tx_pdu); @@ -145,14 +149,8 @@ private: uint16_t c_rnti = SRSRAN_INVALID_RNTI; uint64_t contention_id = 0; - srsran::block_queue - pdu_queue; ///< currently only DCH PDUs supported (add BCH, PCH, etc) - std::array metrics = {}; - /// Rx buffer - srsran::mac_sch_pdu_nr rx_pdu; - srsran::task_multiqueue::queue_handle stack_task_dispatch_queue; // MAC Uplink-related procedures @@ -160,10 +158,11 @@ private: proc_sr_nr proc_sr; proc_bsr_nr proc_bsr; mux_nr mux; + demux_nr demux; - // UL HARQ + // DL/UL HARQ + dl_harq_entity_nr_vector dl_harq = {}; ul_harq_entity_nr_vector ul_harq = {}; - ul_harq_cfg_t ul_harq_cfg; const uint8_t PCELL_CC_IDX = 0; }; diff --git a/srsue/hdr/stack/mac_nr/mac_nr_interfaces.h b/srsue/hdr/stack/mac_nr/mac_nr_interfaces.h index 2370eb96e..0e265beab 100644 --- a/srsue/hdr/stack/mac_nr/mac_nr_interfaces.h +++ b/srsue/hdr/stack/mac_nr/mac_nr_interfaces.h @@ -77,6 +77,16 @@ public: virtual uint16_t get_csrnti() = 0; }; +/** + * @brief Interface from HARQ class to demux class + */ +class demux_interface_harq_nr +{ +public: + /// Inform demux unit about a newly decoded TB. + virtual void push_pdu(srsran::unique_byte_buffer_t pdu, uint32_t tti) = 0; +}; + } // namespace srsue #endif // SRSUE_MAC_NR_INTERFACES_H \ No newline at end of file diff --git a/srsue/hdr/stack/mac_nr/proc_ra_nr.h b/srsue/hdr/stack/mac_nr/proc_ra_nr.h index ce684868f..cdef546c2 100644 --- a/srsue/hdr/stack/mac_nr/proc_ra_nr.h +++ b/srsue/hdr/stack/mac_nr/proc_ra_nr.h @@ -43,7 +43,7 @@ public: // PHY interfaces void prach_sent(uint32_t tti, uint32_t s_id, uint32_t t_id, uint32_t f_id, uint32_t ul_carrier_id); - void handle_rar_pdu(mac_interface_phy_nr::mac_nr_grant_dl_t& grant); + void handle_rar_pdu(mac_interface_phy_nr::tb_action_dl_result_t& grant); void pdcch_to_crnti(); void start_by_rrc(); @@ -104,7 +104,7 @@ private: void ra_procedure_initialization(); void ra_resource_selection(); void ra_preamble_transmission(); - void ra_response_reception(const mac_interface_phy_nr::mac_nr_grant_dl_t& grant); + void ra_response_reception(const mac_interface_phy_nr::tb_action_dl_result_t& tb); void ra_contention_resolution(); void ra_contention_resolution(uint64_t rx_contention_id); void ra_completion(); diff --git a/srsue/hdr/stack/ue_stack_lte.h b/srsue/hdr/stack/ue_stack_lte.h index f365b296a..e83c9f9b9 100644 --- a/srsue/hdr/stack/ue_stack_lte.h +++ b/srsue/hdr/stack/ue_stack_lte.h @@ -96,7 +96,7 @@ public: mac.new_grant_ul(cc_idx, grant, action); } - void new_grant_dl(uint32_t cc_idx, mac_grant_dl_t grant, tb_action_dl_t* action) final + void new_grant_dl(uint32_t cc_idx, mac_grant_dl_t grant, mac_interface_phy_lte::tb_action_dl_t* action) final { mac.new_grant_dl(cc_idx, grant, action); } @@ -113,7 +113,7 @@ public: void mch_decoded(uint32_t len, bool crc) final { mac.mch_decoded(len, crc); } - void new_mch_dl(const srsran_pdsch_grant_t& phy_grant, tb_action_dl_t* action) final + void new_mch_dl(const srsran_pdsch_grant_t& phy_grant, mac_interface_phy_lte::tb_action_dl_t* action) final { mac.new_mch_dl(phy_grant, action); } @@ -124,8 +124,18 @@ public: // MAC Interface for NR PHY int sf_indication(const uint32_t tti) final { return SRSRAN_SUCCESS; } - void tb_decoded(const uint32_t cc_idx, mac_nr_grant_dl_t& grant) final { mac_nr.tb_decoded(cc_idx, grant); } - + void tb_decoded(const uint32_t cc_idx, + const mac_nr_grant_dl_t& grant, + mac_interface_phy_nr::tb_action_dl_result_t result) final + { + mac_nr.tb_decoded(cc_idx, grant, std::move(result)); + } + void new_grant_dl(const uint32_t cc_idx, + const mac_nr_grant_dl_t& grant, + mac_interface_phy_nr::tb_action_dl_t* action) final + { + mac_nr.new_grant_dl(cc_idx, grant, action); + } void new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant, mac_interface_phy_nr::tb_action_ul_t* action) final diff --git a/srsue/hdr/stack/ue_stack_nr.h b/srsue/hdr/stack/ue_stack_nr.h index 674c06469..661cfc373 100644 --- a/srsue/hdr/stack/ue_stack_nr.h +++ b/srsue/hdr/stack/ue_stack_nr.h @@ -80,7 +80,14 @@ public: run_tti(tti); return SRSRAN_SUCCESS; } - void tb_decoded(const uint32_t cc_idx, mac_nr_grant_dl_t& grant) final { mac->tb_decoded(cc_idx, grant); } + void tb_decoded(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_result_t result) final + { + mac->tb_decoded(cc_idx, grant, std::move(result)); + } + void new_grant_dl(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_t* action) final + { + mac->new_grant_dl(cc_idx, grant, action); + } void new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant, tb_action_ul_t* action) final { mac->new_grant_ul(cc_idx, grant, action); diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index 7b80e54da..95aaad815 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -38,19 +38,12 @@ cc_worker::cc_worker(uint32_t cc_idx_, srslog::basic_logger& log, state* phy_sta ERROR("Error initiating UE DL NR"); return; } - - if (srsran_softbuffer_rx_init_guru(&softbuffer_rx, SRSRAN_SCH_NR_MAX_NOF_CB_LDPC, SRSRAN_LDPC_MAX_LEN_ENCODED_CB) < - SRSRAN_SUCCESS) { - ERROR("Error init soft-buffer"); - return; - } } cc_worker::~cc_worker() { srsran_ue_dl_nr_free(&ue_dl); srsran_ue_ul_nr_free(&ue_ul); - srsran_softbuffer_rx_free(&softbuffer_rx); for (cf_t* p : rx_buffer) { if (p != nullptr) { free(p); @@ -240,6 +233,23 @@ bool cc_worker::work_dl() return true; } + // Notify MAC about PDSCH grant + mac_interface_phy_nr::tb_action_dl_t dl_action = {}; + mac_interface_phy_nr::mac_nr_grant_dl_t mac_dl_grant = {}; + mac_dl_grant.rnti = pdsch_cfg.grant.rnti; + mac_dl_grant.pid = pdsch_cfg.grant.tb[0].pid; + mac_dl_grant.rv = pdsch_cfg.grant.tb[0].rv; + mac_dl_grant.ndi = pdsch_cfg.grant.tb[0].ndi; + mac_dl_grant.tbs = pdsch_cfg.grant.tb[0].tbs / 8; + mac_dl_grant.tti = dl_slot_cfg.idx; + phy->stack->new_grant_dl(0, mac_dl_grant, &dl_action); + + // Early stop if MAC says it doesn't need the TB + if (not dl_action.tb.enabled) { + logger.info("Decoding not required. Skipping PDSCH"); + return true; + } + // Get data buffer srsran::unique_byte_buffer_t data = srsran::make_byte_buffer(); if (data == nullptr) { @@ -248,14 +258,10 @@ bool cc_worker::work_dl() } data->N_bytes = pdsch_cfg.grant.tb[0].tbs / 8U; - // Get soft-buffer from MAC - // ... - srsran_softbuffer_rx_reset(&softbuffer_rx); - // Initialise PDSCH Result srsran_pdsch_res_nr_t pdsch_res = {}; pdsch_res.tb[0].payload = data->msg; - pdsch_cfg.grant.tb[0].softbuffer.rx = &softbuffer_rx; + pdsch_cfg.grant.tb[0].softbuffer.rx = dl_action.tb.softbuffer; // Decode actual PDSCH transmission if (srsran_ue_dl_nr_decode_pdsch(&ue_dl, &dl_slot_cfg, &pdsch_cfg, &pdsch_res) < SRSRAN_SUCCESS) { @@ -276,21 +282,16 @@ bool cc_worker::work_dl() } // Notify MAC about PDSCH decoding result - if (pdsch_res.tb[0].crc) { - // Prepare grant - mac_interface_phy_nr::mac_nr_grant_dl_t mac_nr_grant = {}; - mac_nr_grant.tb[0] = std::move(data); - mac_nr_grant.pid = pid; - mac_nr_grant.rnti = pdsch_cfg.grant.rnti; - mac_nr_grant.tti = dl_slot_cfg.idx; - - if (pdsch_cfg.grant.rnti_type == srsran_rnti_type_ra) { - phy->rar_grant_tti = dl_slot_cfg.idx; - } + mac_interface_phy_nr::tb_action_dl_result_t mac_dl_result = {}; + mac_dl_result.ack = pdsch_res.tb[0].crc; + mac_dl_result.payload = mac_dl_result.ack ? std::move(data) : nullptr; // only pass data when successful + phy->stack->tb_decoded(cc_idx, mac_dl_grant, std::move(mac_dl_result)); - // Send data to MAC - phy->stack->tb_decoded(cc_idx, mac_nr_grant); + if (pdsch_cfg.grant.rnti_type == srsran_rnti_type_ra) { + phy->rar_grant_tti = dl_slot_cfg.idx; + } + if (pdsch_res.tb[0].crc) { // Generate DL metrics dl_metrics_t dl_m = {}; dl_m.mcs = pdsch_cfg.grant.tb[0].mcs; diff --git a/srsue/src/stack/mac_nr/CMakeLists.txt b/srsue/src/stack/mac_nr/CMakeLists.txt index 9553e6fbd..6c186bd52 100644 --- a/srsue/src/stack/mac_nr/CMakeLists.txt +++ b/srsue/src/stack/mac_nr/CMakeLists.txt @@ -6,8 +6,15 @@ # the distribution. # -set(SOURCES mac_nr.cc proc_ra_nr.cc proc_bsr_nr.cc proc_sr_nr.cc mux_nr.cc ul_harq_nr.cc) +set(SOURCES mac_nr.cc + proc_ra_nr.cc + proc_bsr_nr.cc + proc_sr_nr.cc + mux_nr.cc + demux_nr.cc + dl_harq_nr.cc + ul_harq_nr.cc) add_library(srsue_mac_nr STATIC ${SOURCES}) target_link_libraries(srsue_mac_nr srsue_mac_common srsran_mac) -add_subdirectory(test) \ No newline at end of file +add_subdirectory(test) diff --git a/srsue/src/stack/mac_nr/demux_nr.cc b/srsue/src/stack/mac_nr/demux_nr.cc new file mode 100644 index 000000000..dce9c4e87 --- /dev/null +++ b/srsue/src/stack/mac_nr/demux_nr.cc @@ -0,0 +1,81 @@ +/** + * + * \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/mac_nr/demux_nr.h" +#include "srsran/common/buffer_pool.h" +#include "srsran/interfaces/ue_rlc_interfaces.h" + +namespace srsue { + +demux_nr::demux_nr(srslog::basic_logger& logger_) : logger(logger_) {} + +demux_nr::~demux_nr() {} + +int32_t demux_nr::init(rlc_interface_mac* rlc_) +{ + rlc = rlc_; + return SRSRAN_SUCCESS; +} + +// Enqueues PDU and returns quickly +void demux_nr::push_pdu(srsran::unique_byte_buffer_t pdu, uint32_t tti) +{ + pdu_queue.push(std::move(pdu)); +} + +void demux_nr::process_pdus() +{ + while (not pdu_queue.empty()) { + srsran::unique_byte_buffer_t pdu = pdu_queue.wait_pop(); + handle_pdu(std::move(pdu)); + } +} + +/// Handling of DLSCH PDUs only +void demux_nr::handle_pdu(srsran::unique_byte_buffer_t pdu) +{ + logger.info(pdu->msg, pdu->N_bytes, "Handling MAC PDU (%d B)", pdu->N_bytes); + + rx_pdu.init_rx(); + if (rx_pdu.unpack(pdu->msg, pdu->N_bytes) != SRSRAN_SUCCESS) { + return; + } + + for (uint32_t i = 0; i < rx_pdu.get_num_subpdus(); ++i) { + srsran::mac_sch_subpdu_nr subpdu = rx_pdu.get_subpdu(i); + logger.info("Handling subPDU %d/%d: rnti=0x%x lcid=%d, sdu_len=%d", + i + 1, + rx_pdu.get_num_subpdus(), + subpdu.get_c_rnti(), + subpdu.get_lcid(), + subpdu.get_sdu_length()); + + // Handle Timing Advance CE + switch (subpdu.get_lcid()) { + case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::DRX_CMD: + logger.info("DRX CE not implemented."); + break; + case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::TA_CMD: + logger.info("Timing Advance CE not implemented."); + break; + case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::CON_RES_ID: + logger.info("Contention Resolution CE not implemented."); + break; + default: + if (subpdu.is_sdu()) { + rlc->write_pdu(subpdu.get_lcid(), subpdu.get_sdu(), subpdu.get_sdu_length()); + } + } + } +} + +} // namespace srsue diff --git a/srsue/src/stack/mac_nr/dl_harq_nr.cc b/srsue/src/stack/mac_nr/dl_harq_nr.cc new file mode 100644 index 000000000..c0466aaea --- /dev/null +++ b/srsue/src/stack/mac_nr/dl_harq_nr.cc @@ -0,0 +1,243 @@ +/** + * + * \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/mac_nr/dl_harq_nr.h" +#include "srsran/common/mac_pcap.h" +#include "srsran/common/rwlock_guard.h" +#include "srsran/srslog/logger.h" +#include "srsue/hdr/stack/mac_nr/demux_nr.h" + +namespace srsue { + +dl_harq_entity_nr::dl_harq_entity_nr(uint8_t cc_idx_, + mac_interface_harq_nr* mac_, + demux_interface_harq_nr* demux_unit_) : + logger(srslog::fetch_basic_logger("MAC-NR")), cc_idx(cc_idx_), mac(mac_), demux_unit(demux_unit_), bcch_proc(this) +{ + // Init broadcast HARQ process + bcch_proc.init(-1); + pthread_rwlock_init(&rwlock, NULL); +} + +dl_harq_entity_nr::~dl_harq_entity_nr() +{ + pthread_rwlock_destroy(&rwlock); +} + +// Called from Stack thread through MAC (TODO: add shared::mutex) +int32_t dl_harq_entity_nr::set_config(const srsran::dl_harq_cfg_nr_t& cfg_) +{ + srsran::rwlock_write_guard lock(rwlock); + if (cfg_.nof_procs < 1 || cfg_.nof_procs > SRSRAN_MAX_HARQ_PROC_DL_NR) { + logger.error("Invalid configuration: %d HARQ processes not supported", cfg_.nof_procs); + return SRSRAN_ERROR; + } + + // clear old processees + for (auto& proc : harq_procs) { + proc = nullptr; + } + + // Allocate and init configured HARQ processes + for (uint32_t i = 0; i < cfg.nof_procs; i++) { + harq_procs[i] = std::unique_ptr(new dl_harq_process_nr(this)); + if (!harq_procs.at(i)->init(i)) { + logger.error("Error while initializing DL-HARQ process %d", i); + return SRSRAN_ERROR; + } + } + + cfg = cfg_; + + logger.debug("cc_idx=%d, set number of HARQ processes for DL to %d", cc_idx, cfg.nof_procs); + + return SRSRAN_SUCCESS; +} + +// Called from PHY workers +void dl_harq_entity_nr::new_grant_dl(const mac_nr_grant_dl_t& grant, mac_interface_phy_nr::tb_action_dl_t* action) +{ + srsran::rwlock_read_guard lock(rwlock); + + *action = {}; + + // Fetch HARQ process + dl_harq_process_nr* proc_ptr = nullptr; + if (grant.rnti == SRSRAN_SIRNTI) { + // Set BCCH PID for SI RNTI + proc_ptr = &bcch_proc; + } else { + if (grant.pid >= cfg.nof_procs) { + logger.error("Invalid PID: %d", grant.pid); + return; + } + proc_ptr = harq_procs.at(grant.pid).get(); + } + + // Check NDI toggled state before forwarding to process + bool ndi_toggled = (grant.ndi != harq_procs.at(grant.pid)->get_ndi()); + + if (grant.rnti == mac->get_temp_crnti() && last_temporal_crnti != mac->get_temp_crnti()) { + // Consider the NDI to have been toggled + last_temporal_crnti = mac->get_temp_crnti(); + logger.info("Considering NDI in pid=%d to be toggled for first Temporal C-RNTI", grant.pid); + ndi_toggled = true; + } + + proc_ptr->new_grant_dl(std::move(grant), ndi_toggled, action); +} + +/// Called from PHY workers +void dl_harq_entity_nr::tb_decoded(const mac_nr_grant_dl_t& grant, mac_interface_phy_nr::tb_action_dl_result_t result) +{ + srsran::rwlock_read_guard lock(rwlock); + + if (grant.rnti == SRSRAN_SIRNTI) { + bcch_proc.tb_decoded(grant, std::move(result)); + } else { + if (grant.pid >= cfg.nof_procs) { + logger.error("Invalid PID: %d", grant.pid); + return; + } + harq_procs.at(grant.pid)->tb_decoded(grant, std::move(result)); + } +} + +/// Called from MAC (Stack thread after, e.g. time alignment expire) +void dl_harq_entity_nr::reset() +{ + srsran::rwlock_write_guard lock(rwlock); + for (const auto& proc : harq_procs) { + if (proc != nullptr) { + proc->reset(); + } + } + bcch_proc.reset(); +} + +float dl_harq_entity_nr::get_average_retx() +{ + return average_retx; +} + +dl_harq_entity_nr::dl_harq_process_nr::dl_harq_process_nr(dl_harq_entity_nr* parent_) : + harq_entity(parent_), + softbuffer_rx(std::unique_ptr(new srsran_softbuffer_rx_t())), + logger(srslog::fetch_basic_logger("MAC-NR")) +{} + +dl_harq_entity_nr::dl_harq_process_nr::~dl_harq_process_nr() +{ + if (softbuffer_rx != nullptr) { + srsran_softbuffer_rx_free(softbuffer_rx.get()); + } +} + +bool dl_harq_entity_nr::dl_harq_process_nr::init(int pid_) +{ + if (softbuffer_rx == nullptr || srsran_softbuffer_rx_init_guru(softbuffer_rx.get(), + SRSRAN_SCH_NR_MAX_NOF_CB_LDPC, + SRSRAN_LDPC_MAX_LEN_ENCODED_CB) != SRSRAN_SUCCESS) { + logger.error("Couldn't allocate and/or initialize softbuffer"); + return false; + } + + if (pid_ < 0) { + is_bcch = true; + pid = 0; + } else { + pid = (uint32_t)pid_; + is_bcch = false; + } + + return true; +} + +void dl_harq_entity_nr::dl_harq_process_nr::reset(void) +{ + current_grant = {}; + is_first_tb = true; + n_retx = 0; +} + +uint8_t dl_harq_entity_nr::dl_harq_process_nr::get_ndi() +{ + return current_grant.ndi; +} + +void dl_harq_entity_nr::dl_harq_process_nr::new_grant_dl(const mac_nr_grant_dl_t& grant, + const bool& ndi_toggled, + mac_interface_phy_nr::tb_action_dl_t* action) +{ + // Determine if it's a new transmission 5.3.2.2 + if (ndi_toggled || // 1st condition (NDI has changed) + (is_bcch && grant.rv == 0) || // 2nd condition (Broadcast and 1st transmission) + is_first_tb) // 3rd condition (is first tx for this tb) + { + // New transmission + n_retx = 0; + srsran_softbuffer_rx_reset_tbs(softbuffer_rx.get(), grant.tbs * 8); + + action->tb.enabled = true; + action->tb.softbuffer = softbuffer_rx.get(); + + // reset conditions + is_first_tb = false; + } else { + // This is a retransmission + if (not acked) { + // If data has not yet been successfully decoded, instruct the PHY to combine the received data + action->tb.enabled = true; + action->tb.softbuffer = softbuffer_rx.get(); + } else { + logger.info("DL %d: Received duplicate. Discarding and retransmitting ACK (n_retx=%d)", pid, n_retx); + } + } + + // increment counter and store grant + n_retx++; + current_grant = grant; +} + +void dl_harq_entity_nr::dl_harq_process_nr::tb_decoded(const mac_nr_grant_dl_t& grant, + mac_interface_phy_nr::tb_action_dl_result_t result) +{ + acked = result.ack; + + if (acked and result.payload != nullptr) { + if (is_bcch) { + logger.warning("Delivering PDU=%d bytes to Dissassemble and Demux unit (BCCH) not implemented", grant.tbs); + reset(); + } else { + if (grant.rnti == harq_entity->mac->get_temp_crnti()) { + logger.debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (Temporal C-RNTI) not implemented", + grant.tbs); + } else { + logger.debug("Delivering PDU=%d bytes to Dissassemble and Demux unit", grant.tbs); + harq_entity->demux_unit->push_pdu(std::move(result.payload), grant.tti); + + // Compute average number of retransmissions per packet + harq_entity->average_retx = SRSRAN_VEC_CMA((float)n_retx, harq_entity->average_retx, harq_entity->nof_pkts++); + } + } + } + + logger.info("DL %d: %s tbs=%d, rv=%d, ack=%s, ndi=%d", + pid, + grant.rv == 0 ? "newTX" : "reTX ", + grant.tbs, + grant.rv, + acked ? "OK" : "KO", + grant.ndi); +} + +} // namespace srsue diff --git a/srsue/src/stack/mac_nr/mac_nr.cc b/srsue/src/stack/mac_nr/mac_nr.cc index e15d1d978..0c4f10778 100644 --- a/srsue/src/stack/mac_nr/mac_nr.cc +++ b/srsue/src/stack/mac_nr/mac_nr.cc @@ -24,9 +24,11 @@ mac_nr::mac_nr(srsran::ext_task_sched_handle task_sched_) : proc_sr(logger), proc_bsr(logger), mux(*this, logger), + demux(logger), pcap(nullptr) { // Create PCell HARQ entities + dl_harq.at(PCELL_CC_IDX) = dl_harq_entity_nr_ptr(new dl_harq_entity_nr(PCELL_CC_IDX, this, &demux)); ul_harq.at(PCELL_CC_IDX) = ul_harq_entity_nr_ptr(new ul_harq_entity_nr(PCELL_CC_IDX, this, &proc_ra, &mux)); } @@ -62,12 +64,25 @@ int mac_nr::init(const mac_nr_args_t& args_, return SRSRAN_ERROR; } + if (demux.init(rlc) != SRSRAN_SUCCESS) { + logger.error("Couldn't initialize demux unit."); + return SRSRAN_ERROR; + } + // Configure PCell HARQ entities if (ul_harq.at(PCELL_CC_IDX)->init() != SRSRAN_SUCCESS) { logger.error("Couldn't initialize UL HARQ entity."); return SRSRAN_ERROR; } + // Set default config until RRC + dl_harq_cfg_nr_t harq_cfg = {}; + harq_cfg.reset(); + if (dl_harq.at(PCELL_CC_IDX)->set_config(harq_cfg) != SRSRAN_SUCCESS) { + logger.error("Couldn't configure DL HARQ entity."); + return SRSRAN_ERROR; + } + started = true; return SRSRAN_SUCCESS; @@ -98,6 +113,8 @@ void mac_nr::run_tti(const uint32_t tti) return; } + logger.set_context(tti); + // Step all procedures logger.debug("Running MAC tti=%d", tti); @@ -106,6 +123,9 @@ void mac_nr::run_tti(const uint32_t tti) proc_bsr.step(tti, mac_buffer_states); proc_sr.step(tti); + + // process received PDUs + stack_task_dispatch_queue.push([this]() { process_pdus(); }); } void mac_nr::update_buffer_states() @@ -228,49 +248,80 @@ bool mac_nr::sr_opportunity(uint32_t tti, uint32_t sr_id, bool meas_gap, bool ul } // This function handles all PCAP writing for a decoded DL TB -void mac_nr::write_pcap(const uint32_t cc_idx, mac_nr_grant_dl_t& grant) +void mac_nr::write_pcap(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_result_t& tb) { if (pcap) { - for (uint32_t i = 0; i < SRSRAN_MAX_CODEWORDS; ++i) { - if (grant.tb[i] != nullptr) { - if (proc_ra.has_rar_rnti() && grant.rnti == proc_ra.get_rar_rnti()) { - pcap->write_dl_ra_rnti_nr(grant.tb[i]->msg, grant.tb[i]->N_bytes, grant.rnti, true, grant.tti); - } else if (grant.rnti == SRSRAN_PRNTI) { - pcap->write_dl_pch_nr(grant.tb[i]->msg, grant.tb[i]->N_bytes, grant.rnti, true, grant.tti); - } else { - pcap->write_dl_crnti_nr(grant.tb[i]->msg, grant.tb[i]->N_bytes, grant.rnti, true, grant.tti); - } + if (tb.ack && tb.payload != nullptr) { + if (proc_ra.has_rar_rnti() && grant.rnti == proc_ra.get_rar_rnti()) { + pcap->write_dl_ra_rnti_nr(tb.payload->msg, tb.payload->N_bytes, grant.rnti, true, grant.tti); + } else if (grant.rnti == SRSRAN_PRNTI) { + pcap->write_dl_pch_nr(tb.payload->msg, tb.payload->N_bytes, grant.rnti, true, grant.tti); + } else { + pcap->write_dl_crnti_nr(tb.payload->msg, tb.payload->N_bytes, grant.rnti, true, grant.tti); } } } } /** - * \brief Called from PHY after decoding a TB - * - * The TB can directly be used + * \brief Called from PHY after decoding PDCCH for DL reception * - * @param cc_idx - * @param grant structure + * @param cc_idx The CC index + * @param grant The DL grant + * @param action The DL action to be filled by MAC */ -void mac_nr::tb_decoded(const uint32_t cc_idx, mac_nr_grant_dl_t& grant) +void mac_nr::new_grant_dl(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_t* action) +{ + logger.debug("new_grant_dl(): cc_idx=%d, tti=%d, rnti=%d, pid=%d, tbs=%d, ndi=%d, rv=%d", + cc_idx, + grant.tti, + grant.rnti, + grant.pid, + grant.tbs, + grant.ndi, + grant.rv); + + // Assert HARQ entity + if (dl_harq.at(cc_idx) == nullptr) { + logger.error("HARQ entity %d has not been created", cc_idx); + return; + } + + dl_harq.at(cc_idx)->new_grant_dl(grant, action); +} + +void mac_nr::tb_decoded(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_result_t result) { - write_pcap(cc_idx, grant); - // handle PDU + logger.debug("tb_decoded(): cc_idx=%d, tti=%d, rnti=%d, pid=%d, tbs=%d, ndi=%d, rv=%d, result=%s", + cc_idx, + grant.tti, + grant.rnti, + grant.pid, + grant.tbs, + grant.ndi, + grant.rv, + result.ack ? "OK" : "KO"); + + write_pcap(cc_idx, grant, result); + if (proc_ra.has_rar_rnti() && grant.rnti == proc_ra.get_rar_rnti()) { - proc_ra.handle_rar_pdu(grant); + proc_ra.handle_rar_pdu(result); } else { - // Push DL PDUs to queue for background processing - for (uint32_t i = 0; i < SRSRAN_MAX_CODEWORDS; ++i) { - if (grant.tb[i] != nullptr) { - metrics[cc_idx].rx_pkts++; - metrics[cc_idx].rx_brate += grant.tb[i]->N_bytes * 8; - pdu_queue.push(std::move(grant.tb[i])); - } + // Assert HARQ entity + if (dl_harq.at(cc_idx) == nullptr) { + logger.error("HARQ entity %d has not been created", cc_idx); + return; } + + dl_harq.at(cc_idx)->tb_decoded(grant, std::move(result)); } - stack_task_dispatch_queue.push([this]() { process_pdus(); }); + // do metrics + metrics[cc_idx].rx_brate += grant.tbs * 8; + metrics[cc_idx].rx_pkts++; + if (not result.ack) { + metrics[cc_idx].rx_errors++; + } } void mac_nr::new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant, tb_action_ul_t* action) @@ -395,7 +446,7 @@ bool mac_nr::set_crnti(const uint16_t c_rnti_) void mac_nr::start_ra_procedure() { - stack_task_dispatch_queue.push([this]() {proc_ra.start_by_rrc();}); + stack_task_dispatch_queue.push([this]() { proc_ra.start_by_rrc(); }); } bool mac_nr::is_valid_crnti(const uint16_t crnti) @@ -435,48 +486,7 @@ void mac_nr::get_metrics(mac_metrics_t m[SRSRAN_MAX_CARRIERS]) */ void mac_nr::process_pdus() { - while (started and not pdu_queue.empty()) { - srsran::unique_byte_buffer_t pdu = pdu_queue.wait_pop(); - // TODO: delegate to demux class - handle_pdu(std::move(pdu)); - } -} - -void mac_nr::handle_pdu(srsran::unique_byte_buffer_t pdu) -{ - logger.info(pdu->msg, pdu->N_bytes, "Handling MAC PDU (%d B)", pdu->N_bytes); - - rx_pdu.init_rx(); - if (rx_pdu.unpack(pdu->msg, pdu->N_bytes) != SRSRAN_SUCCESS) { - return; - } - - for (uint32_t i = 0; i < rx_pdu.get_num_subpdus(); ++i) { - srsran::mac_sch_subpdu_nr subpdu = rx_pdu.get_subpdu(i); - logger.info("Handling subPDU %d/%d: rnti=0x%x lcid=%d, sdu_len=%d", - i + 1, - rx_pdu.get_num_subpdus(), - subpdu.get_c_rnti(), - subpdu.get_lcid(), - subpdu.get_sdu_length()); - - // Handle Timing Advance CE - switch (subpdu.get_lcid()) { - case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::DRX_CMD: - logger.info("DRX CE not implemented."); - break; - case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::TA_CMD: - logger.info("Timing Advance CE not implemented."); - break; - case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::CON_RES_ID: - logger.info("Contention Resolution CE not implemented."); - break; - default: - if (subpdu.is_sdu()) { - rlc->write_pdu(subpdu.get_lcid(), subpdu.get_sdu(), subpdu.get_sdu_length()); - } - } - } + demux.process_pdus(); } uint64_t mac_nr::get_contention_id() diff --git a/srsue/src/stack/mac_nr/proc_ra_nr.cc b/srsue/src/stack/mac_nr/proc_ra_nr.cc index 9a39d3c76..0a94bf0b7 100644 --- a/srsue/src/stack/mac_nr/proc_ra_nr.cc +++ b/srsue/src/stack/mac_nr/proc_ra_nr.cc @@ -178,7 +178,7 @@ void proc_ra_nr::ra_preamble_transmission() } // 5.1.4 Random Access Preamble transmission -void proc_ra_nr::ra_response_reception(const mac_interface_phy_nr::mac_nr_grant_dl_t& grant) +void proc_ra_nr::ra_response_reception(const mac_interface_phy_nr::tb_action_dl_result_t& tb) { if (state != WAITING_FOR_RESPONSE_RECEPTION) { logger.warning( @@ -190,34 +190,32 @@ void proc_ra_nr::ra_response_reception(const mac_interface_phy_nr::mac_nr_grant_ // Stop rar timer rar_timeout_timer.stop(); - for (uint32_t i = 0; i < SRSRAN_MAX_CODEWORDS; ++i) { - if (grant.tb[i] != nullptr) { - srsran::mac_rar_pdu_nr pdu; - if (!pdu.unpack(grant.tb[i]->msg, grant.tb[i]->N_bytes)) { - logger.warning("Error unpacking RAR PDU (%d)", i); - return; - } - logger.info("%s", pdu.to_string()); - - for (auto& subpdu : pdu.get_subpdus()) { - if (subpdu.has_rapid() && subpdu.get_rapid() == preamble_index) { - logger.debug("PROC RA NR: Setting UL grant and prepare Msg3"); - temp_crnti = subpdu.get_temp_crnti(); - - // Set Temporary-C-RNTI if provided, otherwise C-RNTI is ok - phy->set_ul_grant(subpdu.get_ul_grant(), temp_crnti, srsran_rnti_type_ra); - - // reset all parameters that are used before rar - rar_rnti = SRSRAN_INVALID_RNTI; - mac.msg3_prepare(); - current_ta = subpdu.get_ta(); - - // Set Backoff parameter - if (subpdu.has_backoff()) { - preamble_backoff = backoff_table_nr[subpdu.get_backoff() % 16]; // TODO multiplied with SCALING_FACTOR_BI. - } else { - preamble_backoff = 0; - } + if (tb.ack && tb.payload != nullptr) { + srsran::mac_rar_pdu_nr pdu; + if (!pdu.unpack(tb.payload->msg, tb.payload->N_bytes)) { + logger.warning("Error unpacking RAR PDU"); + return; + } + logger.info("%s", pdu.to_string()); + + for (auto& subpdu : pdu.get_subpdus()) { + if (subpdu.has_rapid() && subpdu.get_rapid() == preamble_index) { + logger.debug("PROC RA NR: Setting UL grant and prepare Msg3"); + temp_crnti = subpdu.get_temp_crnti(); + + // Set Temporary-C-RNTI if provided, otherwise C-RNTI is ok + phy->set_ul_grant(subpdu.get_ul_grant(), temp_crnti, srsran_rnti_type_ra); + + // reset all parameters that are used before rar + rar_rnti = SRSRAN_INVALID_RNTI; + mac.msg3_prepare(); + current_ta = subpdu.get_ta(); + + // Set Backoff parameter + if (subpdu.has_backoff()) { + preamble_backoff = backoff_table_nr[subpdu.get_backoff() % 16]; // TODO multiplied with SCALING_FACTOR_BI. + } else { + preamble_backoff = 0; } } } @@ -345,11 +343,13 @@ void proc_ra_nr::prach_sent(uint32_t tti, uint32_t s_id, uint32_t t_id, uint32_t } // Called by PHY thread through MAC parent -void proc_ra_nr::handle_rar_pdu(mac_interface_phy_nr::mac_nr_grant_dl_t& grant) +void proc_ra_nr::handle_rar_pdu(mac_interface_phy_nr::tb_action_dl_result_t& result) { // Defer the handling of the grant to main stack thread in ra_response_reception - auto task_handler = [this](const mac_interface_phy_nr::mac_nr_grant_dl_t& t) { ra_response_reception(std::move(t)); }; - task_queue.push(std::bind(task_handler, std::move(grant))); + auto task_handler = [this](const mac_interface_phy_nr::tb_action_dl_result_t& t) { + ra_response_reception(std::move(t)); + }; + task_queue.push(std::bind(task_handler, std::move(result))); } // Called from PHY thread, defer actions therefore. diff --git a/srsue/src/stack/mac_nr/test/proc_ra_nr_test.cc b/srsue/src/stack/mac_nr/test/proc_ra_nr_test.cc index 3d9bc0e6d..4867c6edb 100644 --- a/srsue/src/stack/mac_nr/test/proc_ra_nr_test.cc +++ b/srsue/src/stack/mac_nr/test/proc_ra_nr_test.cc @@ -72,7 +72,7 @@ public: void rrc_ra_problem() { logger.warning("Dummy MAC RRC ra problem"); } private: - uint16_t crnti = SRSRAN_INVALID_RNTI; + uint16_t crnti = SRSRAN_INVALID_RNTI; srslog::basic_logger& logger; }; @@ -124,12 +124,13 @@ int proc_ra_normal_test() mac_interface_phy_nr::mac_nr_grant_dl_t grant; grant.rnti = 0x16; grant.tti = rach_cfg.ra_responseWindow + tti_start + 3; - grant.pid = 0x0123; + grant.pid = 0x0; uint8_t mac_dl_rar_pdu[] = {0x40, 0x06, 0x68, 0x03, 0x21, 0x46, 0x46, 0x02, 0x00, 0x00, 0x00}; - grant.tb[0] = srsran::make_byte_buffer(); - TESTASSERT(grant.tb[0] != nullptr); - grant.tb[0].get()->append_bytes(mac_dl_rar_pdu, sizeof(mac_dl_rar_pdu)); - proc_ra_nr.handle_rar_pdu(grant); + mac_interface_phy_nr::tb_action_dl_result_t result = {}; + result.payload = srsran::make_byte_buffer(); + TESTASSERT(result.payload != nullptr); + result.payload.get()->append_bytes(mac_dl_rar_pdu, sizeof(mac_dl_rar_pdu)); + proc_ra_nr.handle_rar_pdu(result); task_sched.tic(); task_sched.run_pending_tasks(); diff --git a/srsue/src/stack/ue_stack_lte.cc b/srsue/src/stack/ue_stack_lte.cc index 0d7eeee8f..5a92b142e 100644 --- a/srsue/src/stack/ue_stack_lte.cc +++ b/srsue/src/stack/ue_stack_lte.cc @@ -34,7 +34,7 @@ ue_stack_lte::ue_stack_lte() : rrc_logger(srslog::fetch_basic_logger("RRC", false)), usim_logger(srslog::fetch_basic_logger("USIM", false)), nas_logger(srslog::fetch_basic_logger("NAS", false)), - mac_nr_logger(srslog::fetch_basic_logger("MAC-NR", false)), + mac_nr_logger(srslog::fetch_basic_logger("MAC-NR")), rrc_nr_logger(srslog::fetch_basic_logger("RRC-NR", false)), mac_pcap(), mac_nr_pcap(),