diff --git a/lib/include/srsran/interfaces/gnb_interfaces.h b/lib/include/srsran/interfaces/gnb_interfaces.h index 3042a5c7c..5faf4945b 100644 --- a/lib/include/srsran/interfaces/gnb_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_interfaces.h @@ -27,23 +27,6 @@ namespace srsenb { -/***************************** - * MAC INTERFACES - ****************************/ -class mac_interface_rrc_nr -{ -public: - // Provides cell configuration including SIB periodicity, etc. - virtual int cell_cfg(srsenb::sched_interface::cell_cfg_t* cell_cfg) = 0; - - /// Allocates a new user/RNTI at MAC. Returns RNTI on success or SRSRAN_INVALID_RNTI otherwise. - virtual uint16_t reserve_rnti() = 0; -}; - -// NR interface is identical to EUTRA interface -class mac_interface_rlc_nr : public mac_interface_rlc -{}; - /***************************** * RLC INTERFACES ****************************/ @@ -164,8 +147,7 @@ public: // NR interface identical to EUTRA version class rrc_interface_pdcp_nr : public rrc_interface_pdcp -{ -}; +{}; class phy_interface_rrc_nr { @@ -295,7 +277,7 @@ public: virtual int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) = 0; virtual int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) = 0; virtual int pucch_info(const srsran_slot_cfg_t& slot_cfg, const pucch_info_t& pucch_info) = 0; - virtual int pusch_info(const srsran_slot_cfg_t& slot_cfg, pusch_info_t& pusch_info) = 0; + virtual int pusch_info(const srsran_slot_cfg_t& slot_cfg, pusch_info_t& pusch_info) = 0; virtual void rach_detected(const rach_info_t& rach_info) = 0; }; diff --git a/lib/include/srsran/interfaces/gnb_mac_interfaces.h b/lib/include/srsran/interfaces/gnb_mac_interfaces.h new file mode 100644 index 000000000..c0f633fb6 --- /dev/null +++ b/lib/include/srsran/interfaces/gnb_mac_interfaces.h @@ -0,0 +1,39 @@ +/** + * + * \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 SRSRAN_GNB_MAC_INTERFACES_H +#define SRSRAN_GNB_MAC_INTERFACES_H + +#include "srsenb/hdr/stack/mac/nr/sched_nr_interface.h" + +namespace srsenb { + +class mac_interface_rrc_nr +{ +public: + // Provides cell configuration including SIB periodicity, etc. + virtual int cell_cfg(const sched_interface::cell_cfg_t& cell, + srsran::const_span nr_cells) = 0; + + /// Allocates a new user/RNTI at MAC. Returns RNTI on success or SRSRAN_INVALID_RNTI otherwise. + virtual uint16_t reserve_rnti(uint32_t enb_cc_idx) = 0; + + virtual int ue_cfg(uint16_t rnti, const sched_nr_interface::ue_cfg_t& ue_cfg) = 0; +}; + +// NR interface is identical to EUTRA interface +class mac_interface_rlc_nr : public mac_interface_rlc +{}; + +} // namespace srsenb + +#endif // SRSRAN_GNB_MAC_INTERFACES_H diff --git a/srsenb/hdr/stack/mac/mac_nr.h b/srsenb/hdr/stack/mac/mac_nr.h index e55f5361a..b9edb9749 100644 --- a/srsenb/hdr/stack/mac/mac_nr.h +++ b/srsenb/hdr/stack/mac/mac_nr.h @@ -23,21 +23,21 @@ #include "srsran/common/task_scheduler.h" #include "srsran/interfaces/enb_metrics_interface.h" #include "srsran/interfaces/enb_rlc_interfaces.h" -#include "srsran/interfaces/gnb_interfaces.h" +#include "srsran/interfaces/gnb_mac_interfaces.h" namespace srsenb { struct mac_nr_args_t { srsran::phy_cfg_nr_t phy_base_cfg = {}; - int fixed_dl_mcs = -1; - int fixed_ul_mcs = -1; - srsenb::pcap_args_t pcap; + int fixed_dl_mcs = -1; + int fixed_ul_mcs = -1; + srsenb::pcap_args_t pcap; }; class mac_nr final : public mac_interface_phy_nr, public mac_interface_rrc_nr, public mac_interface_rlc_nr { public: - mac_nr(srsran::task_sched_handle task_sched_); + mac_nr(srsran::task_sched_handle task_sched_, const srsenb::sched_nr_interface::sched_cfg_t& sched_cfg = {}); ~mac_nr(); int init(const mac_nr_args_t& args_, @@ -50,9 +50,11 @@ public: void get_metrics(srsenb::mac_metrics_t& metrics); // MAC interface for RRC - int cell_cfg(srsenb::sched_interface::cell_cfg_t* cell_cfg) override; - uint16_t reserve_rnti() override; - int read_pdu_bcch_bch(uint8_t* payload); + int cell_cfg(const sched_interface::cell_cfg_t& cell, + srsran::const_span nr_cells) override; + uint16_t reserve_rnti(uint32_t enb_cc_idx) override; + int read_pdu_bcch_bch(uint8_t* payload); + int ue_cfg(uint16_t rnti, const sched_nr_interface::ue_cfg_t& ue_cfg) override; // MAC interface for RLC // TODO: @@ -68,7 +70,8 @@ public: void rach_detected(const rach_info_t& rach_info) override; private: - uint16_t add_ue(uint32_t enb_cc_idx); + uint16_t add_ue_(uint32_t enb_cc_idx); + uint16_t alloc_ue(uint32_t enb_cc_idx); int remove_ue(uint16_t rnti); // internal misc helpers @@ -91,7 +94,7 @@ private: rrc_interface_mac_nr* rrc = nullptr; // args - srsran::task_sched_handle task_sched; + srsran::task_sched_handle task_sched; srsran::task_multiqueue::queue_handle stack_task_queue; std::unique_ptr pcap = nullptr; @@ -100,17 +103,17 @@ private: std::atomic started = {false}; - const static uint32_t NUMEROLOGY_IDX = 0; /// only 15kHz supported at this stage + const static uint32_t NUMEROLOGY_IDX = 0; /// only 15kHz supported at this stage srsran::slot_point pdsch_slot, pusch_slot; srsenb::sched_nr sched; srsenb::sched_interface::cell_cfg_t cfg = {}; // Map of active UEs - pthread_rwlock_t rwlock = {}; - static const uint16_t FIRST_RNTI = 0x4601; + pthread_rwlock_t rwlock = {}; + static const uint16_t FIRST_RNTI = 0x4601; srsran::static_circular_map, SRSENB_MAX_UES> ue_db; - std::atomic ue_counter; + std::atomic ue_counter; // BCH buffers struct sib_info_t { diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_cell.h b/srsenb/hdr/stack/mac/nr/sched_nr_cell.h index addc017b6..02ada6f30 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_cell.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_cell.h @@ -53,8 +53,13 @@ class ra_sched public: explicit ra_sched(const bwp_params& bwp_cfg_); - int dl_rach_info(const dl_sched_rar_info_t& rar_info); + /// Addition of detected PRACH into the queue + int dl_rach_info(const dl_sched_rar_info_t& rar_info); + + /// Allocate pending RARs void run_slot(bwp_slot_allocator& slot_grid); + + /// Check if there are pending RARs bool empty() const { return pending_rars.empty(); } private: diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h b/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h index 872069f35..7e996fa93 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h @@ -44,15 +44,16 @@ struct bwp_slot_grid { uint32_t slot_idx; const bwp_params* cfg; - bwp_rb_bitmap dl_prbs; - bwp_rb_bitmap ul_prbs; - pdcch_dl_list_t dl_pdcchs; - pdcch_ul_list_t ul_pdcchs; - pdsch_list_t pdschs; - rar_list_t rar; - slot_coreset_list coresets; - pusch_list_t puschs; - harq_ack_list_t pending_acks; + bwp_rb_bitmap dl_prbs; + bwp_rb_bitmap ul_prbs; + pdcch_dl_list_t dl_pdcchs; + pdcch_ul_list_t ul_pdcchs; + pdsch_list_t pdschs; + rar_list_t rar; + slot_coreset_list coresets; + pusch_list_t puschs; + harq_ack_list_t pending_acks; + srsran_softbuffer_tx_t rar_softbuffer; bwp_slot_grid() = default; explicit bwp_slot_grid(const bwp_params& bwp_params, uint32_t slot_idx_); diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index ef6aa3b89..3ed5fe3d5 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -91,7 +91,7 @@ public: uint32_t freq_idx; uint32_t ta_cmd; uint16_t temp_crnti; - uint32_t msg3_size; + uint32_t msg3_size = 7; slot_point prach_slot; }; diff --git a/srsenb/hdr/stack/rrc/rrc_nr.h b/srsenb/hdr/stack/rrc/rrc_nr.h index 55bab1a29..b5cb99443 100644 --- a/srsenb/hdr/stack/rrc/rrc_nr.h +++ b/srsenb/hdr/stack/rrc/rrc_nr.h @@ -28,6 +28,7 @@ #include "srsran/interfaces/enb_rlc_interfaces.h" #include "srsran/interfaces/enb_rrc_interfaces.h" #include "srsran/interfaces/gnb_interfaces.h" +#include "srsran/interfaces/gnb_mac_interfaces.h" #include "srsran/interfaces/gnb_ngap_interfaces.h" #include "srsran/interfaces/gnb_rrc_nr_interfaces.h" #include @@ -118,8 +119,8 @@ public: int pack_nr_radio_bearer_config(asn1::dyn_octstring& packed_nr_bearer_config); // state - rrc_nr_state_t state = rrc_nr_state_t::RRC_IDLE; - uint8_t transaction_id = 0; + rrc_nr_state_t state = rrc_nr_state_t::RRC_IDLE; + uint8_t transaction_id = 0; uint32_t drb1_lcid = 4; }; @@ -128,12 +129,12 @@ private: rrc_nr_cfg_t cfg = {}; // interfaces - phy_interface_stack_nr* phy = nullptr; - mac_interface_rrc_nr* mac = nullptr; + phy_interface_stack_nr* phy = nullptr; + mac_interface_rrc_nr* mac = nullptr; rlc_interface_rrc* rlc = nullptr; pdcp_interface_rrc* pdcp = nullptr; - gtpu_interface_rrc_nr* gtpu = nullptr; - ngap_interface_rrc_nr* ngap = nullptr; + gtpu_interface_rrc_nr* gtpu = nullptr; + ngap_interface_rrc_nr* ngap = nullptr; rrc_eutra_interface_rrc_nr* rrc_eutra = nullptr; // args diff --git a/srsenb/hdr/stack/upper/rlc_nr.h b/srsenb/hdr/stack/upper/rlc_nr.h index 4a1fa424a..978439bf4 100644 --- a/srsenb/hdr/stack/upper/rlc_nr.h +++ b/srsenb/hdr/stack/upper/rlc_nr.h @@ -14,6 +14,7 @@ #define SRSENB_RLC_NR_H #include "srsran/interfaces/gnb_interfaces.h" +#include "srsran/interfaces/gnb_mac_interfaces.h" #include "srsran/rlc/rlc.h" #include diff --git a/srsenb/src/stack/mac/nr/CMakeLists.txt b/srsenb/src/stack/mac/nr/CMakeLists.txt index 106627e38..7d3c3f536 100644 --- a/srsenb/src/stack/mac/nr/CMakeLists.txt +++ b/srsenb/src/stack/mac/nr/CMakeLists.txt @@ -11,7 +11,7 @@ set(SOURCES mac_nr.cc sched_nr.cc sched_nr_ue.cc sched_nr_worker.cc - sched_nr_grant_allocator.cc + sched_nr_grant_allocator.cc sched_nr_harq.cc sched_nr_pdcch.cc sched_nr_cfg.cc diff --git a/srsenb/src/stack/mac/nr/mac_nr.cc b/srsenb/src/stack/mac/nr/mac_nr.cc index 959930e85..afa2d7218 100644 --- a/srsenb/src/stack/mac/nr/mac_nr.cc +++ b/srsenb/src/stack/mac/nr/mac_nr.cc @@ -24,10 +24,10 @@ namespace srsenb { -mac_nr::mac_nr(srsran::task_sched_handle task_sched_) : +mac_nr::mac_nr(srsran::task_sched_handle task_sched_, const sched_nr_interface::sched_cfg_t& sched_cfg) : logger(srslog::fetch_basic_logger("MAC-NR")), task_sched(task_sched_), - sched(srsenb::sched_nr_interface::sched_cfg_t{}), + sched(sched_cfg), bcch_bch_payload(srsran::make_byte_buffer()) { stack_task_queue = task_sched.make_task_queue(); @@ -56,12 +56,6 @@ int mac_nr::init(const mac_nr_args_t& args_, pcap->open(args.pcap.filename); } - // configure scheduler for 1 carrier - std::vector cells_cfg = srsenb::get_default_cells_cfg(1); - sched.cell_cfg(cells_cfg); - - detected_rachs.resize(cells_cfg.size()); - logger.info("Started"); started = true; @@ -82,16 +76,19 @@ void mac_nr::stop() void mac_nr::get_metrics(srsenb::mac_metrics_t& metrics) {} -int mac_nr::cell_cfg(srsenb::sched_interface::cell_cfg_t* cell_cfg) +int mac_nr::cell_cfg(const sched_interface::cell_cfg_t& cell, + srsran::const_span nr_cells) { - cfg = *cell_cfg; + cfg = cell; + sched.cell_cfg(nr_cells); + detected_rachs.resize(nr_cells.size()); // read SIBs from RRC (SIB1 for now only) for (int i = 0; i < 1 /* srsenb::sched_interface::MAX_SIBS */; i++) { - if (cell_cfg->sibs->len > 0) { + if (cell.sibs->len > 0) { sib_info_t sib = {}; sib.index = i; - sib.periodicity = cell_cfg->sibs->period_rf; + sib.periodicity = cell.sibs->period_rf; sib.payload = srsran::make_byte_buffer(); if (sib.payload == nullptr) { logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); @@ -109,6 +106,34 @@ int mac_nr::cell_cfg(srsenb::sched_interface::cell_cfg_t* cell_cfg) return SRSRAN_SUCCESS; } +int mac_nr::ue_cfg(uint16_t rnti, const sched_nr_interface::ue_cfg_t& ue_cfg) +{ + sched.ue_cfg(rnti, ue_cfg); + return SRSRAN_SUCCESS; +} + +uint16_t mac_nr::reserve_rnti(uint32_t enb_cc_idx) +{ + uint16_t rnti = alloc_ue(enb_cc_idx); + if (rnti == SRSRAN_INVALID_RNTI) { + return rnti; + } + + // Add new user to the scheduler so that it can RX/TX SRB0 + srsenb::sched_nr_interface::ue_cfg_t ue_cfg = srsenb::get_default_ue_cfg(1); + ue_cfg.fixed_dl_mcs = args.fixed_dl_mcs; + ue_cfg.fixed_ul_mcs = args.fixed_ul_mcs; + sched.ue_cfg(rnti, ue_cfg); + + // Register new user in RRC + if (rrc->add_user(rnti) == SRSRAN_ERROR) { + // ue_rem(rnti); + return SRSRAN_SUCCESS; + } + + return rnti; +} + void mac_nr::rach_detected(const rach_info_t& rach_info) { static srsran::mutexed_tprof rach_tprof("rach_tprof", "MAC-NR", 1); @@ -117,12 +142,8 @@ void mac_nr::rach_detected(const rach_info_t& rach_info) uint32_t enb_cc_idx = 0; stack_task_queue.push([this, rach_info, enb_cc_idx, rach_tprof_meas]() mutable { - uint16_t rnti = add_ue(enb_cc_idx); - if (rnti == SRSRAN_INVALID_RNTI) { - return; - } - rach_tprof_meas.defer_stop(); + uint16_t rnti = reserve_rnti(enb_cc_idx); // TODO: Generate RAR data // .. @@ -130,25 +151,14 @@ void mac_nr::rach_detected(const rach_info_t& rach_info) // Log this event. ++detected_rachs[enb_cc_idx]; - // Add new user to the scheduler so that it can RX/TX SRB0 - srsenb::sched_nr_interface::ue_cfg_t ue_cfg = srsenb::get_default_ue_cfg(1); - ue_cfg.fixed_dl_mcs = args.fixed_dl_mcs; - ue_cfg.fixed_ul_mcs = args.fixed_ul_mcs; - sched.ue_cfg(rnti, ue_cfg); - - // Register new user in RRC - if (rrc->add_user(rnti) == SRSRAN_ERROR) { - // ue_rem(rnti); - return; - } - // Trigger scheduler RACH srsenb::sched_nr_interface::dl_sched_rar_info_t rar_info = {}; rar_info.preamble_idx = rach_info.preamble; rar_info.temp_crnti = rnti; + rar_info.ta_cmd = rach_info.time_adv; rar_info.prach_slot = slot_point{NUMEROLOGY_IDX, rach_info.slot_index}; // TODO: fill remaining fields as required - // sched.dl_rach_info(enb_cc_idx, rar_info); + sched.dl_rach_info(enb_cc_idx, rar_info); logger.info("RACH: slot=%d, cc=%d, preamble=%d, offset=%d, temp_crnti=0x%x", rach_info.slot_index, @@ -165,7 +175,7 @@ void mac_nr::rach_detected(const rach_info_t& rach_info) }); } -uint16_t mac_nr::add_ue(uint32_t enb_cc_idx) +uint16_t mac_nr::alloc_ue(uint32_t enb_cc_idx) { ue_nr* inserted_ue = nullptr; uint16_t rnti = SRSRAN_INVALID_RNTI; @@ -216,16 +226,6 @@ int mac_nr::remove_ue(uint16_t rnti) return SRSRAN_SUCCESS; } -uint16_t mac_nr::reserve_rnti() -{ - uint16_t rnti = add_ue(0); - if (rnti == SRSRAN_INVALID_RNTI) { - return rnti; - } - - return rnti; -} - bool mac_nr::is_rnti_valid_unsafe(uint16_t rnti) { if (not started) { diff --git a/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc b/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc index d4109f096..fd243bf7b 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc @@ -29,6 +29,7 @@ bwp_slot_grid::bwp_slot_grid(const bwp_params& bwp_cfg_, uint32_t slot_idx_) : coresets[cs_id].emplace(*cfg, cs_id, slot_idx_, dl_pdcchs, ul_pdcchs); } } + srsran_softbuffer_tx_init_guru(&rar_softbuffer, SRSRAN_SCH_NR_MAX_NOF_CB_LDPC, SRSRAN_LDPC_MAX_LEN_ENCODED_CB); } void bwp_slot_grid::reset() @@ -147,6 +148,7 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t slot_cfg.idx = pdcch_slot.slot_idx(); bool success = phy_cfg.get_pdsch_cfg(slot_cfg, pdcch.dci, pdsch.sch); srsran_assert(success, "Error converting DCI to grant"); + pdsch.sch.grant.tb[0].softbuffer.tx = &bwp_pdcch_slot.rar_softbuffer; // Generate Msg3 grants in PUSCH uint32_t last_msg3 = msg3_rbs.start(); diff --git a/srsenb/src/stack/rrc/rrc_nr.cc b/srsenb/src/stack/rrc/rrc_nr.cc index 920532761..c75ebca49 100644 --- a/srsenb/src/stack/rrc/rrc_nr.cc +++ b/srsenb/src/stack/rrc/rrc_nr.cc @@ -12,6 +12,7 @@ #include "srsenb/hdr/stack/rrc/rrc_nr.h" #include "srsenb/hdr/common/common_enb.h" +#include "srsenb/test/mac/nr/sched_nr_cfg_generators.h" #include "srsran/asn1/rrc_nr_utils.h" #include "srsran/common/common_nr.h" #include "srsran/common/phy_cfg_nr_default.h" @@ -210,23 +211,25 @@ void rrc_nr::config_phy() void rrc_nr::config_mac() { // Fill MAC scheduler configuration for SIBs - srsenb::sched_interface::cell_cfg_t sched_cfg; - set_sched_cell_cfg_sib1(&sched_cfg, cfg.sib1); + // TODO: use parsed cell NR cfg configuration + std::vector sched_cells_cfg = {srsenb::get_default_cells_cfg(1)}; + sched_interface::cell_cfg_t cell_cfg; + set_sched_cell_cfg_sib1(&cell_cfg, cfg.sib1); // set SIB length for (uint32_t i = 0; i < nof_si_messages + 1; i++) { - sched_cfg.sibs[i].len = sib_buffer[i]->N_bytes; + cell_cfg.sibs[i].len = sib_buffer[i]->N_bytes; } // PUCCH width - sched_cfg.nrb_pucch = SRSRAN_MAX(cfg.sr_cfg.nof_prb, cfg.cqi_cfg.nof_prb); - logger.info("Allocating %d PRBs for PUCCH", sched_cfg.nrb_pucch); + cell_cfg.nrb_pucch = SRSRAN_MAX(cfg.sr_cfg.nof_prb, cfg.cqi_cfg.nof_prb); + logger.info("Allocating %d PRBs for PUCCH", cell_cfg.nrb_pucch); // Copy Cell configuration - sched_cfg.cell = cfg.cell; + cell_cfg.cell = cfg.cell; // Configure MAC scheduler - mac->cell_cfg(&sched_cfg); + mac->cell_cfg(cell_cfg, sched_cells_cfg); } int32_t rrc_nr::generate_sibs() @@ -405,7 +408,7 @@ int rrc_nr::sgnb_addition_request(uint16_t eutra_rnti) { task_sched.defer_task([this, eutra_rnti]() { // try to allocate new user - uint16_t nr_rnti = mac->reserve_rnti(); + uint16_t nr_rnti = mac->reserve_rnti(0); if (nr_rnti == SRSRAN_INVALID_RNTI) { logger.error("Failed to allocate RNTI at MAC"); rrc_eutra->sgnb_addition_reject(eutra_rnti); diff --git a/srsenb/test/common/dummy_classes_nr.h b/srsenb/test/common/dummy_classes_nr.h index 4237aebe2..d799aadce 100644 --- a/srsenb/test/common/dummy_classes_nr.h +++ b/srsenb/test/common/dummy_classes_nr.h @@ -14,18 +14,38 @@ #define SRSRAN_DUMMY_NR_CLASSES_H #include "srsran/interfaces/gnb_interfaces.h" +#include "srsran/interfaces/gnb_mac_interfaces.h" namespace srsenb { -class mac_dummy : public mac_interface_rrc_nr +class rrc_nr_dummy : public rrc_interface_mac_nr { public: - int cell_cfg(srsenb::sched_interface::cell_cfg_t* cell_cfg_) + int read_pdu_bcch_bch(const uint32_t tti, srsran::unique_byte_buffer_t& buffer) { return SRSRAN_SUCCESS; } + int read_pdu_bcch_dlsch(uint32_t sib_index, srsran::unique_byte_buffer_t& buffer) { return SRSRAN_SUCCESS; } + int add_user(uint16_t rnti) { return SRSRAN_SUCCESS; } +}; + +class rlc_nr_dummy : public rlc_interface_mac_nr +{ +public: + int read_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes) override { return SRSRAN_SUCCESS; } + void read_pdu_pcch(uint8_t* payload, uint32_t buffer_size) override {} + void write_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes) override {} +}; + +class mac_nr_dummy : public mac_interface_rrc_nr +{ +public: + int cell_cfg(const sched_interface::cell_cfg_t& cell, + srsran::const_span nr_cells) override { - cellcfgobj = *cell_cfg_; + cellcfgobj = cell; return SRSRAN_SUCCESS; } - uint16_t reserve_rnti() { return 0x4601; } + uint16_t reserve_rnti(uint32_t enb_cc_idx) override { return 0x4601; } + + int ue_cfg(uint16_t rnti, const sched_nr_interface::ue_cfg_t& ue_cfg) override { return SRSRAN_SUCCESS; } srsenb::sched_interface::cell_cfg_t cellcfgobj; }; diff --git a/srsenb/test/common/rlc_test_dummy.h b/srsenb/test/common/rlc_test_dummy.h new file mode 100644 index 000000000..377f5567e --- /dev/null +++ b/srsenb/test/common/rlc_test_dummy.h @@ -0,0 +1,28 @@ +/** + * + * \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 SRSRAN_RLC_TEST_DUMMY_H +#define SRSRAN_RLC_TEST_DUMMY_H + +#include "srsran/interfaces/enb_rlc_interfaces.h" + +namespace srsenb { + +class rlc_dummy : public rlc_interface_mac +{ + int read_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes) { return SRSRAN_SUCCESS; } + void write_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes) {} +}; + +} // namespace srsenb + +#endif // SRSRAN_RLC_TEST_DUMMY_H diff --git a/srsenb/test/mac/nr/sched_nr_cfg_generators.h b/srsenb/test/mac/nr/sched_nr_cfg_generators.h index 498f2a578..310c63a6e 100644 --- a/srsenb/test/mac/nr/sched_nr_cfg_generators.h +++ b/srsenb/test/mac/nr/sched_nr_cfg_generators.h @@ -18,7 +18,7 @@ namespace srsenb { -srsran_coreset_t get_default_coreset0(uint32_t nof_prb) +inline srsran_coreset_t get_default_coreset0(uint32_t nof_prb) { srsran_coreset_t coreset{}; coreset.id = 0; @@ -30,8 +30,8 @@ srsran_coreset_t get_default_coreset0(uint32_t nof_prb) return coreset; } -sched_nr_interface::cell_cfg_t get_default_cell_cfg(const srsran::phy_cfg_nr_t& phy_cfg = srsran::phy_cfg_nr_default_t{ - srsran::phy_cfg_nr_default_t::reference_cfg_t{}}) +inline sched_nr_interface::cell_cfg_t get_default_cell_cfg( + const srsran::phy_cfg_nr_t& phy_cfg = srsran::phy_cfg_nr_default_t{srsran::phy_cfg_nr_default_t::reference_cfg_t{}}) { sched_nr_interface::cell_cfg_t cell_cfg{}; @@ -65,7 +65,7 @@ sched_nr_interface::cell_cfg_t get_default_cell_cfg(const srsran::phy_cfg_nr_t& return cell_cfg; } -std::vector get_default_cells_cfg( +inline std::vector get_default_cells_cfg( uint32_t nof_sectors, const srsran::phy_cfg_nr_t& phy_cfg = srsran::phy_cfg_nr_default_t{srsran::phy_cfg_nr_default_t::reference_cfg_t{}}) { @@ -77,9 +77,9 @@ std::vector get_default_cells_cfg( return cells; } -sched_nr_interface::ue_cfg_t get_default_ue_cfg(uint32_t nof_cc, - const srsran::phy_cfg_nr_t& phy_cfg = srsran::phy_cfg_nr_default_t{ - srsran::phy_cfg_nr_default_t::reference_cfg_t{}}) +inline sched_nr_interface::ue_cfg_t get_default_ue_cfg( + uint32_t nof_cc, + const srsran::phy_cfg_nr_t& phy_cfg = srsran::phy_cfg_nr_default_t{srsran::phy_cfg_nr_default_t::reference_cfg_t{}}) { sched_nr_interface::ue_cfg_t uecfg{}; uecfg.carriers.resize(nof_cc); diff --git a/srsenb/test/rrc/rrc_nr_test.cc b/srsenb/test/rrc/rrc_nr_test.cc index 3875956f9..5803cf84a 100644 --- a/srsenb/test/rrc/rrc_nr_test.cc +++ b/srsenb/test/rrc/rrc_nr_test.cc @@ -38,10 +38,10 @@ int test_sib_generation() { srsran::task_scheduler task_sched; - mac_dummy mac_obj; - rlc_dummy rlc_obj; - pdcp_dummy pdcp_obj; - rrc_nr rrc_obj(&task_sched); + mac_nr_dummy mac_obj; + rlc_dummy rlc_obj; + pdcp_dummy pdcp_obj; + rrc_nr rrc_obj(&task_sched); // set cfg rrc_nr_cfg_t default_cfg = {}; @@ -67,10 +67,10 @@ int test_rrc_setup() { srsran::task_scheduler task_sched; - mac_dummy mac_obj; - rlc_dummy rlc_obj; - pdcp_dummy pdcp_obj; - rrc_nr rrc_obj(&task_sched); + mac_nr_dummy mac_obj; + rlc_dummy rlc_obj; + pdcp_dummy pdcp_obj; + rrc_nr rrc_obj(&task_sched); // set cfg rrc_nr_cfg_t default_cfg = {}; diff --git a/test/phy/CMakeLists.txt b/test/phy/CMakeLists.txt index 841d53339..f76226e2e 100644 --- a/test/phy/CMakeLists.txt +++ b/test/phy/CMakeLists.txt @@ -18,6 +18,7 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) srsran_radio srsenb_phy srsgnb_mac + srsran_mac ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} @@ -73,6 +74,7 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_bidir_sched nr_phy_test --reference=carrier=${NR_PHY_TEST_BW} --duration=100 # 100 slots + --rnti=17921 # 0x4601 --gnb.stack.pdsch.slots=0,1,2,3,4,5 # All possible DL slots --gnb.stack.pdsch.start=0 # Start at RB 0 --gnb.stack.pdsch.length=52 # Full 10 MHz BW diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index 71c169e83..27efa70c9 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -15,7 +15,10 @@ #include "dummy_rx_harq_proc.h" #include "dummy_tx_harq_proc.h" +#include "srsenb/hdr/stack/mac/mac_nr.h" #include "srsenb/hdr/stack/mac/nr/sched_nr.h" +#include "srsenb/test/common/dummy_classes_nr.h" +#include "srsenb/test/common/rlc_test_dummy.h" #include "srsenb/test/mac/nr/sched_nr_cfg_generators.h" #include #include @@ -73,9 +76,12 @@ private: srsran::phy_cfg_nr_t phy_cfg = {}; bool valid = false; - std::unique_ptr sched; - srsran::slot_point pdsch_slot, pusch_slot; - srslog::basic_logger& sched_logger; + srsran::task_scheduler task_sched; + srsenb::rrc_nr_dummy rrc_obj; + srsenb::rlc_dummy rlc_obj; + std::unique_ptr mac; + srsran::slot_point pdsch_slot, pusch_slot; + srslog::basic_logger& sched_logger; std::mutex metrics_mutex; metrics_t metrics = {}; @@ -291,8 +297,6 @@ private: metrics.mac.tx_errors += tb_count; logger.debug("NACK received!"); } - - sched->dl_ack_info(rnti, 0, ack_bit->pid, 0, is_ok); } // Process SR @@ -305,13 +309,14 @@ private: public: struct args_t { - srsran::phy_cfg_nr_t phy_cfg; ///< Physical layer configuration - bool use_dummy_sched = true; ///< Use dummy or real NR scheduler - uint16_t rnti = 0x1234; ///< C-RNTI - uint32_t ss_id = 1; ///< Search Space identifier - uint32_t pdcch_aggregation_level = 0; ///< PDCCH aggregation level - uint32_t pdcch_dl_candidate = 0; ///< PDCCH DL DCI candidate index - uint32_t pdcch_ul_candidate = 1; ///< PDCCH UL DCI candidate index + srsran::phy_cfg_nr_t phy_cfg; ///< Physical layer configuration + bool use_dummy_sched = true; ///< Use dummy or real NR scheduler + bool wait_preamble = false; ///< Whether a UE is created automatically or the stack waits for a PRACH + uint16_t rnti = 0x1234; ///< C-RNTI + uint32_t ss_id = 1; ///< Search Space identifier + uint32_t pdcch_aggregation_level = 0; ///< PDCCH aggregation level + uint32_t pdcch_dl_candidate = 0; ///< PDCCH DL DCI candidate index + uint32_t pdcch_ul_candidate = 1; ///< PDCCH UL DCI candidate index struct { uint32_t rb_start = 0; ///< Start frequency domain resource block uint32_t rb_length = 10; ///< Number of frequency domain resource blocks @@ -335,15 +340,20 @@ public: srsenb::sched_nr_interface::sched_cfg_t sched_cfg{}; sched_cfg.pdsch_enabled = args.pdsch.slots != "" and args.pdsch.slots != "none"; sched_cfg.pusch_enabled = args.pusch.slots != "" and args.pusch.slots != "none"; - sched.reset(new srsenb::sched_nr{sched_cfg}); + mac.reset(new srsenb::mac_nr{&task_sched, sched_cfg}); + mac->init(srsenb::mac_nr_args_t{}, nullptr, nullptr, &rlc_obj, &rrc_obj); std::vector cells_cfg = srsenb::get_default_cells_cfg(1, phy_cfg); - sched->cell_cfg(cells_cfg); + mac->cell_cfg(srsenb::sched_interface::cell_cfg_t{}, cells_cfg); // add UE to scheduler - srsenb::sched_nr_interface::ue_cfg_t ue_cfg = srsenb::get_default_ue_cfg(1, phy_cfg); - ue_cfg.fixed_dl_mcs = args.pdsch.mcs; - ue_cfg.fixed_ul_mcs = args.pusch.mcs; - sched->ue_cfg(args.rnti, ue_cfg); + if (not use_dummy_sched and not args.wait_preamble) { + mac->reserve_rnti(0); + + srsenb::sched_nr_interface::ue_cfg_t ue_cfg = srsenb::get_default_ue_cfg(1, phy_cfg); + ue_cfg.fixed_dl_mcs = args.pdsch.mcs; + ue_cfg.fixed_ul_mcs = args.pusch.mcs; + mac->ue_cfg(args.rnti, ue_cfg); + } dl.mcs = args.pdsch.mcs; ul.mcs = args.pusch.mcs; @@ -417,9 +427,7 @@ public: } if (not use_dummy_sched) { - srsenb::sched_nr_interface::dl_sched_res_t dl_res; - int ret = sched->get_dl_sched(pdsch_slot, 0, dl_res); - dl_sched = dl_res.dl_sched; + int ret = mac->get_dl_sched(slot_cfg, dl_sched); for (pdsch_t& pdsch : dl_sched.pdsch) { // Set TBS @@ -465,7 +473,7 @@ public: } if (not use_dummy_sched) { - int ret = sched->get_ul_sched(pusch_slot, 0, ul_sched); + int ret = mac->get_ul_sched(slot_cfg, ul_sched); return ret; } @@ -541,22 +549,12 @@ public: return SRSRAN_SUCCESS; } - void dl_ack_info(uint16_t rnti_, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) + int pucch_info(const srsran_slot_cfg_t& slot_cfg, const pucch_info_t& pucch_info) override { if (not use_dummy_sched) { - sched->dl_ack_info(rnti_, cc, pid, tb_idx, ack); + mac->pucch_info(slot_cfg, pucch_info); } - } - void ul_crc_info(uint16_t rnti_, uint32_t cc, uint32_t pid, bool crc) - { - if (not use_dummy_sched) { - sched->ul_crc_info(rnti_, cc, pid, crc); - } - } - - int pucch_info(const srsran_slot_cfg_t& slot_cfg, const pucch_info_t& pucch_info) override - { // Handle UCI data if (not handle_uci_data(pucch_info.uci_data.cfg, pucch_info.uci_data.value)) { logger.error("Error handling UCI data from PUCCH reception"); @@ -588,6 +586,10 @@ public: int pusch_info(const srsran_slot_cfg_t& slot_cfg, pusch_info_t& pusch_info) override { + if (not use_dummy_sched) { + mac->pusch_info(slot_cfg, pusch_info); + } + // Handle UCI data if (not handle_uci_data(pusch_info.uci_cfg, pusch_info.pusch_data.uci)) { logger.error("Error handling UCI data from PUCCH reception"); @@ -602,23 +604,19 @@ public: metrics.mac.rx_brate += rx_harq_proc[pusch_info.pid].get_tbs(); metrics.mac.rx_pkts++; - ul_crc_info(rnti, 0, pusch_info.pid, pusch_info.pusch_data.tb[0].crc); - return SRSRAN_SUCCESS; } void rach_detected(const rach_info_t& rach_info) override { if (not use_dummy_sched) { - srsenb::sched_nr_interface::dl_sched_rar_info_t ra_info; - ra_info.preamble_idx = rach_info.preamble; - ra_info.ta_cmd = rach_info.time_adv; - ra_info.ofdm_symbol_idx = 0; - ra_info.msg3_size = 7; - ra_info.freq_idx = 0; - ra_info.prach_slot = pdsch_slot - TX_ENB_DELAY; - ra_info.temp_crnti = rnti; - sched->dl_rach_info(0, ra_info); + mac->rach_detected(rach_info); + task_sched.run_pending_tasks(); + + srsenb::sched_nr_interface::ue_cfg_t ue_cfg = srsenb::get_default_ue_cfg(1, phy_cfg); + ue_cfg.fixed_dl_mcs = ue_cfg.fixed_dl_mcs; + ue_cfg.fixed_ul_mcs = ue_cfg.fixed_ul_mcs; + mac->ue_cfg(rnti, ue_cfg); } std::unique_lock lock(metrics_mutex); diff --git a/test/phy/nr_phy_test.cc b/test/phy/nr_phy_test.cc index d6071f195..618c85d6b 100644 --- a/test/phy/nr_phy_test.cc +++ b/test/phy/nr_phy_test.cc @@ -115,8 +115,9 @@ test_bench::args_t::args_t(int argc, char** argv) ue_stack.rnti = rnti; - gnb_stack.rnti = rnti; - gnb_stack.phy_cfg = phy_cfg; + gnb_stack.rnti = rnti; + gnb_stack.phy_cfg = phy_cfg; + gnb_stack.wait_preamble = ue_stack.prach_preamble > 0; if (gnb_stack.pdsch.rb_length == 0) { gnb_stack.pdsch.rb_length = phy_cfg.carrier.nof_prb; @@ -271,8 +272,8 @@ int main(int argc, char** argv) } // Assert metrics - TESTASSERT(metrics.gnb_stack.mac.tx_errors == 0); - TESTASSERT(metrics.gnb_stack.mac.rx_errors == 0); + TESTASSERT_EQ(0, metrics.gnb_stack.mac.tx_errors); + TESTASSERT_EQ(0, metrics.gnb_stack.mac.rx_errors); TESTASSERT(metrics.ue_stack.sr_count == metrics.gnb_stack.sr_count); // If reached here, the test is successful