From 0217bf533271c6e2c73a2058c9ea3fcb97fc8324 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Wed, 5 May 2021 11:03:58 +0200 Subject: [PATCH 01/34] Fixed name space for rrc ue --- lib/test/asn1/srsran_asn1_rrc_ul_dcch_test.cc | 4 ++-- srsue/hdr/stack/rrc/rrc.h | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/test/asn1/srsran_asn1_rrc_ul_dcch_test.cc b/lib/test/asn1/srsran_asn1_rrc_ul_dcch_test.cc index fd99cbe92..a85ce41c6 100644 --- a/lib/test/asn1/srsran_asn1_rrc_ul_dcch_test.cc +++ b/lib/test/asn1/srsran_asn1_rrc_ul_dcch_test.cc @@ -52,7 +52,7 @@ int rrc_ue_cap_info_test(srsran::mac_pcap* pcap) rrc_logger.set_level(srslog::basic_levels::debug); rrc_logger.set_hex_dump_max_size(128); - rrc_args_t args = {}; + srsue::rrc_args_t args = {}; args.feature_group = 0xe6041c00; args.nof_supported_bands = 1; args.supported_bands[0] = 8; @@ -119,7 +119,7 @@ int rrc_ue_cap_info_test(srsran::mac_pcap* pcap) int pack_fail_test() { - rrc_args_t args = {}; + srsue::rrc_args_t args = {}; args.feature_group = 0xe6041c00; args.nof_supported_bands = 1; args.supported_bands[0] = 8; diff --git a/srsue/hdr/stack/rrc/rrc.h b/srsue/hdr/stack/rrc/rrc.h index 0f6a3fef4..13b24042a 100644 --- a/srsue/hdr/stack/rrc/rrc.h +++ b/srsue/hdr/stack/rrc/rrc.h @@ -31,6 +31,10 @@ #include #include +using srsran::byte_buffer_t; + +namespace srsue { + #define SRSRAN_RRC_N_BANDS 43 typedef struct { std::string ue_category_str; @@ -53,10 +57,6 @@ typedef struct { #define SRSRAN_RELEASE_MAX 15 #define SRSRAN_RELEASE_DEFAULT (SRSRAN_RELEASE_MAX) -using srsran::byte_buffer_t; - -namespace srsue { - class phy_controller; class usim_interface_rrc; class gw_interface_rrc; From 8d2e81ad6f3ea876cc15df8db03fac082adcf46d Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 16 Jul 2021 10:06:22 +0200 Subject: [PATCH 02/34] enb,mac,nr: add basic UE object skeleton refactor that also adds a basic UE object to the NR MAC --- .../srsran/interfaces/enb_metrics_interface.h | 2 +- .../srsran/interfaces/enb_rrc_interfaces.h | 29 ++- .../srsran/interfaces/gnb_interfaces.h | 7 + srsenb/hdr/stack/enb_stack_base.h | 9 - .../hdr/stack/mac/{ => common}/mac_metrics.h | 0 srsenb/hdr/stack/mac/mac_nr.h | 53 ++-- srsenb/hdr/stack/mac/nr/ue_nr.h | 104 ++++++++ srsenb/hdr/stack/mac/ue.h | 2 +- srsenb/hdr/stack/rrc/rrc.h | 5 +- srsenb/hdr/stack/rrc/rrc_config_nr.h | 45 ++++ srsenb/hdr/stack/rrc/rrc_endc.h | 17 +- srsenb/hdr/stack/rrc/rrc_nr.h | 45 +--- srsenb/hdr/stack/rrc/rrc_ue.h | 5 - srsenb/src/main.cc | 10 +- srsenb/src/stack/enb_stack_lte.cc | 18 +- srsenb/src/stack/gnb_stack_nr.cc | 25 +- srsenb/src/stack/mac/nr/CMakeLists.txt | 15 +- srsenb/src/stack/mac/nr/mac_nr.cc | 236 ++++++++++++------ srsenb/src/stack/mac/nr/ue_nr.cc | 186 ++++++++++++++ srsenb/src/stack/rrc/rrc.cc | 17 +- srsenb/src/stack/rrc/rrc_endc.cc | 37 ++- srsenb/src/stack/rrc/rrc_nr.cc | 133 +++++++--- srsenb/src/stack/rrc/rrc_ue.cc | 12 - srsenb/test/common/dummy_classes.h | 40 --- srsenb/test/common/dummy_classes_common.h | 64 +++++ srsenb/test/common/dummy_classes_nr.h | 35 +++ srsenb/test/common/dummy_nr_classes.h | 60 ----- srsenb/test/rrc/rrc_nr_test.cc | 6 +- srsenb/test/rrc/test_helpers.h | 1 + srsenb/test/upper/gtpu_test.cc | 1 + test/phy/dummy_gnb_stack.h | 2 +- test/phy/dummy_rx_harq_proc.h | 2 +- test/phy/dummy_tx_harq_proc.h | 2 +- 33 files changed, 868 insertions(+), 357 deletions(-) rename srsenb/hdr/stack/mac/{ => common}/mac_metrics.h (100%) create mode 100644 srsenb/hdr/stack/mac/nr/ue_nr.h create mode 100644 srsenb/hdr/stack/rrc/rrc_config_nr.h create mode 100644 srsenb/src/stack/mac/nr/ue_nr.cc create mode 100644 srsenb/test/common/dummy_classes_common.h create mode 100644 srsenb/test/common/dummy_classes_nr.h delete mode 100644 srsenb/test/common/dummy_nr_classes.h diff --git a/lib/include/srsran/interfaces/enb_metrics_interface.h b/lib/include/srsran/interfaces/enb_metrics_interface.h index cdd9dc913..ca3f3e8bd 100644 --- a/lib/include/srsran/interfaces/enb_metrics_interface.h +++ b/lib/include/srsran/interfaces/enb_metrics_interface.h @@ -17,7 +17,7 @@ #include "srsenb/hdr/common/common_enb.h" #include "srsenb/hdr/phy/phy_metrics.h" -#include "srsenb/hdr/stack/mac/mac_metrics.h" +#include "srsenb/hdr/stack/mac/common/mac_metrics.h" #include "srsenb/hdr/stack/rrc/rrc_metrics.h" #include "srsenb/hdr/stack/s1ap/s1ap_metrics.h" #include "srsran/common/metrics_hub.h" diff --git a/lib/include/srsran/interfaces/enb_rrc_interfaces.h b/lib/include/srsran/interfaces/enb_rrc_interfaces.h index dac845bc7..4948b1a47 100644 --- a/lib/include/srsran/interfaces/enb_rrc_interfaces.h +++ b/lib/include/srsran/interfaces/enb_rrc_interfaces.h @@ -127,21 +127,40 @@ class rrc_nr_interface_rrc { public: /// Request addition of NR carrier for UE (TODO: add configuration check, QCI, security, etc.) - virtual int sgnb_addition_request(uint16_t rnti) = 0; + virtual int sgnb_addition_request(uint16_t eutra_rnti) = 0; /// Provide information whether the requested configuration was applied successfully by the UE - virtual int sgnb_reconfiguration_complete(uint16_t rnti, asn1::dyn_octstring reconfig_response) = 0; + virtual int sgnb_reconfiguration_complete(uint16_t eutra_rnti, asn1::dyn_octstring reconfig_response) = 0; }; /// X2AP inspired interface for response from NR RRC to EUTRA RRC class rrc_eutra_interface_rrc_nr { public: - /// Signal successful addition of UE - virtual void sgnb_addition_ack(uint16_t rnti, + /** + * @brief Signal successful addition of UE + * + * @param eutra_rnti The RNTI that the EUTRA RRC used to request the SgNB addition + * @param nr_secondary_cell_group_cfg_r15 Encoded part of the RRC Reconfiguration + * @param nr_radio_bearer_cfg1_r15 Encoded part of the RRC Reconfiguration + */ + virtual void sgnb_addition_ack(uint16_t eutra_rnti, const asn1::dyn_octstring& nr_secondary_cell_group_cfg_r15, const asn1::dyn_octstring& nr_radio_bearer_cfg1_r15) = 0; - virtual void sgnb_addition_reject(uint16_t rnti) = 0; + + /** + * @brief Signal unsuccessful SgNB addition + * + * @param eutra_rnti The RNTI that the EUTRA RRC used to request the SgNB addition + */ + virtual void sgnb_addition_reject(uint16_t eutra_rnti) = 0; + + /** + * @brief Signal completion of SgNB addition after UE (with new NR identity) has attached + * + * @param nr_rnti The RNTI that the EUTRA RRC used to request the SgNB addition + */ + virtual void sgnb_addition_complete(uint16_t eutra_rnti) = 0; }; } // namespace srsenb diff --git a/lib/include/srsran/interfaces/gnb_interfaces.h b/lib/include/srsran/interfaces/gnb_interfaces.h index 71b5d424d..9f41130d8 100644 --- a/lib/include/srsran/interfaces/gnb_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_interfaces.h @@ -32,6 +32,9 @@ 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; }; class mac_interface_rlc_nr @@ -145,6 +148,9 @@ public: // Provides MIB packed message virtual int read_pdu_bcch_bch(const uint32_t tti, srsran::unique_byte_buffer_t& buffer) = 0; virtual int read_pdu_bcch_dlsch(uint32_t sib_index, srsran::unique_byte_buffer_t& buffer) = 0; + + /// User management + virtual int add_user(uint16_t rnti) = 0; }; class rrc_interface_rlc_nr { @@ -183,6 +189,7 @@ public: // TBD }; +// Combined interface for stack (MAC and RRC) to access PHY class phy_interface_stack_nr : public phy_interface_rrc_nr, public phy_interface_mac_nr { public: diff --git a/srsenb/hdr/stack/enb_stack_base.h b/srsenb/hdr/stack/enb_stack_base.h index 44375e12a..7af3f08c1 100644 --- a/srsenb/hdr/stack/enb_stack_base.h +++ b/srsenb/hdr/stack/enb_stack_base.h @@ -59,14 +59,6 @@ typedef struct { int stack_hex_limit; } stack_log_args_t; -// Expert arguments to create GW without core NW -typedef struct { - std::string ip_addr; - srsue::gw_args_t gw_args; - uint8_t drb_lcid; - uint16_t rnti; -} core_less_args_t; - typedef struct { std::string type; uint32_t sync_queue_size; // Max allowed difference between PHY and Stack clocks (in TTI) @@ -78,7 +70,6 @@ typedef struct { pcap_args_t s1ap_pcap; stack_log_args_t log; embms_args_t embms; - core_less_args_t coreless; } stack_args_t; struct stack_metrics_t; diff --git a/srsenb/hdr/stack/mac/mac_metrics.h b/srsenb/hdr/stack/mac/common/mac_metrics.h similarity index 100% rename from srsenb/hdr/stack/mac/mac_metrics.h rename to srsenb/hdr/stack/mac/common/mac_metrics.h diff --git a/srsenb/hdr/stack/mac/mac_nr.h b/srsenb/hdr/stack/mac/mac_nr.h index 7fec1d1f8..1e26415ea 100644 --- a/srsenb/hdr/stack/mac/mac_nr.h +++ b/srsenb/hdr/stack/mac/mac_nr.h @@ -15,27 +15,19 @@ #include "srsran/common/block_queue.h" #include "srsran/common/mac_pcap.h" -#include "srsran/mac/mac_sch_pdu_nr.h" +#include "srsenb/hdr/common/rnti_pool.h" #include "srsenb/hdr/stack/enb_stack_base.h" +#include "srsenb/hdr/stack/mac/nr/ue_nr.h" #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" namespace srsenb { struct mac_nr_args_t { srsenb::pcap_args_t pcap; - - // params for the dummy user - srsenb::sched_interface::sched_args_t sched; - uint16_t rnti; - uint32_t drb_lcid; - - // Add args - std::string log_level; - uint32_t log_hex_limit; - uint32_t tb_size = 64; }; class mac_nr final : public mac_interface_phy_nr, public mac_interface_rrc_nr, public mac_interface_rlc_nr @@ -47,7 +39,7 @@ public: int init(const mac_nr_args_t& args_, phy_interface_stack_nr* phy, stack_interface_mac* stack_, - rlc_interface_mac_nr* rlc_, + rlc_interface_mac* rlc_, rrc_interface_mac_nr* rrc_); void stop(); @@ -55,6 +47,7 @@ public: // 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); // MAC interface for RLC @@ -66,6 +59,7 @@ public: int rx_data_indication(stack_interface_phy_nr::rx_data_ind_t& grant); void process_pdus(); + void rach_detected(const srsran_slot_cfg_t& slot_cfg, uint32_t enb_cc_idx, uint32_t preamble_idx, uint32_t time_adv); int slot_indication(const srsran_slot_cfg_t& slot_cfg) override; int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) override; int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) override; @@ -74,26 +68,40 @@ public: void rach_detected(const rach_info_t& rach_info) override; private: + uint16_t add_ue(uint32_t enb_cc_idx); + int remove_ue(uint16_t rnti); + + // internal misc helpers + bool is_rnti_valid_unsafe(uint16_t rnti); + bool is_rnti_active_unsafe(uint16_t rnti); + // PDU processing int handle_pdu(srsran::unique_byte_buffer_t pdu); // Interaction with other components - phy_interface_stack_nr* phy_h = nullptr; - stack_interface_mac* stack_h = nullptr; - rlc_interface_mac_nr* rlc_h = nullptr; - rrc_interface_mac_nr* rrc_h = nullptr; + phy_interface_stack_nr* phy = nullptr; + stack_interface_mac* stack = nullptr; + rlc_interface_mac* rlc = nullptr; + rrc_interface_mac_nr* rrc = nullptr; // args srsran::task_sched_handle task_sched; + srsran::task_multiqueue::queue_handle stack_task_queue; std::unique_ptr pcap = nullptr; mac_nr_args_t args = {}; srslog::basic_logger& logger; - bool started = false; + std::atomic started = {false}; srsenb::sched_interface::cell_cfg_t cfg = {}; + // Map of active UEs + pthread_rwlock_t rwlock = {}; + static const uint16_t FIRST_RNTI = 0x4601; + rnti_map_t > ue_db; + std::atomic ue_counter; + // BCH buffers struct sib_info_t { uint32_t index; @@ -103,15 +111,8 @@ private: std::vector bcch_dlsch_payload; srsran::unique_byte_buffer_t bcch_bch_payload = nullptr; - // UE-specific buffer - srsran::mac_sch_pdu_nr ue_tx_pdu; - std::vector ue_tx_buffer; - srsran::block_queue - ue_rx_pdu_queue; ///< currently only DCH PDUs supported (add BCH, PCH, etc) - - srsran::unique_byte_buffer_t ue_rlc_buffer; - - srsran::mac_sch_pdu_nr ue_rx_pdu; + // Number of rach preambles detected for a cc. + std::vector detected_rachs; }; } // namespace srsenb diff --git a/srsenb/hdr/stack/mac/nr/ue_nr.h b/srsenb/hdr/stack/mac/nr/ue_nr.h new file mode 100644 index 000000000..355d9a6ed --- /dev/null +++ b/srsenb/hdr/stack/mac/nr/ue_nr.h @@ -0,0 +1,104 @@ +/** + * + * \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 SRSENB_UE_NR_H +#define SRSENB_UE_NR_H + +#include "srsenb/hdr/stack/mac/common/mac_metrics.h" +#include "srsran/common/block_queue.h" +#include "srsran/common/interfaces_common.h" +#include "srsran/interfaces/enb_rlc_interfaces.h" +#include "srsran/interfaces/sched_interface.h" +#include "srsran/mac/mac_sch_pdu_nr.h" +#include +#include + +namespace srsenb { + +class rrc_interface_mac_nr; +class rlc_interface_mac_nr; +class phy_interface_stack_nr; + +class ue_nr : public srsran::read_pdu_interface +{ +public: + ue_nr(uint16_t rnti, + uint32_t enb_cc_idx, + sched_interface* sched_, + rrc_interface_mac_nr* rrc_, + rlc_interface_mac* rlc, + phy_interface_stack_nr* phy_, + srslog::basic_logger& logger); + + virtual ~ue_nr(); + void reset(); + void ue_cfg(const sched_interface::ue_cfg_t& ue_cfg); + + void set_tti(uint32_t tti); + uint16_t get_rnti() const { return rnti; } + void set_active(bool active) { active_state.store(active, std::memory_order_relaxed); } + bool is_active() const { return active_state.load(std::memory_order_relaxed); } + + uint8_t* generate_pdu(uint32_t enb_cc_idx, + uint32_t harq_pid, + uint32_t tb_idx, + const sched_interface::dl_sched_pdu_t pdu[sched_interface::MAX_RLC_PDU_LIST], + uint32_t nof_pdu_elems, + uint32_t grant_size); + int process_pdu(srsran::unique_byte_buffer_t pdu); + + std::mutex metrics_mutex = {}; + void metrics_read(mac_ue_metrics_t* metrics_); + void metrics_rx(bool crc, uint32_t tbs); + void metrics_tx(bool crc, uint32_t tbs); + void metrics_phr(float phr); + void metrics_dl_ri(uint32_t dl_cqi); + void metrics_dl_pmi(uint32_t dl_cqi); + void metrics_dl_cqi(uint32_t dl_cqi); + void metrics_cnt(); + + uint32_t read_pdu(uint32_t lcid, uint8_t* payload, uint32_t requested_bytes) final; + +private: + rlc_interface_mac* rlc = nullptr; + rrc_interface_mac_nr* rrc = nullptr; + phy_interface_stack_nr* phy = nullptr; + srslog::basic_logger& logger; + sched_interface* sched = nullptr; + + uint64_t conres_id = 0; + uint16_t rnti = 0; + uint32_t last_tti = 0; + uint32_t nof_failures = 0; + + std::atomic active_state{true}; + + uint32_t phr_counter = 0; + uint32_t dl_cqi_counter = 0; + uint32_t dl_ri_counter = 0; + uint32_t dl_pmi_counter = 0; + mac_ue_metrics_t ue_metrics = {}; + + // UE-specific buffer for MAC PDU packing, unpacking and handling + srsran::mac_sch_pdu_nr mac_pdu_dl, mac_pdu_ul; + std::vector ue_tx_buffer; + srsran::block_queue + ue_rx_pdu_queue; ///< currently only DCH PDUs supported (add BCH, PCH, etc) + srsran::unique_byte_buffer_t ue_rlc_buffer; + + // Mutexes + std::mutex mutex; +}; + +} // namespace srsenb + +#endif // SRSENB_UE_NR_H diff --git a/srsenb/hdr/stack/mac/ue.h b/srsenb/hdr/stack/mac/ue.h index 8855d9a1b..4fb3a6d58 100644 --- a/srsenb/hdr/stack/mac/ue.h +++ b/srsenb/hdr/stack/mac/ue.h @@ -13,7 +13,7 @@ #ifndef SRSENB_UE_H #define SRSENB_UE_H -#include "mac_metrics.h" +#include "common/mac_metrics.h" #include "srsran/adt/circular_array.h" #include "srsran/adt/circular_map.h" #include "srsran/adt/pool/pool_interface.h" diff --git a/srsenb/hdr/stack/rrc/rrc.h b/srsenb/hdr/stack/rrc/rrc.h index 2a7861e3e..c0aec7310 100644 --- a/srsenb/hdr/stack/rrc/rrc.h +++ b/srsenb/hdr/stack/rrc/rrc.h @@ -126,10 +126,11 @@ public: int notify_ue_erab_updates(uint16_t rnti, srsran::const_byte_span nas_pdu) override; // rrc_eutra_interface_rrc_nr - void sgnb_addition_ack(uint16_t rnti, + void sgnb_addition_ack(uint16_t eutra_rnti, const asn1::dyn_octstring& nr_secondary_cell_group_cfg_r15, const asn1::dyn_octstring& nr_radio_bearer_cfg1_r15) override; - void sgnb_addition_reject(uint16_t rnti) override; + void sgnb_addition_reject(uint16_t eutra_rnti) override; + void sgnb_addition_complete(uint16_t eutra_rnti) override; // rrc_interface_pdcp void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) override; diff --git a/srsenb/hdr/stack/rrc/rrc_config_nr.h b/srsenb/hdr/stack/rrc/rrc_config_nr.h new file mode 100644 index 000000000..469d7bfee --- /dev/null +++ b/srsenb/hdr/stack/rrc/rrc_config_nr.h @@ -0,0 +1,45 @@ +/** + * + * \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_RRC_CONFIG_NR_H +#define SRSRAN_RRC_CONFIG_NR_H + +#include "srsran/asn1/rrc_nr.h" +#include "srsue/hdr/phy/phy_common.h" + +namespace srsenb { + +// TODO: Make this common to NR and LTE +struct rrc_nr_cfg_sr_t { + uint32_t period; + // asn1::rrc::sched_request_cfg_c::setup_s_::dsr_trans_max_e_ dsr_max; + uint32_t nof_prb; + uint32_t sf_mapping[80]; + uint32_t nof_subframes; +}; + +struct rrc_nr_cfg_t { + asn1::rrc_nr::mib_s mib; + asn1::rrc_nr::sib1_s sib1; + asn1::rrc_nr::sys_info_ies_s::sib_type_and_info_item_c_ sibs[ASN1_RRC_NR_MAX_SIB]; + uint32_t nof_sibs; + rrc_nr_cfg_sr_t sr_cfg; + rrc_cfg_cqi_t cqi_cfg; + srsran_cell_t cell; + + std::string log_level; + uint32_t log_hex_limit; +}; + +} // namespace srsenb + +#endif // SRSRAN_RRC_CONFIG_NR_H diff --git a/srsenb/hdr/stack/rrc/rrc_endc.h b/srsenb/hdr/stack/rrc/rrc_endc.h index 80032f470..422371575 100644 --- a/srsenb/hdr/stack/rrc/rrc_endc.h +++ b/srsenb/hdr/stack/rrc/rrc_endc.h @@ -48,6 +48,7 @@ public: void handle_sgnb_addition_ack(const asn1::dyn_octstring& nr_secondary_cell_group_cfg_r15, const asn1::dyn_octstring& nr_radio_bearer_cfg1_r15); void handle_sgnb_addition_reject(); + void handle_sgnb_addition_complete(); private: // Send SgNB addition request to gNB @@ -63,10 +64,15 @@ private: bool endc_supported = false; asn1::rrc::rrc_conn_recfg_complete_s pending_recfg_complete; + // temporary storage for NR reconfiguration + asn1::dyn_octstring nr_secondary_cell_group_cfg_r15; + asn1::dyn_octstring nr_radio_bearer_cfg1_r15; + // events struct sgnb_add_req_sent_ev {}; struct sgnb_add_req_ack_ev {}; struct sgnb_add_req_reject_ev {}; + struct rrc_recfg_sent_ev {}; struct prach_nr_received_ev {}; using recfg_complete_ev = asn1::rrc::rrc_conn_recfg_complete_s; @@ -75,6 +81,7 @@ private: // states struct idle_st {}; struct wait_sgnb_add_req_resp {}; + struct prepare_recfg {}; struct wait_recfg_comp {}; struct wait_prach_nr {}; @@ -86,11 +93,8 @@ private: protected: // states - state_list states{this, - idle_st{}, - wait_sgnb_add_req_resp{}, - wait_recfg_comp{}, - wait_prach_nr{}}; + state_list + states{this, idle_st{}, wait_sgnb_add_req_resp{}, prepare_recfg{}, wait_recfg_comp{}, wait_prach_nr{}}; // transitions using fsm = rrc_endc; @@ -100,8 +104,9 @@ protected: // +-----------------------+-----------------------+------------------------+----------------------------+-------------------------+ row< idle_st, wait_sgnb_add_req_resp, sgnb_add_req_sent_ev, nullptr >, // +-----------------------+-----------------------+------------------------+----------------------------+-------------------------+ - row< wait_sgnb_add_req_resp, wait_recfg_comp, sgnb_add_req_ack_ev >, + row< wait_sgnb_add_req_resp, prepare_recfg, sgnb_add_req_ack_ev >, row< wait_sgnb_add_req_resp, idle_st, sgnb_add_req_reject_ev >, + row< prepare_recfg, wait_recfg_comp, rrc_recfg_sent_ev >, row< wait_recfg_comp, idle_st, recfg_complete_ev, &fsm::handle_recfg_complete > // +-----------------------+-----------------------+------------------------+----------------------------+-------------------------+ >; diff --git a/srsenb/hdr/stack/rrc/rrc_nr.h b/srsenb/hdr/stack/rrc/rrc_nr.h index b6dc82b70..87c225bef 100644 --- a/srsenb/hdr/stack/rrc/rrc_nr.h +++ b/srsenb/hdr/stack/rrc/rrc_nr.h @@ -14,6 +14,7 @@ #define SRSENB_RRC_NR_H #include "rrc_config_common.h" +#include "rrc_config_nr.h" #include "rrc_metrics.h" #include "srsenb/hdr/stack/enb_stack_base.h" #include "srsran/asn1/rrc_nr.h" @@ -23,6 +24,8 @@ #include "srsran/common/task_scheduler.h" #include "srsran/common/threads.h" #include "srsran/common/timeout.h" +#include "srsran/interfaces/enb_pdcp_interfaces.h" +#include "srsran/interfaces/enb_rlc_interfaces.h" #include "srsran/interfaces/enb_rrc_interfaces.h" #include "srsran/interfaces/gnb_interfaces.h" #include "srsran/interfaces/gnb_ngap_interfaces.h" @@ -34,30 +37,6 @@ namespace srsenb { enum class rrc_nr_state_t { RRC_IDLE, RRC_INACTIVE, RRC_CONNECTED }; -// TODO: Make this common to NR and LTE -struct rrc_nr_cfg_sr_t { - uint32_t period; - // asn1::rrc::sched_request_cfg_c::setup_s_::dsr_trans_max_e_ dsr_max; - uint32_t nof_prb; - uint32_t sf_mapping[80]; - uint32_t nof_subframes; -}; - -struct rrc_nr_cfg_t { - asn1::rrc_nr::mib_s mib; - asn1::rrc_nr::sib1_s sib1; - asn1::rrc_nr::sys_info_ies_s::sib_type_and_info_item_c_ sibs[ASN1_RRC_NR_MAX_SIB]; - uint32_t nof_sibs; - rrc_nr_cfg_sr_t sr_cfg; - rrc_cfg_cqi_t cqi_cfg; - srsran_cell_t cell; - - std::string log_level; - uint32_t log_hex_limit; - - srsenb::core_less_args_t coreless; -}; - class rrc_nr final : public rrc_interface_pdcp_nr, public rrc_interface_mac_nr, public rrc_interface_rlc_nr, @@ -70,8 +49,8 @@ public: int32_t init(const rrc_nr_cfg_t& cfg, phy_interface_stack_nr* phy, mac_interface_rrc_nr* mac, - rlc_interface_rrc_nr* rlc, - pdcp_interface_rrc_nr* pdcp, + rlc_interface_rrc* rlc, + pdcp_interface_rrc* pdcp, ngap_interface_rrc_nr* ngap_, gtpu_interface_rrc_nr* gtpu, rrc_eutra_interface_rrc_nr* rrc_eutra_); @@ -81,7 +60,8 @@ public: void get_metrics(srsenb::rrc_metrics_t& m); rrc_nr_cfg_t update_default_cfg(const rrc_nr_cfg_t& rrc_cfg); - void add_user(uint16_t rnti); + int add_user(uint16_t rnti); + int update_user(uint16_t new_rnti, uint16_t old_rnti); void config_mac(); int32_t generate_sibs(); int read_pdu_bcch_bch(const uint32_t tti, srsran::unique_byte_buffer_t& buffer) final; @@ -110,7 +90,7 @@ public: void send_connection_setup(); void send_dl_ccch(asn1::rrc_nr::dl_ccch_msg_s* dl_dcch_msg); - int handle_sgnb_addition_request(); + int handle_sgnb_addition_request(uint16_t eutra_rnti); // getters bool is_connected() { return state == rrc_nr_state_t::RRC_CONNECTED; } @@ -120,13 +100,12 @@ public: // setters private: - rrc_nr* parent; - uint16_t rnti; + rrc_nr* parent = nullptr; + uint16_t rnti = SRSRAN_INVALID_RNTI; // state rrc_nr_state_t state = rrc_nr_state_t::RRC_IDLE; uint8_t transaction_id = 0; - srsran::timer_handler::unique_timer rrc_setup_periodic_timer; }; private: @@ -135,8 +114,8 @@ private: // interfaces phy_interface_stack_nr* phy = nullptr; mac_interface_rrc_nr* mac = nullptr; - rlc_interface_rrc_nr* rlc = nullptr; - pdcp_interface_rrc_nr* pdcp = nullptr; + rlc_interface_rrc* rlc = nullptr; + pdcp_interface_rrc* pdcp = nullptr; gtpu_interface_rrc_nr* gtpu = nullptr; ngap_interface_rrc_nr* ngap = nullptr; rrc_eutra_interface_rrc_nr* rrc_eutra = nullptr; diff --git a/srsenb/hdr/stack/rrc/rrc_ue.h b/srsenb/hdr/stack/rrc/rrc_ue.h index 91b8a6fcf..554d7c0a5 100644 --- a/srsenb/hdr/stack/rrc/rrc_ue.h +++ b/srsenb/hdr/stack/rrc/rrc_ue.h @@ -109,11 +109,6 @@ public: bool handle_ue_ctxt_mod_req(const asn1::s1ap::ue_context_mod_request_s& msg); void handle_ue_info_resp(const asn1::rrc::ue_info_resp_r9_s& msg, srsran::unique_byte_buffer_t pdu); - // SgNB handler - void handle_sgnb_addition_ack(const asn1::dyn_octstring& nr_secondary_cell_group_cfg_r15, - const asn1::dyn_octstring& nr_radio_bearer_cfg1_r15); - void handle_sgnb_addition_reject(); - void set_bitrates(const asn1::s1ap::ue_aggregate_maximum_bitrate_s& rates); /// Helper to check UE ERABs diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 7f300756b..2fb380ff0 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -243,7 +243,6 @@ void parse_args(all_args_t* args, int argc, char* argv[]) ("expert.ts1_reloc_overall_timeout", bpo::value(&args->stack.s1ap.ts1_reloc_overall_timeout)->default_value(10000), "S1AP TS 36.413 TS1RelocOverall Expiry Timeout value in milliseconds") ("expert.rlf_min_ul_snr_estim", bpo::value(&args->stack.mac.rlf_min_ul_snr_estim)->default_value(-2), "SNR threshold in dB below which the eNB is notified with rlf ko.") - // eMBMS section ("embms.enable", bpo::value(&args->stack.embms.enable)->default_value(false), "Enables MBMS in the eNB") ("embms.m1u_multiaddr", bpo::value(&args->stack.embms.m1u_multiaddr)->default_value("239.255.0.1"), "M1-U Multicast address the eNB joins.") @@ -259,14 +258,7 @@ void parse_args(all_args_t* args, int argc, char* argv[]) ("vnf.port", bpo::value(&args->phy.vnf_args.bind_port)->default_value(3333), "Bind port") ("log.vnf_level", bpo::value(&args->phy.vnf_args.log_level), "VNF log level") ("log.vnf_hex_limit", bpo::value(&args->phy.vnf_args.log_hex_limit), "VNF log hex dump limit") - - // Arguments for coreless operation - ("coreless.ip_devname", bpo::value(&args->stack.coreless.gw_args.tun_dev_name)->default_value("tun1"), "Name of the TUN device") - ("coreless.ip_address", bpo::value(&args->stack.coreless.ip_addr)->default_value("192.168.1.1"), "IP address of the TUN device") - ("coreless.ip_netmask", bpo::value(&args->stack.coreless.gw_args.tun_dev_netmask)->default_value("255.255.255.0"), "Netmask of the TUN device") - ("coreless.drb_lcid", bpo::value(&args->stack.coreless.drb_lcid)->default_value(4), "LCID of the dummy DRB") - ("coreless.rnti", bpo::value(&args->stack.coreless.rnti)->default_value(1234), "RNTI of the dummy user") - ; + ; // Positional options - config file location bpo::options_description position("Positional options"); diff --git a/srsenb/src/stack/enb_stack_lte.cc b/srsenb/src/stack/enb_stack_lte.cc index 627239fa1..5434ebb0e 100644 --- a/srsenb/src/stack/enb_stack_lte.cc +++ b/srsenb/src/stack/enb_stack_lte.cc @@ -13,6 +13,7 @@ #include "srsenb/hdr/stack/enb_stack_lte.h" #include "srsenb/hdr/common/rnti_pool.h" #include "srsenb/hdr/enb.h" +#include "srsenb/hdr/stack/rrc/rrc_config_nr.h" #include "srsran/interfaces/enb_metrics_interface.h" #include "srsran/rlc/bearer_mem_pool.h" #include "srsran/srslog/event_trace.h" @@ -131,7 +132,7 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_) // add sync queue sync_task_queue = task_sched.make_task_queue(args.sync_queue_size); - // Init all layers + // Init all LTE layers if (!mac.init(args.mac, rrc_cfg.cell_list, phy, &rlc, &rrc)) { stack_logger.error("Couldn't initialize MAC"); return SRSRAN_ERROR; @@ -147,6 +148,21 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_) return SRSRAN_ERROR; } + // NR layers + mac_nr_args_t mac_args = {}; + mac_args.pcap = args.mac_pcap; + if (mac_nr.init(mac_args, nullptr, nullptr, &rlc_nr, &rrc_nr) != SRSRAN_SUCCESS) { + stack_logger.error("Couldn't initialize MAC-NR"); + return SRSRAN_ERROR; + } + + rrc_nr_cfg_t rrc_cfg_nr = {}; + if (rrc_nr.init(rrc_cfg_nr, nullptr, &mac_nr, &rlc_nr, &pdcp_nr, nullptr, nullptr, &rrc) != SRSRAN_SUCCESS) { + stack_logger.error("Couldn't initialize RRC-NR"); + return SRSRAN_ERROR; + } + // FIXME: Add RLC and PDCP + gtpu_args_t gtpu_args; gtpu_args.embms_enable = args.embms.enable; gtpu_args.embms_m1u_multiaddr = args.embms.m1u_multiaddr; diff --git a/srsenb/src/stack/gnb_stack_nr.cc b/srsenb/src/stack/gnb_stack_nr.cc index 7716da3e8..d287d2888 100644 --- a/srsenb/src/stack/gnb_stack_nr.cc +++ b/srsenb/src/stack/gnb_stack_nr.cc @@ -62,13 +62,8 @@ int gnb_stack_nr::init(const srsenb::stack_args_t& args_, const rrc_nr_cfg_t& rr // Init all layers mac_nr_args_t mac_args = {}; - mac_args.log_level = args.log.mac_level; - mac_args.log_hex_limit = args.log.mac_hex_limit; mac_args.pcap = args.mac_pcap; - mac_args.sched = args.mac.sched; - mac_args.tb_size = args.mac.nr_tb_size; - mac_args.rnti = args.coreless.rnti; - m_mac->init(mac_args, phy, this, m_rlc.get(), m_rrc.get()); + m_mac->init(mac_args, phy, this, nullptr, m_rrc.get()); rlc_logger.set_level(srslog::str_to_basic_level(args.log.rlc_level)); rlc_logger.set_hex_dump_max_size(args.log.rlc_hex_limit); @@ -79,19 +74,12 @@ int gnb_stack_nr::init(const srsenb::stack_args_t& args_, const rrc_nr_cfg_t& rr pdcp_args.log_hex_limit = args.log.pdcp_hex_limit; m_pdcp->init(pdcp_args, m_rlc.get(), m_rrc.get(), m_sdap.get()); - m_rrc->init(rrc_cfg_, phy, m_mac.get(), m_rlc.get(), m_pdcp.get(), nullptr, nullptr, nullptr); + m_rrc->init(rrc_cfg_, phy, m_mac.get(), nullptr, nullptr, nullptr, nullptr, nullptr); m_sdap->init(m_pdcp.get(), nullptr, m_gw.get()); - m_gw->init(args.coreless.gw_args, this); - char* err_str = nullptr; - if (m_gw->setup_if_addr(5, - LIBLTE_MME_PDN_TYPE_IPV4, - htonl(inet_addr(args.coreless.ip_addr.c_str())), - nullptr, - err_str)) { - printf("Error configuring TUN interface\n"); - } + srsue::gw_args_t gw_args = {}; + m_gw->init(gw_args, this); // TODO: add NGAP // m_gtpu->init(args.s1ap.gtp_bind_addr, args.s1ap.mme_addr, @@ -146,7 +134,6 @@ void gnb_stack_nr::run_tti_impl(uint32_t tti) void gnb_stack_nr::process_pdus() { - mac_task_queue.push([this]() { m_mac->process_pdus(); }); } /******************************************************** @@ -170,12 +157,12 @@ int gnb_stack_nr::rx_data_indication(rx_data_ind_t& grant) // Temporary GW interface void gnb_stack_nr::write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) { - m_pdcp->write_sdu(args.coreless.rnti, lcid, std::move(sdu)); + // not implemented } bool gnb_stack_nr::has_active_radio_bearer(uint32_t eps_bearer_id) { - return (eps_bearer_id == args.coreless.drb_lcid); + return false; } int gnb_stack_nr::slot_indication(const srsran_slot_cfg_t& slot_cfg) { diff --git a/srsenb/src/stack/mac/nr/CMakeLists.txt b/srsenb/src/stack/mac/nr/CMakeLists.txt index b71ffe52a..85091bd35 100644 --- a/srsenb/src/stack/mac/nr/CMakeLists.txt +++ b/srsenb/src/stack/mac/nr/CMakeLists.txt @@ -6,7 +6,18 @@ # the distribution. # -set(SOURCES mac_nr.cc sched_nr.cc sched_nr_ue.cc sched_nr_worker.cc sched_nr_rb_grid.cc sched_nr_harq.cc - sched_nr_pdcch.cc sched_nr_cfg.cc sched_nr_helpers.cc sched_nr_bwp.cc sched_nr_rb.cc harq_softbuffer.cc) +set(SOURCES mac_nr.cc + ue_nr.cc + sched_nr.cc + sched_nr_ue.cc + sched_nr_worker.cc + sched_nr_rb_grid.cc + sched_nr_harq.cc + sched_nr_pdcch.cc + sched_nr_cfg.cc + sched_nr_helpers.cc + sched_nr_bwp.cc + sched_nr_rb.cc + harq_softbuffer.cc) add_library(srsgnb_mac STATIC ${SOURCES}) diff --git a/srsenb/src/stack/mac/nr/mac_nr.cc b/srsenb/src/stack/mac/nr/mac_nr.cc index 56b9cf1ed..650b2e7cb 100644 --- a/srsenb/src/stack/mac/nr/mac_nr.cc +++ b/srsenb/src/stack/mac/nr/mac_nr.cc @@ -13,6 +13,9 @@ #include "srsenb/hdr/stack/mac/mac_nr.h" #include "srsran/common/buffer_pool.h" #include "srsran/common/log_helper.h" +#include "srsran/common/rwlock_guard.h" +#include "srsran/common/standard_streams.h" +#include "srsran/common/time_prof.h" #include #include #include @@ -22,7 +25,9 @@ namespace srsenb { mac_nr::mac_nr(srsran::task_sched_handle task_sched_) : logger(srslog::fetch_basic_logger("MAC-NR")), task_sched(task_sched_) -{} +{ + stack_task_queue = task_sched.make_task_queue(); +} mac_nr::~mac_nr() { @@ -32,18 +37,15 @@ mac_nr::~mac_nr() int mac_nr::init(const mac_nr_args_t& args_, phy_interface_stack_nr* phy_, stack_interface_mac* stack_, - rlc_interface_mac_nr* rlc_, + rlc_interface_mac* rlc_, rrc_interface_mac_nr* rrc_) { args = args_; - phy_h = phy_; - stack_h = stack_; - rlc_h = rlc_; - rrc_h = rrc_; - - logger.set_level(srslog::str_to_basic_level(args.log_level)); - logger.set_hex_dump_max_size(args.log_hex_limit); + phy = phy_; + stack = stack_; + rlc = rlc_; + rrc = rrc_; if (args.pcap.enable) { pcap = std::unique_ptr(new srsran::mac_pcap()); @@ -55,20 +57,6 @@ int mac_nr::init(const mac_nr_args_t& args_, return SRSRAN_ERROR; } - // allocate 8 tx buffers for UE (TODO: as we don't handle softbuffers why do we need so many buffers) - for (int i = 0; i < SRSRAN_FDD_NOF_HARQ; i++) { - srsran::unique_byte_buffer_t buffer = srsran::make_byte_buffer(); - if (buffer == nullptr) { - return SRSRAN_ERROR; - } - ue_tx_buffer.emplace_back(std::move(buffer)); - } - - ue_rlc_buffer = srsran::make_byte_buffer(); - if (ue_rlc_buffer == nullptr) { - return SRSRAN_ERROR; - } - logger.info("Started"); started = true; @@ -89,77 +77,167 @@ void mac_nr::stop() void mac_nr::get_metrics(srsenb::mac_metrics_t& metrics) {} -int mac_nr::rx_data_indication(stack_interface_phy_nr::rx_data_ind_t& rx_data) +int mac_nr::cell_cfg(srsenb::sched_interface::cell_cfg_t* cell_cfg) { - // push received PDU on queue - if (rx_data.tb != nullptr) { - if (pcap) { - pcap->write_ul_crnti_nr(rx_data.tb->msg, rx_data.tb->N_bytes, rx_data.rnti, true, rx_data.tti); + cfg = *cell_cfg; + + // read SIBs from RRC (SIB1 for now only) + for (int i = 0; i < srsenb::sched_interface::MAX_SIBS; i++) { + if (cell_cfg->sibs->len > 0) { + sib_info_t sib = {}; + sib.index = i; + sib.periodicity = cell_cfg->sibs->period_rf; + sib.payload = srsran::make_byte_buffer(); + if (rrc->read_pdu_bcch_dlsch(sib.index, sib.payload) != SRSRAN_SUCCESS) { + logger.error("Couldn't read SIB %d from RRC", sib.index); + } + + logger.info("Including SIB %d into SI scheduling", sib.index); + bcch_dlsch_payload.push_back(std::move(sib)); } - ue_rx_pdu_queue.push(std::move(rx_data.tb)); } - // inform stack that new PDUs may have been received - stack_h->process_pdus(); - return SRSRAN_SUCCESS; } -/** - * Called from the main stack thread to process received PDUs - */ -void mac_nr::process_pdus() +void mac_nr::rach_detected(const srsran_slot_cfg_t& slot_cfg, + uint32_t enb_cc_idx, + uint32_t preamble_idx, + uint32_t time_adv) { - while (started and not ue_rx_pdu_queue.empty()) { - srsran::unique_byte_buffer_t pdu = ue_rx_pdu_queue.wait_pop(); - /// TODO; delegate to demux class - handle_pdu(std::move(pdu)); - } + static srsran::mutexed_tprof rach_tprof("rach_tprof", "MAC-NR", 1); + logger.set_context(slot_cfg.idx); + auto rach_tprof_meas = rach_tprof.start(); + + stack_task_queue.push([this, slot_cfg, enb_cc_idx, preamble_idx, time_adv, rach_tprof_meas]() mutable { + uint16_t rnti = add_ue(enb_cc_idx); + if (rnti == SRSRAN_INVALID_RNTI) { + return; + } + + rach_tprof_meas.defer_stop(); + + // TODO: Generate RAR data + // .. + + // Log this event. + ++detected_rachs[enb_cc_idx]; + + // Add new user to the scheduler so that it can RX/TX SRB0 + // .. + + // Register new user in RRC + if (rrc->add_user(rnti) == SRSRAN_ERROR) { + // ue_rem(rnti); + return; + } + + // Trigger scheduler RACH + // scheduler.dl_rach_info(enb_cc_idx, rar_info); + + logger.info("RACH: cc=%d, preamble=%d, offset=%d, temp_crnti=0x%x", + slot_cfg.idx, + enb_cc_idx, + preamble_idx, + time_adv, + rnti); + srsran::console("RACH: cc=%d, preamble=%d, offset=%d, temp_crnti=0x%x\n", + slot_cfg.idx, + enb_cc_idx, + preamble_idx, + time_adv, + rnti); + }); } -int mac_nr::handle_pdu(srsran::unique_byte_buffer_t pdu) +uint16_t mac_nr::add_ue(uint32_t enb_cc_idx) { - logger.info(pdu->msg, pdu->N_bytes, "Handling MAC PDU (%d B)", pdu->N_bytes); + ue_nr* inserted_ue = nullptr; + uint16_t rnti = SRSRAN_INVALID_RNTI; + + do { + // Assign new RNTI + rnti = FIRST_RNTI + (ue_counter.fetch_add(1, std::memory_order_relaxed) % 60000); + + // Pre-check if rnti is valid + { + srsran::rwlock_read_guard read_lock(rwlock); + if (not is_rnti_valid_unsafe(rnti)) { + continue; + } + } - ue_rx_pdu.init_rx(true); - if (ue_rx_pdu.unpack(pdu->msg, pdu->N_bytes) != SRSRAN_SUCCESS) { - return SRSRAN_ERROR; - } + // Allocate and initialize UE object + // TODO: add sched interface + unique_rnti_ptr ue_ptr = make_rnti_obj(rnti, rnti, enb_cc_idx, nullptr, rrc, rlc, phy, logger); + + // Add UE to rnti map + srsran::rwlock_write_guard rw_lock(rwlock); + if (not is_rnti_valid_unsafe(rnti)) { + continue; + } + auto ret = ue_db.insert(rnti, std::move(ue_ptr)); + if (ret.has_value()) { + inserted_ue = ret.value()->second.get(); + } else { + logger.info("Failed to allocate rnti=0x%x. Attempting a different rnti.", rnti); + } + } while (inserted_ue == nullptr); - for (uint32_t i = 0; i < ue_rx_pdu.get_num_subpdus(); ++i) { - srsran::mac_sch_subpdu_nr subpdu = ue_rx_pdu.get_subpdu(i); - logger.info("Handling subPDU %d/%d: lcid=%d, sdu_len=%d", - i, - ue_rx_pdu.get_num_subpdus(), - subpdu.get_lcid(), - subpdu.get_sdu_length()); + // Set PCAP if available + // .. - // rlc_h->write_pdu(args.rnti, subpdu.get_lcid(), subpdu.get_sdu(), subpdu.get_sdu_length()); + return rnti; +} + +// Remove UE from the perspective of L2/L3 +int mac_nr::remove_ue(uint16_t rnti) +{ + srsran::rwlock_write_guard lock(rwlock); + if (is_rnti_active_unsafe(rnti)) { + ue_db.erase(rnti); + } else { + logger.error("User rnti=0x%x not found", rnti); + return SRSRAN_ERROR; } + return SRSRAN_SUCCESS; } -int mac_nr::cell_cfg(srsenb::sched_interface::cell_cfg_t* cell_cfg) +uint16_t mac_nr::reserve_rnti() { - cfg = *cell_cfg; + uint16_t rnti = add_ue(0); + if (rnti == SRSRAN_INVALID_RNTI) { + return rnti; + } - // read SIBs from RRC (SIB1 for now only) - for (int i = 0; i < srsenb::sched_interface::MAX_SIBS; i++) { - if (cell_cfg->sibs->len > 0) { - sib_info_t sib = {}; - sib.index = i; - sib.periodicity = cell_cfg->sibs->period_rf; - sib.payload = srsran::make_byte_buffer(); - if (rrc_h->read_pdu_bcch_dlsch(sib.index, sib.payload) != SRSRAN_SUCCESS) { - logger.error("Couldn't read SIB %d from RRC", sib.index); - } + return rnti; +} - logger.info("Including SIB %d into SI scheduling", sib.index); - bcch_dlsch_payload.push_back(std::move(sib)); - } +bool mac_nr::is_rnti_valid_unsafe(uint16_t rnti) +{ + if (not started) { + logger.info("RACH ignored as eNB is being shutdown"); + return false; + } + if (ue_db.full()) { + logger.warning("Maximum number of connected UEs %zd connected to the eNB. Ignoring PRACH", SRSENB_MAX_UES); + return false; + } + if (not ue_db.has_space(rnti)) { + logger.info("Failed to allocate rnti=0x%x. Attempting a different rnti.", rnti); + return false; } + return true; +} - return SRSRAN_SUCCESS; +bool mac_nr::is_rnti_active_unsafe(uint16_t rnti) +{ + if (not ue_db.contains(rnti)) { + logger.error("User rnti=0x%x not found", rnti); + return false; + } + return ue_db[rnti]->is_active(); } int mac_nr::slot_indication(const srsran_slot_cfg_t& slot_cfg) @@ -181,8 +259,22 @@ int mac_nr::pucch_info(const srsran_slot_cfg_t& slot_cfg, const mac_interface_ph } int mac_nr::pusch_info(const srsran_slot_cfg_t& slot_cfg, const mac_interface_phy_nr::pusch_info_t& pusch_info) { - return 0; + // FIXME: does the PUSCH info call include received PDUs? + uint16_t rnti = pusch_info.rnti; + srsran::unique_byte_buffer_t rx_pdu; + auto process_pdu_task = [this, rnti](srsran::unique_byte_buffer_t& pdu) { + srsran::rwlock_read_guard lock(rwlock); + if (is_rnti_active_unsafe(rnti)) { + ue_db[rnti]->process_pdu(std::move(pdu)); + } else { + logger.debug("Discarding PDU rnti=0x%x", rnti); + } + }; + stack_task_queue.try_push(std::bind(process_pdu_task, std::move(rx_pdu))); + + return SRSRAN_SUCCESS; } + void mac_nr::rach_detected(const mac_interface_phy_nr::rach_info_t& rach_info) {} } // namespace srsenb diff --git a/srsenb/src/stack/mac/nr/ue_nr.cc b/srsenb/src/stack/mac/nr/ue_nr.cc new file mode 100644 index 000000000..42ff4710e --- /dev/null +++ b/srsenb/src/stack/mac/nr/ue_nr.cc @@ -0,0 +1,186 @@ +/** + * + * \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 +#include +#include +#include + +#include "srsenb/hdr/stack/mac/nr/ue_nr.h" +#include "srsran/common/string_helpers.h" +#include "srsran/interfaces/gnb_interfaces.h" + +namespace srsenb { + +ue_nr::ue_nr(uint16_t rnti_, + uint32_t enb_cc_idx, + sched_interface* sched_, + rrc_interface_mac_nr* rrc_, + rlc_interface_mac* rlc_, + phy_interface_stack_nr* phy_, + srslog::basic_logger& logger_) : + rnti(rnti_), sched(sched_), rrc(rrc_), rlc(rlc_), phy(phy_), logger(logger_) +{} + +ue_nr::~ue_nr() {} + +void ue_nr::reset() +{ + ue_metrics = {}; + nof_failures = 0; +} + +void ue_nr::ue_cfg(const sched_interface::ue_cfg_t& ue_cfg) +{ + // nop +} + +void ue_nr::set_tti(uint32_t tti) +{ + last_tti = tti; +} + +int ue_nr::process_pdu(srsran::unique_byte_buffer_t pdu) +{ + logger.info(pdu->msg, pdu->N_bytes, "Handling MAC PDU (%d B)", pdu->N_bytes); + + mac_pdu_ul.init_rx(true); + if (mac_pdu_ul.unpack(pdu->msg, pdu->N_bytes) != SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + + if (logger.info.enabled()) { + fmt::memory_buffer str_buffer; + // mac_pdu_ul.to_string(str_buffer); + logger.info("0x%x %s", rnti, srsran::to_c_str(str_buffer)); + } + + for (uint32_t i = 0; i < mac_pdu_ul.get_num_subpdus(); ++i) { + srsran::mac_sch_subpdu_nr subpdu = mac_pdu_ul.get_subpdu(i); + logger.info("Handling subPDU %d/%d: lcid=%d, sdu_len=%d", + i, + mac_pdu_ul.get_num_subpdus(), + subpdu.get_lcid(), + subpdu.get_sdu_length()); + + rlc->write_pdu(rnti, subpdu.get_lcid(), subpdu.get_sdu(), subpdu.get_sdu_length()); + } + return SRSRAN_SUCCESS; +} + +uint32_t ue_nr::read_pdu(uint32_t lcid, uint8_t* payload, uint32_t requested_bytes) +{ + return rlc->read_pdu(rnti, lcid, payload, requested_bytes); +} + +uint8_t* ue_nr::generate_pdu(uint32_t enb_cc_idx, + uint32_t harq_pid, + uint32_t tb_idx, + const sched_interface::dl_sched_pdu_t pdu[sched_interface::MAX_RLC_PDU_LIST], + uint32_t nof_pdu_elems, + uint32_t grant_size) +{ + std::lock_guard lock(mutex); + uint8_t* ret = nullptr; + if (enb_cc_idx < SRSRAN_MAX_CARRIERS && harq_pid < SRSRAN_FDD_NOF_HARQ && tb_idx < SRSRAN_MAX_TB) { + srsran::byte_buffer_t* buffer = nullptr; // TODO: read from scheduler output + buffer->clear(); + + mac_pdu_dl.init_tx(buffer, grant_size); + + // read RLC PDU + ue_rlc_buffer->clear(); + int lcid = 4; + int pdu_len = rlc->read_pdu(rnti, lcid, ue_rlc_buffer->msg, grant_size - 2); + + // Only create PDU if RLC has something to tx + if (pdu_len > 0) { + logger.info("Adding MAC PDU for RNTI=%d", rnti); + ue_rlc_buffer->N_bytes = pdu_len; + logger.info(ue_rlc_buffer->msg, ue_rlc_buffer->N_bytes, "Read %d B from RLC", ue_rlc_buffer->N_bytes); + + // add to MAC PDU and pack + mac_pdu_dl.add_sdu(4, ue_rlc_buffer->msg, ue_rlc_buffer->N_bytes); + mac_pdu_dl.pack(); + } + + if (logger.info.enabled()) { + fmt::memory_buffer str_buffer; + // mac_pdu_dl.to_string(str_buffer); + logger.info("0x%x %s", rnti, srsran::to_c_str(str_buffer)); + } + } else { + logger.error( + "Invalid parameters calling generate_pdu: cc_idx=%d, harq_pid=%d, tb_idx=%d", enb_cc_idx, harq_pid, tb_idx); + } + return ret; +} + +/******* METRICS interface ***************/ +void ue_nr::metrics_read(mac_ue_metrics_t* metrics_) +{ + uint32_t ul_buffer = sched->get_ul_buffer(rnti); + uint32_t dl_buffer = sched->get_dl_buffer(rnti); + + std::lock_guard lock(metrics_mutex); + ue_metrics.rnti = rnti; + ue_metrics.ul_buffer = ul_buffer; + ue_metrics.dl_buffer = dl_buffer; + + // set PCell sector id + std::array cc_list = sched->get_enb_ue_cc_map(rnti); + auto it = std::find(cc_list.begin(), cc_list.end(), 0); + ue_metrics.cc_idx = std::distance(cc_list.begin(), it); + + *metrics_ = ue_metrics; + + phr_counter = 0; + dl_cqi_counter = 0; + ue_metrics = {}; +} + +void ue_nr::metrics_dl_cqi(uint32_t dl_cqi) +{ + std::lock_guard lock(metrics_mutex); + ue_metrics.dl_cqi = SRSRAN_VEC_CMA((float)dl_cqi, ue_metrics.dl_cqi, dl_cqi_counter); + dl_cqi_counter++; +} + +void ue_nr::metrics_rx(bool crc, uint32_t tbs) +{ + std::lock_guard lock(metrics_mutex); + if (crc) { + ue_metrics.rx_brate += tbs * 8; + } else { + ue_metrics.rx_errors++; + } + ue_metrics.rx_pkts++; +} + +void ue_nr::metrics_tx(bool crc, uint32_t tbs) +{ + std::lock_guard lock(metrics_mutex); + if (crc) { + ue_metrics.tx_brate += tbs * 8; + } else { + ue_metrics.tx_errors++; + } + ue_metrics.tx_pkts++; +} + +void ue_nr::metrics_cnt() +{ + std::lock_guard lock(metrics_mutex); + ue_metrics.nof_tti++; +} + +} // namespace srsenb diff --git a/srsenb/src/stack/rrc/rrc.cc b/srsenb/src/stack/rrc/rrc.cc index d80d3f81a..078a51dbd 100644 --- a/srsenb/src/stack/rrc/rrc.cc +++ b/srsenb/src/stack/rrc/rrc.cc @@ -554,16 +554,25 @@ void rrc::set_erab_status(uint16_t rnti, const asn1::s1ap::bearers_subject_to_st EN-DC/NSA helper functions *******************************************************************************/ -void rrc::sgnb_addition_ack(uint16_t rnti, +void rrc::sgnb_addition_ack(uint16_t eutra_rnti, const asn1::dyn_octstring& nr_secondary_cell_group_cfg_r15, const asn1::dyn_octstring& nr_radio_bearer_cfg1_r15) { - users.at(rnti)->endc_handler->handle_sgnb_addition_ack(nr_secondary_cell_group_cfg_r15, nr_radio_bearer_cfg1_r15); + users.at(eutra_rnti) + ->endc_handler->handle_sgnb_addition_ack(nr_secondary_cell_group_cfg_r15, nr_radio_bearer_cfg1_r15); + + // trigger RRC Reconfiguration to send NR config to UE + users.at(eutra_rnti)->send_connection_reconf(); +} + +void rrc::sgnb_addition_reject(uint16_t eutra_rnti) +{ + users.at(eutra_rnti)->endc_handler->handle_sgnb_addition_reject(); } -void rrc::sgnb_addition_reject(uint16_t rnti) +void rrc::sgnb_addition_complete(uint16_t eutra_rnti) { - users.at(rnti)->endc_handler->handle_sgnb_addition_reject(); + users.at(eutra_rnti)->endc_handler->handle_sgnb_addition_complete(); } /******************************************************************************* diff --git a/srsenb/src/stack/rrc/rrc_endc.cc b/srsenb/src/stack/rrc/rrc_endc.cc index d8a298a4f..46ca65ca4 100644 --- a/srsenb/src/stack/rrc/rrc_endc.cc +++ b/srsenb/src/stack/rrc/rrc_endc.cc @@ -124,7 +124,7 @@ bool rrc::ue::rrc_endc::fill_conn_recfg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn meas_cfg.meas_gap_cfg_present = true; meas_cfg.meas_gap_cfg.set_setup(); meas_cfg.meas_gap_cfg.setup().gap_offset.set_gp0() = 16; - } else { + } else if (is_in_state()) { // only add reconfigure EN-DC extension/release 15.10 field if ENDC activation is active conn_recfg->non_crit_ext_present = true; conn_recfg->non_crit_ext.non_crit_ext_present = true; @@ -139,8 +139,21 @@ bool rrc::ue::rrc_endc::fill_conn_recfg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn rrc_conn_recfg_v1510_ies_s& reconf_v1510 = conn_recfg->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext .non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext; reconf_v1510.nr_cfg_r15_present = true; + reconf_v1510.nr_cfg_r15.set_setup(); + + reconf_v1510.nr_cfg_r15.setup().endc_release_and_add_r15 = false; + reconf_v1510.nr_cfg_r15.setup().nr_secondary_cell_group_cfg_r15_present = true; + reconf_v1510.nr_cfg_r15.setup().nr_secondary_cell_group_cfg_r15 = nr_secondary_cell_group_cfg_r15; + reconf_v1510.sk_counter_r15_present = true; reconf_v1510.sk_counter_r15 = 0; + + reconf_v1510.nr_radio_bearer_cfg1_r15_present = true; + reconf_v1510.nr_radio_bearer_cfg1_r15 = nr_radio_bearer_cfg1_r15; + + // inform FSM + rrc_recfg_sent_ev recfg_sent{}; + trigger(recfg_sent); } return true; @@ -226,18 +239,17 @@ void rrc::ue::rrc_endc::handle_ue_meas_report(const meas_report_s& msg) trigger(sgnb_add_req); } -void rrc::ue::rrc_endc::handle_sgnb_addition_ack(const asn1::dyn_octstring& nr_secondary_cell_group_cfg_r15, - const asn1::dyn_octstring& nr_radio_bearer_cfg1_r15) +void rrc::ue::rrc_endc::handle_sgnb_addition_ack(const asn1::dyn_octstring& nr_secondary_cell_group_cfg_r15_, + const asn1::dyn_octstring& nr_radio_bearer_cfg1_r15_) { logger.info("Received SgNB addition acknowledgement for rnti=%d", rrc_ue->rnti); - // prepare reconfiguration message with NR fields - srsran::unique_byte_buffer_t pdu = srsran::make_byte_buffer(); - if (pdu == nullptr) { - logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); - return; - } - // rrc_enb->send_connection_reconf(std::move(pdu)); + // store received configurations + nr_secondary_cell_group_cfg_r15 = nr_secondary_cell_group_cfg_r15_; + nr_radio_bearer_cfg1_r15 = nr_radio_bearer_cfg1_r15_; + + sgnb_add_req_ack_ev sgnb_add_ack{}; + trigger(sgnb_add_ack); } void rrc::ue::rrc_endc::handle_sgnb_addition_reject() @@ -250,4 +262,9 @@ void rrc::ue::rrc_endc::handle_recfg_complete(wait_recfg_comp& s, const recfg_co logger.info("User rnti=0x%x successfully enabled EN-DC", rrc_ue->rnti); } +void rrc::ue::rrc_endc::handle_sgnb_addition_complete() +{ + logger.info("Received SgNB addition complete for rnti=%d", rrc_ue->rnti); +} + } // namespace srsenb diff --git a/srsenb/src/stack/rrc/rrc_nr.cc b/srsenb/src/stack/rrc/rrc_nr.cc index 7c59e14ce..a7fdd459c 100644 --- a/srsenb/src/stack/rrc/rrc_nr.cc +++ b/srsenb/src/stack/rrc/rrc_nr.cc @@ -26,8 +26,8 @@ rrc_nr::rrc_nr(srsran::task_sched_handle task_sched_) : int rrc_nr::init(const rrc_nr_cfg_t& cfg_, phy_interface_stack_nr* phy_, mac_interface_rrc_nr* mac_, - rlc_interface_rrc_nr* rlc_, - pdcp_interface_rrc_nr* pdcp_, + rlc_interface_rrc* rlc_, + pdcp_interface_rrc* pdcp_, ngap_interface_rrc_nr* ngap_, gtpu_interface_rrc_nr* gtpu_, rrc_eutra_interface_rrc_nr* rrc_eutra_) @@ -36,8 +36,9 @@ int rrc_nr::init(const rrc_nr_cfg_t& cfg_, mac = mac_; rlc = rlc_; pdcp = pdcp_; - gtpu = gtpu_; ngap = ngap_; + gtpu = gtpu_; + rrc_eutra = rrc_eutra_; // TODO: overwriting because we are not passing config right now cfg = update_default_cfg(cfg_); @@ -56,22 +57,6 @@ int rrc_nr::init(const rrc_nr_cfg_t& cfg_, config_mac(); - // add dummy user - logger.info("Creating dummy DRB for RNTI=%d on LCID=%d", cfg.coreless.rnti, cfg.coreless.drb_lcid); - add_user(cfg.coreless.rnti); - srsran::rlc_config_t rlc_cnfg = srsran::rlc_config_t::default_rlc_um_nr_config(6); - rlc->add_bearer(cfg.coreless.rnti, cfg.coreless.drb_lcid, rlc_cnfg); - srsran::pdcp_config_t pdcp_cnfg{cfg.coreless.drb_lcid, - srsran::PDCP_RB_IS_DRB, - srsran::SECURITY_DIRECTION_DOWNLINK, - srsran::SECURITY_DIRECTION_UPLINK, - srsran::PDCP_SN_LEN_18, - srsran::pdcp_t_reordering_t::ms500, - srsran::pdcp_discard_timer_t::infinity, - false, - srsran::srsran_rat_t::nr}; - pdcp->add_bearer(cfg.coreless.rnti, cfg.coreless.drb_lcid, pdcp_cnfg); - logger.info("Started"); running = true; @@ -171,16 +156,46 @@ rrc_nr_cfg_t rrc_nr::update_default_cfg(const rrc_nr_cfg_t& current) } // This function is called from PRACH worker (can wait) -void rrc_nr::add_user(uint16_t rnti) +int rrc_nr::add_user(uint16_t rnti) { if (users.count(rnti) == 0) { users.insert(std::make_pair(rnti, std::unique_ptr(new ue(this, rnti)))); rlc->add_user(rnti); pdcp->add_user(rnti); logger.info("Added new user rnti=0x%x", rnti); + return SRSRAN_SUCCESS; } else { logger.error("Adding user rnti=0x%x (already exists)", rnti); + return SRSRAN_ERROR; + } +} + +/* Function called by MAC after the reception of a C-RNTI CE indicating that the UE still has a + * valid RNTI. + */ +int rrc_nr::update_user(uint16_t new_rnti, uint16_t old_rnti) +{ + // Remove new_rnti + auto new_ue_it = users.find(new_rnti); + if (new_ue_it != users.end()) { + // TODO: cleanup new user? + return SRSRAN_ERROR; + } + + // Send Reconfiguration to old_rnti if is RRC_CONNECT or RRC Release if already released here + auto old_it = users.find(old_rnti); + if (old_it == users.end()) { + logger.info("rnti=0x%x received MAC CRNTI CE: 0x%x, but old context is unavailable", new_rnti, old_rnti); + return SRSRAN_ERROR; + } + ue* ue_ptr = old_it->second.get(); + + // Assume that SgNB addition is running + logger.info("Resuming rnti=0x%x RRC connection due to received C-RNTI CE from rnti=0x%x.", old_rnti, new_rnti); + if (ue_ptr->is_connected()) { + rrc_eutra->sgnb_addition_complete(new_rnti); } + return SRSRAN_SUCCESS; } void rrc_nr::config_mac() @@ -355,15 +370,37 @@ void rrc_nr::notify_pdcp_integrity_error(uint16_t rnti, uint32_t lcid) {} Interface for EUTRA RRC *******************************************************************************/ -int rrc_nr::sgnb_addition_request(uint16_t rnti) +int rrc_nr::sgnb_addition_request(uint16_t eutra_rnti) { - // try to allocate new user - task_sched.defer_task([]() {}); + task_sched.defer_task([this, eutra_rnti]() { + // try to allocate new user + uint16_t nr_rnti = mac->reserve_rnti(); + if (nr_rnti == SRSRAN_INVALID_RNTI) { + logger.error("Failed to allocate RNTI at MAC"); + rrc_eutra->sgnb_addition_reject(eutra_rnti); + return; + } + + if (add_user(nr_rnti) != SRSRAN_SUCCESS) { + logger.error("Failed to allocate RNTI at RRC"); + rrc_eutra->sgnb_addition_reject(eutra_rnti); + return; + } + + // new RNTI is now registered at MAC and RRC + auto user_it = users.find(nr_rnti); + if (user_it == users.end()) { + logger.warning("Unrecognised rnti: 0x%x", nr_rnti); + return; + } + user_it->second->handle_sgnb_addition_request(eutra_rnti); + }); // return straight away return SRSRAN_SUCCESS; } -int rrc_nr::sgnb_reconfiguration_complete(uint16_t rnti, asn1::dyn_octstring reconfig_response) + +int rrc_nr::sgnb_reconfiguration_complete(uint16_t eutra_rnti, asn1::dyn_octstring reconfig_response) { return SRSRAN_SUCCESS; } @@ -376,13 +413,6 @@ int rrc_nr::sgnb_reconfiguration_complete(uint16_t rnti, asn1::dyn_octstring rec *******************************************************************************/ rrc_nr::ue::ue(rrc_nr* parent_, uint16_t rnti_) : parent(parent_), rnti(rnti_) { - // setup periodic RRCSetup send - rrc_setup_periodic_timer = parent->task_sched.get_unique_timer(); - rrc_setup_periodic_timer.set(5000, [this](uint32_t tid) { - send_connection_setup(); - rrc_setup_periodic_timer.run(); - }); - rrc_setup_periodic_timer.run(); } void rrc_nr::ue::send_connection_setup() @@ -427,7 +457,7 @@ void rrc_nr::ue::send_dl_ccch(dl_ccch_msg_s* dl_ccch_msg) parent->rlc->write_sdu(rnti, (uint32_t)srsran::nr_srb::srb0, std::move(pdu)); } -int rrc_nr::ue::handle_sgnb_addition_request() +int rrc_nr::ue::handle_sgnb_addition_request(uint16_t eutra_rnti) { // provide hard-coded NR configs asn1::dyn_octstring nr_config; @@ -438,14 +468,47 @@ int rrc_nr::ue::handle_sgnb_addition_request() recfg_ies.radio_bearer_cfg_present = true; recfg_ies.radio_bearer_cfg.drb_to_add_mod_list_present = true; - recfg_ies.radio_bearer_cfg.drb_to_release_list.resize(1); - // recfg_ies.radio_bearer_cfg.drb_to_release_list[0].set_eps_bearer_id(5); + recfg_ies.radio_bearer_cfg.drb_to_add_mod_list.resize(1); + + // configure fixed DRB1 + auto& drb_item = recfg_ies.radio_bearer_cfg.drb_to_add_mod_list[0]; + drb_item.drb_id = 1; + drb_item.cn_assoc_present = true; + drb_item.cn_assoc.set_eps_bearer_id() = 5; + drb_item.pdcp_cfg_present = true; + drb_item.pdcp_cfg.ciphering_disabled_present = true; + drb_item.pdcp_cfg.drb_present = true; + drb_item.pdcp_cfg.drb.pdcp_sn_size_dl_present = true; + drb_item.pdcp_cfg.drb.pdcp_sn_size_dl = asn1::rrc_nr::pdcp_cfg_s::drb_s_::pdcp_sn_size_dl_opts::len18bits; + drb_item.pdcp_cfg.drb.pdcp_sn_size_ul_present = true; + drb_item.pdcp_cfg.drb.pdcp_sn_size_ul = asn1::rrc_nr::pdcp_cfg_s::drb_s_::pdcp_sn_size_ul_opts::len18bits; + drb_item.pdcp_cfg.drb.discard_timer_present = true; + drb_item.pdcp_cfg.drb.discard_timer = asn1::rrc_nr::pdcp_cfg_s::drb_s_::discard_timer_opts::ms100; + drb_item.pdcp_cfg.drb.hdr_compress.set_not_used(); + drb_item.pdcp_cfg.t_reordering_present = true; + drb_item.pdcp_cfg.t_reordering = asn1::rrc_nr::pdcp_cfg_s::t_reordering_opts::ms0; + + recfg_ies.radio_bearer_cfg.security_cfg_present = true; + recfg_ies.radio_bearer_cfg.security_cfg.key_to_use_present = true; + recfg_ies.radio_bearer_cfg.security_cfg.key_to_use = asn1::rrc_nr::security_cfg_s::key_to_use_opts::secondary; + recfg_ies.radio_bearer_cfg.security_cfg.security_algorithm_cfg_present = true; + recfg_ies.radio_bearer_cfg.security_cfg.security_algorithm_cfg.ciphering_algorithm = ciphering_algorithm_opts::nea2; + + uint8_t buffer[1024]; + + asn1::bit_ref bref_pack(buffer, sizeof(buffer)); + radio_bearer_cfg_s& radio_bearer_cfg_pack = recfg_ies.radio_bearer_cfg; + if (radio_bearer_cfg_pack.pack(bref_pack) != asn1::SRSASN_SUCCESS) { + parent->logger.error("Failed to pack NR radio bearer config"); + parent->rrc_eutra->sgnb_addition_reject(eutra_rnti); + return SRSRAN_ERROR; + } // TODO: fill configs asn1::dyn_octstring nr_secondary_cell_group_cfg; asn1::dyn_octstring nr_radio_bearer_config; - parent->rrc_eutra->sgnb_addition_ack(rnti, nr_secondary_cell_group_cfg, nr_radio_bearer_config); + parent->rrc_eutra->sgnb_addition_ack(eutra_rnti, nr_secondary_cell_group_cfg, nr_radio_bearer_config); return SRSRAN_SUCCESS; } diff --git a/srsenb/src/stack/rrc/rrc_ue.cc b/srsenb/src/stack/rrc/rrc_ue.cc index b0c60fce6..f53b528ee 100644 --- a/srsenb/src/stack/rrc/rrc_ue.cc +++ b/srsenb/src/stack/rrc/rrc_ue.cc @@ -1158,18 +1158,6 @@ void rrc::ue::update_scells() parent->logger.info("SCells activated for rnti=0x%x", rnti); } -/// EN-DC helper -void rrc::ue::handle_sgnb_addition_ack(const asn1::dyn_octstring& nr_secondary_cell_group_cfg_r15, - const asn1::dyn_octstring& nr_radio_bearer_cfg1_r15) -{ - endc_handler->handle_sgnb_addition_ack(nr_secondary_cell_group_cfg_r15, nr_radio_bearer_cfg1_r15); -} - -void rrc::ue::handle_sgnb_addition_reject() -{ - endc_handler->handle_sgnb_addition_reject(); -} - /********************** HELPERS ***************************/ void rrc::ue::send_dl_ccch(dl_ccch_msg_s* dl_ccch_msg, std::string* octet_str) diff --git a/srsenb/test/common/dummy_classes.h b/srsenb/test/common/dummy_classes.h index 9338f1484..d439a44d1 100644 --- a/srsenb/test/common/dummy_classes.h +++ b/srsenb/test/common/dummy_classes.h @@ -16,7 +16,6 @@ #include "srsran/interfaces/enb_gtpu_interfaces.h" #include "srsran/interfaces/enb_interfaces.h" #include "srsran/interfaces/enb_mac_interfaces.h" -#include "srsran/interfaces/enb_pdcp_interfaces.h" #include "srsran/interfaces/enb_phy_interfaces.h" #include "srsran/interfaces/enb_rlc_interfaces.h" #include "srsran/interfaces/enb_rrc_interfaces.h" @@ -45,45 +44,6 @@ public: uint16_t last_rnti = 70; }; -class rlc_dummy : public rlc_interface_rrc -{ -public: - void clear_buffer(uint16_t rnti) override {} - void add_user(uint16_t rnti) override {} - void rem_user(uint16_t rnti) override {} - void add_bearer(uint16_t rnti, uint32_t lcid, srsran::rlc_config_t cnfg) override {} - void add_bearer_mrb(uint16_t rnti, uint32_t lcid) override {} - void del_bearer(uint16_t rnti, uint32_t lcid) override {} - void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu) override {} - bool has_bearer(uint16_t rnti, uint32_t lcid) override { return false; } - bool suspend_bearer(uint16_t rnti, uint32_t lcid) override { return true; } - bool resume_bearer(uint16_t rnti, uint32_t lcid) override { return true; } - void reestablish(uint16_t rnti) override {} -}; - -class pdcp_dummy : public pdcp_interface_rrc, public pdcp_interface_gtpu -{ -public: - void reset(uint16_t rnti) override {} - void add_user(uint16_t rnti) override {} - void rem_user(uint16_t rnti) override {} - void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu, int pdcp_sn) override {} - void add_bearer(uint16_t rnti, uint32_t lcid, srsran::pdcp_config_t cnfg) override {} - void del_bearer(uint16_t rnti, uint32_t lcid) override {} - void config_security(uint16_t rnti, uint32_t lcid, srsran::as_security_config_t sec_cfg_) override {} - void enable_integrity(uint16_t rnti, uint32_t lcid) override {} - void enable_encryption(uint16_t rnti, uint32_t lcid) override {} - bool get_bearer_state(uint16_t rnti, uint32_t lcid, srsran::pdcp_lte_state_t* state) override { return true; } - bool set_bearer_state(uint16_t rnti, uint32_t lcid, const srsran::pdcp_lte_state_t& state) override { return true; } - void reestablish(uint16_t rnti) override {} - void send_status_report(uint16_t rnti) override {} - void send_status_report(uint16_t rnti, uint32_t lcid) override {} - std::map get_buffered_pdus(uint16_t rnti, uint32_t lcid) override - { - return {}; - } -}; - class s1ap_dummy : public s1ap_interface_rrc { public: diff --git a/srsenb/test/common/dummy_classes_common.h b/srsenb/test/common/dummy_classes_common.h new file mode 100644 index 000000000..f376f672b --- /dev/null +++ b/srsenb/test/common/dummy_classes_common.h @@ -0,0 +1,64 @@ +/** + * + * \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 SRSENB_DUMMY_CLASSES_COMMON_H +#define SRSENB_DUMMY_CLASSES_COMMON_H + +#include "srsran/interfaces/enb_pdcp_interfaces.h" +#include "srsran/interfaces/enb_rlc_interfaces.h" + +namespace srsenb { + +class rlc_dummy : public rlc_interface_rrc +{ +public: + void clear_buffer(uint16_t rnti) override {} + void add_user(uint16_t rnti) override {} + void rem_user(uint16_t rnti) override {} + void add_bearer(uint16_t rnti, uint32_t lcid, srsran::rlc_config_t cnfg) override {} + void add_bearer_mrb(uint16_t rnti, uint32_t lcid) override {} + void del_bearer(uint16_t rnti, uint32_t lcid) override {} + void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu) override { last_sdu = std::move(sdu); } + bool has_bearer(uint16_t rnti, uint32_t lcid) override { return false; } + bool suspend_bearer(uint16_t rnti, uint32_t lcid) override { return true; } + bool resume_bearer(uint16_t rnti, uint32_t lcid) override { return true; } + void reestablish(uint16_t rnti) override {} + + srsran::unique_byte_buffer_t last_sdu; +}; + +class pdcp_dummy : public pdcp_interface_rrc, public pdcp_interface_gtpu +{ +public: + void reset(uint16_t rnti) override {} + void add_user(uint16_t rnti) override {} + void rem_user(uint16_t rnti) override {} + void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu, int pdcp_sn) override {} + void add_bearer(uint16_t rnti, uint32_t lcid, srsran::pdcp_config_t cnfg) override {} + void del_bearer(uint16_t rnti, uint32_t lcid) override {} + void config_security(uint16_t rnti, uint32_t lcid, srsran::as_security_config_t sec_cfg_) override {} + void enable_integrity(uint16_t rnti, uint32_t lcid) override {} + void enable_encryption(uint16_t rnti, uint32_t lcid) override {} + bool get_bearer_state(uint16_t rnti, uint32_t lcid, srsran::pdcp_lte_state_t* state) override { return true; } + bool set_bearer_state(uint16_t rnti, uint32_t lcid, const srsran::pdcp_lte_state_t& state) override { return true; } + void reestablish(uint16_t rnti) override {} + void send_status_report(uint16_t rnti) override {} + void send_status_report(uint16_t rnti, uint32_t lcid) override {} + std::map get_buffered_pdus(uint16_t rnti, uint32_t lcid) override + { + return {}; + } +}; + +} // namespace srsenb + +#endif // SRSENB_DUMMY_CLASSES_COMMON_H diff --git a/srsenb/test/common/dummy_classes_nr.h b/srsenb/test/common/dummy_classes_nr.h new file mode 100644 index 000000000..4237aebe2 --- /dev/null +++ b/srsenb/test/common/dummy_classes_nr.h @@ -0,0 +1,35 @@ +/** + * + * \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_DUMMY_NR_CLASSES_H +#define SRSRAN_DUMMY_NR_CLASSES_H + +#include "srsran/interfaces/gnb_interfaces.h" + +namespace srsenb { + +class mac_dummy : public mac_interface_rrc_nr +{ +public: + int cell_cfg(srsenb::sched_interface::cell_cfg_t* cell_cfg_) + { + cellcfgobj = *cell_cfg_; + return SRSRAN_SUCCESS; + } + uint16_t reserve_rnti() { return 0x4601; } + + srsenb::sched_interface::cell_cfg_t cellcfgobj; +}; + +} // namespace srsenb + +#endif // SRSRAN_DUMMY_NR_CLASSES_H diff --git a/srsenb/test/common/dummy_nr_classes.h b/srsenb/test/common/dummy_nr_classes.h deleted file mode 100644 index 2939c9f18..000000000 --- a/srsenb/test/common/dummy_nr_classes.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * - * \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_DUMMY_NR_CLASSES_H -#define SRSRAN_DUMMY_NR_CLASSES_H - -#include "srsran/interfaces/gnb_interfaces.h" - -namespace srsenb { - -class mac_dummy : public mac_interface_rrc_nr -{ -public: - int cell_cfg(srsenb::sched_interface::cell_cfg_t* cell_cfg_) - { - cellcfgobj = *cell_cfg_; - return SRSRAN_SUCCESS; - } - - srsenb::sched_interface::cell_cfg_t cellcfgobj; -}; - -class rlc_dummy : public rlc_interface_rrc_nr -{ -public: - void clear_buffer(uint16_t rnti) override {} - void add_user(uint16_t rnti) override {} - void rem_user(uint16_t rnti) override {} - void add_bearer(uint16_t rnti, uint32_t lcid, srsran::rlc_config_t cnfg) override {} - void add_bearer_mrb(uint16_t rnti, uint32_t lcid) override {} - void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu) override { last_sdu = std::move(sdu); } - - srsran::unique_byte_buffer_t last_sdu; -}; - -class pdcp_dummy : public pdcp_interface_rrc_nr -{ -public: - void reset(uint16_t rnti) override {} - void add_user(uint16_t rnti) override {} - void rem_user(uint16_t rnti) override {} - void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu) override {} - void add_bearer(uint16_t rnti, uint32_t lcid, srsran::pdcp_config_t cnfg) override {} - void config_security(uint16_t rnti, uint32_t lcid, srsran::as_security_config_t sec_cfg) override {} - void enable_integrity(uint16_t rnti, uint32_t lcid) override {} - void enable_encryption(uint16_t rnti, uint32_t lcid) override {} -}; - -} // namespace srsenb - -#endif // SRSRAN_DUMMY_NR_CLASSES_H diff --git a/srsenb/test/rrc/rrc_nr_test.cc b/srsenb/test/rrc/rrc_nr_test.cc index eb7f68965..3875956f9 100644 --- a/srsenb/test/rrc/rrc_nr_test.cc +++ b/srsenb/test/rrc/rrc_nr_test.cc @@ -11,7 +11,8 @@ */ #include "srsenb/hdr/stack/rrc/rrc_nr.h" -#include "srsenb/test/common/dummy_nr_classes.h" +#include "srsenb/test/common/dummy_classes_common.h" +#include "srsenb/test/common/dummy_classes_nr.h" #include "srsran/common/test_common.h" #include @@ -82,7 +83,8 @@ int test_rrc_setup() for (uint32_t i = 0; i < timeout and rlc_obj.last_sdu == nullptr; ++i) { task_sched.tic(); } - TESTASSERT(rlc_obj.last_sdu != nullptr); + // TODO: trigger proper RRC Setup procedure (not timer based) + // TESTASSERT(rlc_obj.last_sdu != nullptr); } return SRSRAN_SUCCESS; } diff --git a/srsenb/test/rrc/test_helpers.h b/srsenb/test/rrc/test_helpers.h index 1f4923e6d..44d652a96 100644 --- a/srsenb/test/rrc/test_helpers.h +++ b/srsenb/test/rrc/test_helpers.h @@ -15,6 +15,7 @@ #include "srsenb/src/enb_cfg_parser.h" #include "srsenb/test/common/dummy_classes.h" +#include "srsenb/test/common/dummy_classes_common.h" #include "srsran/adt/span.h" using namespace srsenb; diff --git a/srsenb/test/upper/gtpu_test.cc b/srsenb/test/upper/gtpu_test.cc index 2590f1ae1..b33e27867 100644 --- a/srsenb/test/upper/gtpu_test.cc +++ b/srsenb/test/upper/gtpu_test.cc @@ -17,6 +17,7 @@ #include "srsenb/hdr/stack/upper/gtpu.h" #include "srsenb/test/common/dummy_classes.h" +#include "srsenb/test/common/dummy_classes_common.h" #include "srsran/common/network_utils.h" #include "srsran/common/test_common.h" #include "srsran/upper/gtpu.h" diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index 3da1b293f..e7568ab4d 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -17,7 +17,7 @@ #include "dummy_tx_harq_proc.h" #include #include -#include +#include #include #include #include diff --git a/test/phy/dummy_rx_harq_proc.h b/test/phy/dummy_rx_harq_proc.h index 146213e70..77ca5c6fa 100644 --- a/test/phy/dummy_rx_harq_proc.h +++ b/test/phy/dummy_rx_harq_proc.h @@ -14,7 +14,7 @@ #define SRSRAN_DUMMY_RX_HARQ_PROC_H #include -#include +#include #include #include #include diff --git a/test/phy/dummy_tx_harq_proc.h b/test/phy/dummy_tx_harq_proc.h index 19c0138dc..6ae47d873 100644 --- a/test/phy/dummy_tx_harq_proc.h +++ b/test/phy/dummy_tx_harq_proc.h @@ -14,7 +14,7 @@ #define SRSRAN_TX_DUMMY_HARQ_PROC_H #include -#include +#include #include #include #include From a142192d4e8f7d50c36c13234ed58db923a78c0a Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 14 Jul 2021 09:41:25 +0200 Subject: [PATCH 03/34] test_common: handle return value from make_byte_buffer() --- lib/include/srsran/common/test_common.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/include/srsran/common/test_common.h b/lib/include/srsran/common/test_common.h index 19d86f731..76180d184 100644 --- a/lib/include/srsran/common/test_common.h +++ b/lib/include/srsran/common/test_common.h @@ -145,6 +145,10 @@ inline void test_init(int argc, char** argv) inline void copy_msg_to_buffer(unique_byte_buffer_t& pdu, const_byte_span msg) { pdu = srsran::make_byte_buffer(); + if (pdu == nullptr) { + srslog::fetch_basic_logger("ALL").error("Couldn't allocate PDU in %s().", __FUNCTION__); + return; + } memcpy(pdu->msg, msg.data(), msg.size()); pdu->N_bytes = msg.size(); } From 48e42f13a3c24cb348ff81dfe59a9ab116591382 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 14 Jul 2021 09:42:27 +0200 Subject: [PATCH 04/34] mac_nr: only request first 2 SIBs from RRC --- srsenb/src/stack/mac/nr/mac_nr.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/srsenb/src/stack/mac/nr/mac_nr.cc b/srsenb/src/stack/mac/nr/mac_nr.cc index 650b2e7cb..5668ea225 100644 --- a/srsenb/src/stack/mac/nr/mac_nr.cc +++ b/srsenb/src/stack/mac/nr/mac_nr.cc @@ -82,12 +82,16 @@ int mac_nr::cell_cfg(srsenb::sched_interface::cell_cfg_t* cell_cfg) cfg = *cell_cfg; // read SIBs from RRC (SIB1 for now only) - for (int i = 0; i < srsenb::sched_interface::MAX_SIBS; i++) { + for (int i = 0; i < 1 /* srsenb::sched_interface::MAX_SIBS */; i++) { if (cell_cfg->sibs->len > 0) { sib_info_t sib = {}; sib.index = i; sib.periodicity = cell_cfg->sibs->period_rf; sib.payload = srsran::make_byte_buffer(); + if (sib.payload == nullptr) { + logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return SRSRAN_ERROR; + } if (rrc->read_pdu_bcch_dlsch(sib.index, sib.payload) != SRSRAN_SUCCESS) { logger.error("Couldn't read SIB %d from RRC", sib.index); } From b3ab661261ae0a50af24ccff8825857d4483236a Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 14 Jul 2021 09:42:47 +0200 Subject: [PATCH 05/34] rrc_mobility: change log to info when receiving non-EUTRA meas report --- srsenb/src/stack/rrc/rrc_mobility.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsenb/src/stack/rrc/rrc_mobility.cc b/srsenb/src/stack/rrc/rrc_mobility.cc index 475396540..5e285b6f9 100644 --- a/srsenb/src/stack/rrc/rrc_mobility.cc +++ b/srsenb/src/stack/rrc/rrc_mobility.cc @@ -228,7 +228,7 @@ void rrc::ue::rrc_mobility::handle_ue_meas_report(const meas_report_s& msg, srsr } if (meas_res.meas_result_neigh_cells.type().value != meas_results_s::meas_result_neigh_cells_c_::types::meas_result_list_eutra) { - Error("MeasReports regarding non-EUTRA are not supported!"); + Info("Skipping MeasReport for non-EUTRA neighbor."); return; } const meas_id_list& measid_list = rrc_ue->current_ue_cfg.meas_cfg.meas_id_to_add_mod_list; From 921a04ce6542508f843c088e6657cb4f12831508 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 15 Jul 2021 17:39:19 +0200 Subject: [PATCH 06/34] enb,mac_nr: turn UE object into normal std::unique_ptr --- srsenb/hdr/stack/mac/mac_nr.h | 3 ++- srsenb/src/stack/mac/nr/mac_nr.cc | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/srsenb/hdr/stack/mac/mac_nr.h b/srsenb/hdr/stack/mac/mac_nr.h index 1e26415ea..6c54cd4f0 100644 --- a/srsenb/hdr/stack/mac/mac_nr.h +++ b/srsenb/hdr/stack/mac/mac_nr.h @@ -99,7 +99,8 @@ private: // Map of active UEs pthread_rwlock_t rwlock = {}; static const uint16_t FIRST_RNTI = 0x4601; - rnti_map_t > ue_db; + srsran::static_circular_map, SRSENB_MAX_UES> ue_db; + std::atomic ue_counter; // BCH buffers diff --git a/srsenb/src/stack/mac/nr/mac_nr.cc b/srsenb/src/stack/mac/nr/mac_nr.cc index 5668ea225..9a7d275cb 100644 --- a/srsenb/src/stack/mac/nr/mac_nr.cc +++ b/srsenb/src/stack/mac/nr/mac_nr.cc @@ -173,7 +173,7 @@ uint16_t mac_nr::add_ue(uint32_t enb_cc_idx) // Allocate and initialize UE object // TODO: add sched interface - unique_rnti_ptr ue_ptr = make_rnti_obj(rnti, rnti, enb_cc_idx, nullptr, rrc, rlc, phy, logger); + std::unique_ptr ue_ptr = std::unique_ptr(new ue_nr(rnti, enb_cc_idx, nullptr, rrc, rlc, phy, logger)); // Add UE to rnti map srsran::rwlock_write_guard rw_lock(rwlock); From 3f5094f30ebd79f69eac8425f95c1af7446e7795 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 15 Jul 2021 23:11:39 +0200 Subject: [PATCH 07/34] Remove confusing subband_size variable and replace with subband_wideband_ratio --- lib/include/srsran/phy/phch/cqi.h | 1 - lib/src/asn1/rrc_utils.cc | 7 ++++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/include/srsran/phy/phch/cqi.h b/lib/include/srsran/phy/phch/cqi.h index fb2d6b60b..3ae569e30 100644 --- a/lib/include/srsran/phy/phch/cqi.h +++ b/lib/include/srsran/phy/phch/cqi.h @@ -51,7 +51,6 @@ typedef struct { bool ri_idx_present; bool format_is_subband; uint8_t subband_wideband_ratio; ///< K value in TS 36.331. 0 for wideband reporting, (1..4) otherwise - uint32_t subband_size; srsran_cqi_report_mode_t periodic_mode; srsran_cqi_report_mode_t aperiodic_mode; } srsran_cqi_report_cfg_t; diff --git a/lib/src/asn1/rrc_utils.cc b/lib/src/asn1/rrc_utils.cc index 73524624b..3296ea37b 100644 --- a/lib/src/asn1/rrc_utils.cc +++ b/lib/src/asn1/rrc_utils.cc @@ -559,7 +559,8 @@ void set_phy_cfg_t_dedicated_cfg(phy_cfg_t* cfg, const asn1::rrc::phys_cfg_ded_s cqi_report_periodic.cqi_format_ind_periodic_r10.type().value == asn1::rrc::cqi_report_periodic_r10_c::setup_s_::cqi_format_ind_periodic_r10_c_::types::subband_cqi_r10; if (cfg->dl_cfg.cqi_report.format_is_subband) { - cfg->dl_cfg.cqi_report.subband_size = cqi_report_periodic.cqi_format_ind_periodic_r10.subband_cqi_r10().k; + cfg->dl_cfg.cqi_report.subband_wideband_ratio = + cqi_report_periodic.cqi_format_ind_periodic_r10.subband_cqi_r10().k; } if (cqi_report_periodic.ri_cfg_idx_present) { cfg->dl_cfg.cqi_report.ri_idx = cqi_report_periodic.ri_cfg_idx; @@ -586,7 +587,7 @@ void set_phy_cfg_t_dedicated_cfg(phy_cfg_t* cfg, const asn1::rrc::phys_cfg_ded_s asn1_type.cqi_report_cfg.cqi_report_periodic.setup().cqi_format_ind_periodic.type().value == asn1::rrc::cqi_report_periodic_c::setup_s_::cqi_format_ind_periodic_c_::types::subband_cqi; if (cfg->dl_cfg.cqi_report.format_is_subband) { - cfg->dl_cfg.cqi_report.subband_size = + cfg->dl_cfg.cqi_report.subband_wideband_ratio = asn1_type.cqi_report_cfg.cqi_report_periodic.setup().cqi_format_ind_periodic.subband_cqi().k; } if (asn1_type.cqi_report_cfg.cqi_report_periodic.setup().ri_cfg_idx_present) { @@ -862,7 +863,7 @@ void set_phy_cfg_t_scell_config(phy_cfg_t* cfg, const asn1::rrc::scell_to_add_mo cqi_cfg.cqi_format_ind_periodic_r10.type().value == cqi_cfg_t::cqi_format_ind_periodic_r10_c_::types::subband_cqi_r10; if (cfg->dl_cfg.cqi_report.format_is_subband) { - cfg->dl_cfg.cqi_report.subband_size = cqi_cfg.cqi_format_ind_periodic_r10.subband_cqi_r10().k; + cfg->dl_cfg.cqi_report.subband_wideband_ratio = cqi_cfg.cqi_format_ind_periodic_r10.subband_cqi_r10().k; } if (cqi_cfg.ri_cfg_idx_present) { cfg->dl_cfg.cqi_report.ri_idx = cqi_cfg.ri_cfg_idx; From 2e1127f3858b6a39308fa7697b0b56ccb8f74fe7 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 15 Jul 2021 23:58:51 +0200 Subject: [PATCH 08/34] Add sub-band CQI periodicity and configuration to lib --- lib/include/srsran/phy/phch/cqi.h | 7 +++ lib/src/phy/enb/enb_dl.c | 10 +++- lib/src/phy/phch/cqi.c | 83 +++++++++++++++++++++++-------- 3 files changed, 77 insertions(+), 23 deletions(-) diff --git a/lib/include/srsran/phy/phch/cqi.h b/lib/include/srsran/phy/phch/cqi.h index 3ae569e30..2bab78dfc 100644 --- a/lib/include/srsran/phy/phch/cqi.h +++ b/lib/include/srsran/phy/phch/cqi.h @@ -146,11 +146,18 @@ srsran_cqi_value_tostring(srsran_cqi_cfg_t* cfg, srsran_cqi_value_t* value, char SRSRAN_API bool srsran_cqi_periodic_send(const srsran_cqi_report_cfg_t* periodic_cfg, uint32_t tti, srsran_frame_type_t frame_type); +SRSRAN_API bool srsran_cqi_periodic_is_subband(const srsran_cqi_report_cfg_t* cfg, + uint32_t tti, + uint32_t nof_prb, + srsran_frame_type_t frame_type); + SRSRAN_API bool srsran_cqi_periodic_ri_send(const srsran_cqi_report_cfg_t* periodic_cfg, uint32_t tti, srsran_frame_type_t frame_type); SRSRAN_API int srsran_cqi_hl_get_no_subbands(int nof_prb); +SRSRAN_API int srsran_cqi_hl_get_L(int nof_prb); + SRSRAN_API uint8_t srsran_cqi_from_snr(float snr); SRSRAN_API float srsran_cqi_to_coderate(uint32_t cqi, bool use_alt_table); diff --git a/lib/src/phy/enb/enb_dl.c b/lib/src/phy/enb/enb_dl.c index c9b240b2f..5c079aab8 100644 --- a/lib/src/phy/enb/enb_dl.c +++ b/lib/src/phy/enb/enb_dl.c @@ -441,7 +441,15 @@ bool srsran_enb_dl_gen_cqi_periodic(const srsran_cell_t* cell, cqi_cfg->ri_len = srsran_ri_nof_bits(cell); cqi_enabled = true; } else if (srsran_cqi_periodic_send(&dl_cfg->cqi_report, tti, cell->frame_type)) { - cqi_cfg->type = SRSRAN_CQI_TYPE_WIDEBAND; + if (dl_cfg->cqi_report.format_is_subband && + srsran_cqi_periodic_is_subband(&dl_cfg->cqi_report, tti, cell->nof_prb, cell->frame_type)) { + // 36.213 table 7.2.2-1, periodic CQI supports UE-selected only + cqi_cfg->type = SRSRAN_CQI_TYPE_SUBBAND_UE; + cqi_cfg->L = srsran_cqi_hl_get_L(cell->nof_prb); + cqi_cfg->subband_label_2_bits = cqi_cfg->L > 1; + } else { + cqi_cfg->type = SRSRAN_CQI_TYPE_WIDEBAND; + } if (dl_cfg->tm == SRSRAN_TM4) { cqi_cfg->pmi_present = true; cqi_cfg->rank_is_not_one = last_ri > 0; diff --git a/lib/src/phy/phch/cqi.c b/lib/src/phy/phch/cqi.c index 374e50238..d7ef51d34 100644 --- a/lib/src/phy/phch/cqi.c +++ b/lib/src/phy/phch/cqi.c @@ -444,7 +444,7 @@ static bool cqi_get_N_tdd(uint32_t I_cqi_pmi, uint32_t* N_p, uint32_t* N_offset) return true; } -static bool cqi_send(uint32_t I_cqi_pmi, uint32_t tti, bool is_fdd) +static bool cqi_send(uint32_t I_cqi_pmi, uint32_t tti, bool is_fdd, uint32_t H) { uint32_t N_p = 0; @@ -461,7 +461,7 @@ static bool cqi_send(uint32_t I_cqi_pmi, uint32_t tti, bool is_fdd) } if (N_p) { - if ((tti - N_offset) % N_p == 0) { + if ((tti - N_offset) % (H * N_p) == 0) { return true; } } @@ -517,6 +517,51 @@ static bool ri_send(uint32_t I_cqi_pmi, uint32_t I_ri, uint32_t tti, bool is_fdd return false; } +/* Returns the subband size for higher layer-configured subband feedback, + * i.e., the number of RBs per subband as a function of the cell bandwidth + * (Table 7.2.1-3 in TS 36.213) + */ +static int cqi_hl_get_subband_size(int nof_prb) +{ + if (nof_prb < 7) { + return 0; + } else if (nof_prb <= 26) { + return 4; + } else if (nof_prb <= 63) { + return 6; + } else if (nof_prb <= 110) { + return 8; + } else { + return -1; + } +} + +/* Returns the bandwidth parts (J) + * (Table 7.2.2-2 in TS 36.213) + */ +static int cqi_hl_get_bwp_J(int nof_prb) +{ + if (nof_prb < 7) { + return 0; + } else if (nof_prb <= 26) { + return 4; + } else if (nof_prb <= 63) { + return 6; + } else if (nof_prb <= 110) { + return 8; + } else { + return -1; + } +} + +/* Returns the number of bits to index a bandwidth part (L) + * L = ceil(log2(nof_prb/k/J)) + */ +int srsran_cqi_hl_get_L(int nof_prb) +{ + return (int)ceil((float)nof_prb / cqi_hl_get_subband_size(nof_prb) / cqi_hl_get_bwp_J(nof_prb)); +} + bool srsran_cqi_periodic_ri_send(const srsran_cqi_report_cfg_t* cfg, uint32_t tti, srsran_frame_type_t frame_type) { return cfg->periodic_configured && cfg->ri_idx_present && @@ -525,7 +570,20 @@ bool srsran_cqi_periodic_ri_send(const srsran_cqi_report_cfg_t* cfg, uint32_t tt bool srsran_cqi_periodic_send(const srsran_cqi_report_cfg_t* cfg, uint32_t tti, srsran_frame_type_t frame_type) { - return cfg->periodic_configured && cqi_send(cfg->pmi_idx, tti, frame_type == SRSRAN_FDD); + return cfg->periodic_configured && cqi_send(cfg->pmi_idx, tti, frame_type == SRSRAN_FDD, 1); +} + +bool srsran_cqi_periodic_is_subband(const srsran_cqi_report_cfg_t* cfg, + uint32_t tti, + uint32_t nof_prb, + srsran_frame_type_t frame_type) +{ + uint32_t K = cfg->subband_wideband_ratio; + uint32_t J = cqi_hl_get_bwp_J(nof_prb); + uint32_t H = J * K + 1; + + // A periodic report is subband if it's a CQI opportunity and is not wideband + return srsran_cqi_periodic_send(cfg, tti, frame_type) && !cqi_send(cfg->pmi_idx, tti, frame_type == SRSRAN_FDD, H); } // CQI-to-Spectral Efficiency: 36.213 Table 7.2.3-1 @@ -592,25 +650,6 @@ uint8_t srsran_cqi_from_snr(float snr) return 0; } -/* Returns the subband size for higher layer-configured subband feedback, - * i.e., the number of RBs per subband as a function of the cell bandwidth - * (Table 7.2.1-3 in TS 36.213) - */ -static int cqi_hl_get_subband_size(int nof_prb) -{ - if (nof_prb < 7) { - return 0; - } else if (nof_prb <= 26) { - return 4; - } else if (nof_prb <= 63) { - return 6; - } else if (nof_prb <= 110) { - return 8; - } else { - return -1; - } -} - /* Returns the number of subbands to be reported in CQI measurements as * defined in clause 7.2 in TS 36.213, i.e., the N parameter */ From 74d0a8adb8ceb75dbe9a4f1851dc922ebc18466f Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Thu, 15 Jul 2021 12:06:42 +0100 Subject: [PATCH 09/34] sched: add subband cqi info interface to LTE scheduler --- .../srsran/interfaces/enb_mac_interfaces.h | 12 +++++++++++ .../srsran/interfaces/sched_interface.h | 11 +++++----- srsenb/hdr/phy/nr/worker_pool.h | 4 ++++ srsenb/hdr/stack/enb_stack_lte.h | 4 ++++ srsenb/hdr/stack/mac/mac.h | 1 + srsenb/hdr/stack/mac/sched.h | 1 + srsenb/hdr/stack/mac/sched_ue.h | 1 + .../stack/mac/sched_ue_ctrl/sched_ue_cell.h | 3 +++ srsenb/src/stack/mac/mac.cc | 21 +++++++++++++++---- srsenb/src/stack/mac/sched.cc | 7 +++++++ srsenb/src/stack/mac/sched_ue.cc | 11 +++++----- .../stack/mac/sched_ue_ctrl/sched_ue_cell.cc | 21 +++++++++++++++---- srsenb/test/phy/enb_phy_test.cc | 8 +++++++ 13 files changed, 87 insertions(+), 18 deletions(-) diff --git a/lib/include/srsran/interfaces/enb_mac_interfaces.h b/lib/include/srsran/interfaces/enb_mac_interfaces.h index 82fbf2371..9e2ea5673 100644 --- a/lib/include/srsran/interfaces/enb_mac_interfaces.h +++ b/lib/include/srsran/interfaces/enb_mac_interfaces.h @@ -124,6 +124,18 @@ public: */ virtual int cqi_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t cqi_value) = 0; + /** + * PHY callback for giving MAC the Channel Quality information of a given RNTI, TTI, eNb cell/carrier for a specific + * subband + * @param tti the given TTI + * @param rnti the UE identifier in the eNb + * @param cc_idx The eNb Cell/Carrier where the measurement corresponds + * @param sb_idx Index of the Sub-band + * @param cqi_value the corresponding Channel Quality Information + * @return SRSRAN_SUCCESS if no error occurs, SRSRAN_ERROR* if an error occurs + */ + virtual int sb_cqi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t sb_idx, uint32_t cqi_value) = 0; + typedef enum { PUSCH = 0, PUCCH, SRS } ul_channel_t; /** diff --git a/lib/include/srsran/interfaces/sched_interface.h b/lib/include/srsran/interfaces/sched_interface.h index d0e3eefe4..aae980273 100644 --- a/lib/include/srsran/interfaces/sched_interface.h +++ b/lib/include/srsran/interfaces/sched_interface.h @@ -288,11 +288,12 @@ public: virtual int dl_mac_buffer_state(uint16_t rnti, uint32_t ce_code, uint32_t nof_cmds) = 0; /* DL information */ - virtual int dl_ack_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t tb_idx, bool ack) = 0; - virtual int dl_rach_info(uint32_t enb_cc_idx, dl_sched_rar_info_t rar_info) = 0; - virtual int dl_ri_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t ri_value) = 0; - virtual int dl_pmi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t pmi_value) = 0; - virtual int dl_cqi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t cqi_value) = 0; + virtual int dl_ack_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t tb_idx, bool ack) = 0; + virtual int dl_rach_info(uint32_t enb_cc_idx, dl_sched_rar_info_t rar_info) = 0; + virtual int dl_ri_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t ri_value) = 0; + virtual int dl_pmi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t pmi_value) = 0; + virtual int dl_cqi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t cqi_value) = 0; + virtual int dl_sb_cqi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t sb_idx, uint32_t cqi) = 0; /* UL information */ virtual int ul_crc_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, bool crc) = 0; diff --git a/srsenb/hdr/phy/nr/worker_pool.h b/srsenb/hdr/phy/nr/worker_pool.h index 28d8085bb..d246619c6 100644 --- a/srsenb/hdr/phy/nr/worker_pool.h +++ b/srsenb/hdr/phy/nr/worker_pool.h @@ -49,6 +49,10 @@ private: int ri_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t ri_value) override { return 0; } int pmi_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t pmi_value) override { return 0; } int cqi_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t cqi_value) override { return 0; } + int sb_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t sb_idx, uint32_t cqi_value) override + { + return 0; + } int snr_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, float snr_db, ul_channel_t ch) override { return 0; } int ta_info(uint32_t tti, uint16_t rnti, float ta_us) override { return 0; } int ack_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t tb_idx, bool ack) override { return 0; } diff --git a/srsenb/hdr/stack/enb_stack_lte.h b/srsenb/hdr/stack/enb_stack_lte.h index 64e5c4ec7..60871c7d5 100644 --- a/srsenb/hdr/stack/enb_stack_lte.h +++ b/srsenb/hdr/stack/enb_stack_lte.h @@ -66,6 +66,10 @@ public: { return mac.cqi_info(tti, rnti, cc_idx, cqi_value); } + int sb_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t sb_idx, uint32_t cqi_value) final + { + return mac.sb_cqi_info(tti, rnti, cc_idx, sb_idx, cqi_value); + } int snr_info(uint32_t tti_rx, uint16_t rnti, uint32_t cc_idx, float snr_db, ul_channel_t ch) final { return mac.snr_info(tti_rx, rnti, cc_idx, snr_db, ch); diff --git a/srsenb/hdr/stack/mac/mac.h b/srsenb/hdr/stack/mac/mac.h index 23b40a658..0bf5bbc6f 100644 --- a/srsenb/hdr/stack/mac/mac.h +++ b/srsenb/hdr/stack/mac/mac.h @@ -56,6 +56,7 @@ public: int ri_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t ri_value) override; int pmi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t pmi_value) override; int cqi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t cqi_value) override; + int sb_cqi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t sb_idx, uint32_t cqi_value) override; int snr_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, float snr, ul_channel_t ch) override; int ta_info(uint32_t tti, uint16_t rnti, float ta_us) override; int ack_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t tb_idx, bool ack) override; diff --git a/srsenb/hdr/stack/mac/sched.h b/srsenb/hdr/stack/mac/sched.h index 4441a2aca..8aaf1195a 100644 --- a/srsenb/hdr/stack/mac/sched.h +++ b/srsenb/hdr/stack/mac/sched.h @@ -61,6 +61,7 @@ public: int dl_ri_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t ri_value) final; int dl_pmi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t pmi_value) final; int dl_cqi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t cqi_value) final; + int dl_sb_cqi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t sb_idx, uint32_t cqi_value) final; int ul_crc_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, bool crc) final; int ul_sr_info(uint32_t tti, uint16_t rnti) override; int ul_bsr(uint16_t rnti, uint32_t lcg_id, uint32_t bsr) final; diff --git a/srsenb/hdr/stack/mac/sched_ue.h b/srsenb/hdr/stack/mac/sched_ue.h index dadbff6fa..da03a9fc2 100644 --- a/srsenb/hdr/stack/mac/sched_ue.h +++ b/srsenb/hdr/stack/mac/sched_ue.h @@ -60,6 +60,7 @@ public: void set_dl_ri(tti_point tti_rx, uint32_t enb_cc_idx, uint32_t ri); void set_dl_pmi(tti_point tti_rx, uint32_t enb_cc_idx, uint32_t ri); void set_dl_cqi(tti_point tti_rx, uint32_t enb_cc_idx, uint32_t cqi); + void set_dl_sb_cqi(tti_point tti_rx, uint32_t enb_cc_idx, uint32_t sb_idx, uint32_t cqi); int set_ack_info(tti_point tti_rx, uint32_t enb_cc_idx, uint32_t tb_idx, bool ack); void set_ul_crc(tti_point tti_rx, uint32_t enb_cc_idx, bool crc_res); diff --git a/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_ue_cell.h b/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_ue_cell.h index 4c6585ad7..e71e6b8b8 100644 --- a/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_ue_cell.h +++ b/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_ue_cell.h @@ -34,6 +34,7 @@ struct sched_ue_cell { void finish_tti(tti_point tti_rx); int set_dl_wb_cqi(tti_point tti_rx, uint32_t dl_cqi_); + int set_dl_sb_cqi(tti_point tti_rx, uint32_t sb_idx, uint32_t dl_cqi_); bool configured() const { return ue_cc_idx >= 0; } int get_ue_cc_idx() const { return ue_cc_idx; } @@ -80,6 +81,8 @@ struct sched_ue_cell { int fixed_mcs_ul = 0, fixed_mcs_dl = 0; private: + void check_cc_activation(uint32_t dl_cqi); + // args srslog::basic_logger& logger; const sched_interface::ue_cfg_t* ue_cfg = nullptr; diff --git a/srsenb/src/stack/mac/mac.cc b/srsenb/src/stack/mac/mac.cc index ac06e20f4..f9fcd278a 100644 --- a/srsenb/src/stack/mac/mac.cc +++ b/srsenb/src/stack/mac/mac.cc @@ -392,6 +392,19 @@ int mac::cqi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t cqi return SRSRAN_SUCCESS; } +int mac::sb_cqi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t sb_idx, uint32_t cqi_value) +{ + logger.set_context(tti); + srsran::rwlock_read_guard lock(rwlock); + + if (not check_ue_active(rnti)) { + return SRSRAN_ERROR; + } + + scheduler.dl_sb_cqi_info(tti, rnti, enb_cc_idx, sb_idx, cqi_value); + return SRSRAN_SUCCESS; +} + int mac::snr_info(uint32_t tti_rx, uint16_t rnti, uint32_t enb_cc_idx, float snr, ul_channel_t ch) { logger.set_context(tti_rx); @@ -815,9 +828,9 @@ int mac::get_mch_sched(uint32_t tti, bool is_mcch, dl_sched_list_t& dl_sched_res int requested_bytes = (mcs_data.tbs / 8 > (int)mch.mtch_sched[mtch_index].lcid_buffer_size) ? (mch.mtch_sched[mtch_index].lcid_buffer_size) : ((mcs_data.tbs / 8) - 2); - int bytes_received = ue_db[SRSRAN_MRNTI]->read_pdu(current_lcid, mtch_payload_buffer, requested_bytes); - mch.pdu[0].lcid = current_lcid; - mch.pdu[0].nbytes = bytes_received; + int bytes_received = ue_db[SRSRAN_MRNTI]->read_pdu(current_lcid, mtch_payload_buffer, requested_bytes); + mch.pdu[0].lcid = current_lcid; + mch.pdu[0].nbytes = bytes_received; mch.mtch_sched[0].mtch_payload = mtch_payload_buffer; dl_sched_res->pdsch[0].dci.rnti = SRSRAN_MRNTI; if (bytes_received) { @@ -969,7 +982,7 @@ void mac::write_mcch(const srsran::sib2_mbms_t* sib2_, sib2 = *sib2_; sib13 = *sib13_; memcpy(mcch_payload_buffer, mcch_payload, mcch_payload_length * sizeof(uint8_t)); - current_mcch_length = mcch_payload_length; + current_mcch_length = mcch_payload_length; std::unique_ptr ptr = std::unique_ptr{ new ue(SRSRAN_MRNTI, args.nof_prb, &scheduler, rrc_h, rlc_h, phy_h, logger, cells.size(), softbuffer_pool.get())}; auto ret = ue_db.insert(SRSRAN_MRNTI, std::move(ptr)); diff --git a/srsenb/src/stack/mac/sched.cc b/srsenb/src/stack/mac/sched.cc index fc7040163..f55023c23 100644 --- a/srsenb/src/stack/mac/sched.cc +++ b/srsenb/src/stack/mac/sched.cc @@ -209,6 +209,13 @@ int sched::dl_cqi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_ rnti, [tti, enb_cc_idx, cqi_value](sched_ue& ue) { ue.set_dl_cqi(tti_point{tti}, enb_cc_idx, cqi_value); }); } +int sched::dl_sb_cqi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t sb_idx, uint32_t cqi_value) +{ + return ue_db_access_locked(rnti, [tti, enb_cc_idx, cqi_value, sb_idx](sched_ue& ue) { + ue.set_dl_sb_cqi(tti_point{tti}, enb_cc_idx, sb_idx, cqi_value); + }); +} + int sched::dl_rach_info(uint32_t enb_cc_idx, dl_sched_rar_info_t rar_info) { std::lock_guard lock(sched_mutex); diff --git a/srsenb/src/stack/mac/sched_ue.cc b/srsenb/src/stack/mac/sched_ue.cc index 2f269d5b6..0b8f07107 100644 --- a/srsenb/src/stack/mac/sched_ue.cc +++ b/srsenb/src/stack/mac/sched_ue.cc @@ -275,11 +275,12 @@ void sched_ue::set_dl_pmi(tti_point tti_rx, uint32_t enb_cc_idx, uint32_t pmi) void sched_ue::set_dl_cqi(tti_point tti_rx, uint32_t enb_cc_idx, uint32_t cqi) { - if (cells[enb_cc_idx].cc_state() != cc_st::idle) { - cells[enb_cc_idx].set_dl_wb_cqi(tti_rx, cqi); - } else { - logger.warning("Received DL CQI for invalid enb cell index %d", enb_cc_idx); - } + cells[enb_cc_idx].set_dl_wb_cqi(tti_rx, cqi); +} + +void sched_ue::set_dl_sb_cqi(tti_point tti_rx, uint32_t enb_cc_idx, uint32_t sb_idx, uint32_t cqi) +{ + cells[enb_cc_idx].set_dl_sb_cqi(tti_rx, sb_idx, cqi); } void sched_ue::set_ul_snr(tti_point tti_rx, uint32_t enb_cc_idx, float snr, uint32_t ul_ch_code) diff --git a/srsenb/src/stack/mac/sched_ue_ctrl/sched_ue_cell.cc b/srsenb/src/stack/mac/sched_ue_ctrl/sched_ue_cell.cc index c7ba14e42..2f33a85aa 100644 --- a/srsenb/src/stack/mac/sched_ue_ctrl/sched_ue_cell.cc +++ b/srsenb/src/stack/mac/sched_ue_ctrl/sched_ue_cell.cc @@ -165,15 +165,28 @@ void sched_ue_cell::finish_tti(tti_point tti_rx) harq_ent.finish_tti(tti_rx); } -int sched_ue_cell::set_dl_wb_cqi(tti_point tti_rx, uint32_t dl_cqi_) +void sched_ue_cell::check_cc_activation(uint32_t dl_cqi) { - CHECK_VALID_CC("DL CQI"); - dl_cqi_ctxt.cqi_wb_info(tti_rx, dl_cqi_); - if (ue_cc_idx > 0 and cc_state_ == cc_st::activating and dl_cqi_ > 0) { + if (ue_cc_idx > 0 and cc_state_ == cc_st::activating and dl_cqi > 0) { // Wait for SCell to receive a positive CQI before activating it cc_state_ = cc_st::active; logger.info("SCHED: SCell index=%d is now active", ue_cc_idx); } +} + +int sched_ue_cell::set_dl_wb_cqi(tti_point tti_rx, uint32_t dl_cqi_) +{ + CHECK_VALID_CC("DL CQI"); + dl_cqi_ctxt.cqi_wb_info(tti_rx, dl_cqi_); + check_cc_activation(dl_cqi_); + return SRSRAN_SUCCESS; +} + +int sched_ue_cell::set_dl_sb_cqi(tti_point tti_rx, uint32_t sb_idx, uint32_t dl_cqi_) +{ + CHECK_VALID_CC("DL CQI"); + dl_cqi_ctxt.cqi_sb_info(tti_rx, sb_idx, dl_cqi_); + check_cc_activation(dl_cqi_); return SRSRAN_SUCCESS; } diff --git a/srsenb/test/phy/enb_phy_test.cc b/srsenb/test/phy/enb_phy_test.cc index 016aee059..dc497b053 100644 --- a/srsenb/test/phy/enb_phy_test.cc +++ b/srsenb/test/phy/enb_phy_test.cc @@ -283,6 +283,7 @@ private: CALLBACK(ri_info); CALLBACK(pmi_info); CALLBACK(cqi_info); + CALLBACK(sb_cqi_info); CALLBACK(snr_info); CALLBACK(ta_info); CALLBACK(ack_info); @@ -461,6 +462,13 @@ public: return SRSRAN_SUCCESS; } + int sb_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t sb_idx, uint32_t cqi_value) override + { + notify_sb_cqi_info(); + logger.info("Received CQI tti=%d; rnti=0x%x; cc_idx=%d; sb_idx=%d cqi=%d;", tti, rnti, cc_idx, sb_idx, cqi_value); + + return SRSRAN_SUCCESS; + } int snr_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, float snr_db, ul_channel_t ch) override { notify_snr_info(); From e6683b7387455ff3fd90732808cb43accad42e66 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 16 Jul 2021 11:05:18 +0100 Subject: [PATCH 10/34] sched,nr: simplify scheduler threading architecture to reflect the new cc-based parallelism model --- srsenb/hdr/stack/mac/nr/sched_nr.h | 7 +- .../nr/{sched_nr_bwp.h => sched_nr_cell.h} | 21 +- srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 4 +- srsenb/hdr/stack/mac/nr/sched_nr_ue.h | 50 ++--- srsenb/hdr/stack/mac/nr/sched_nr_worker.h | 69 ++++-- srsenb/src/stack/mac/nr/CMakeLists.txt | 2 +- srsenb/src/stack/mac/nr/sched_nr.cc | 99 ++------- .../nr/{sched_nr_bwp.cc => sched_nr_cell.cc} | 9 +- srsenb/src/stack/mac/nr/sched_nr_ue.cc | 52 ++--- srsenb/src/stack/mac/nr/sched_nr_worker.cc | 199 +++++++++++------- srsenb/test/mac/nr/sched_nr_test.cc | 61 +----- 11 files changed, 254 insertions(+), 319 deletions(-) rename srsenb/hdr/stack/mac/nr/{sched_nr_bwp.h => sched_nr_cell.h} (75%) rename srsenb/src/stack/mac/nr/{sched_nr_bwp.cc => sched_nr_cell.cc} (94%) diff --git a/srsenb/hdr/stack/mac/nr/sched_nr.h b/srsenb/hdr/stack/mac/nr/sched_nr.h index d99b702ca..731897fbe 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr.h @@ -27,7 +27,7 @@ namespace srsenb { namespace sched_nr_impl { class sched_worker_manager; -class serv_cell_ctxt; +class serv_cell_manager; } // namespace sched_nr_impl class ue_event_manager; @@ -62,14 +62,11 @@ private: std::mutex ue_db_mutex; ue_map_t ue_db; - // management of UE feedback - std::unique_ptr pending_events; - // management of Sched Result buffering std::unique_ptr pending_results; // management of cell resources - std::vector > cells; + std::vector > cells; }; } // namespace srsenb diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_bwp.h b/srsenb/hdr/stack/mac/nr/sched_nr_cell.h similarity index 75% rename from srsenb/hdr/stack/mac/nr/sched_nr_bwp.h rename to srsenb/hdr/stack/mac/nr/sched_nr_cell.h index 252ee6f26..f65323f12 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_bwp.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_cell.h @@ -10,8 +10,8 @@ * */ -#ifndef SRSRAN_SCHED_NR_BWP_H -#define SRSRAN_SCHED_NR_BWP_H +#ifndef SRSRAN_SCHED_NR_CELL_H +#define SRSRAN_SCHED_NR_CELL_H #include "sched_nr_cfg.h" #include "sched_nr_rb_grid.h" @@ -62,17 +62,26 @@ public: bwp_res_grid grid; }; -class serv_cell_ctxt +class serv_cell_manager { public: + using feedback_callback_t = srsran::move_callback; + + explicit serv_cell_manager(const sched_cell_params& cell_cfg_); + + void add_user(uint16_t rnti, ue_carrier* ue); + void rem_user(uint16_t rnti); + srsran::bounded_vector bwps; + const sched_cell_params& cfg; - explicit serv_cell_ctxt(const sched_cell_params& cell_cfg_); + srsran::static_circular_map ues; - const sched_cell_params* cfg; +private: + srslog::basic_logger& logger; }; } // namespace sched_nr_impl } // namespace srsenb -#endif // SRSRAN_SCHED_NR_BWP_H +#endif // SRSRAN_SCHED_NR_CELL_H diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index bf68f3684..44e140ddf 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -63,9 +63,7 @@ public: srsran::bounded_vector bwps{1}; // idx0 for BWP-common }; - struct sched_cfg_t { - uint32_t nof_concurrent_subframes = 1; - }; + struct sched_cfg_t {}; struct ue_cc_cfg_t { bool active = false; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h index 97ece0a45..53e11dc44 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h @@ -30,41 +30,37 @@ class slot_ue { public: slot_ue() = default; - explicit slot_ue(resource_guard::token ue_token, uint16_t rnti_, tti_point tti_rx_, uint32_t cc); + explicit slot_ue(uint16_t rnti_, tti_point tti_rx_, uint32_t cc); slot_ue(slot_ue&&) noexcept = default; slot_ue& operator=(slot_ue&&) noexcept = default; - bool empty() const { return ue_token.empty(); } - void release() { ue_token.release(); } + bool empty() const { return rnti == SCHED_NR_INVALID_RNTI; } + void release() { rnti = SCHED_NR_INVALID_RNTI; } uint16_t rnti = SCHED_NR_INVALID_RNTI; tti_point tti_rx; uint32_t cc = SCHED_NR_MAX_CARRIERS; // UE parameters common to all sectors - const bwp_ue_cfg* cfg = nullptr; - bool pending_sr; + bool pending_sr; // UE parameters that are sector specific - const ue_cc_cfg_t* cc_cfg = nullptr; - tti_point pdcch_tti; - tti_point pdsch_tti; - tti_point pusch_tti; - tti_point uci_tti; - uint32_t dl_cqi; - uint32_t ul_cqi; - dl_harq_proc* h_dl = nullptr; - harq_proc* h_ul = nullptr; - -private: - resource_guard::token ue_token; + const bwp_ue_cfg* cfg = nullptr; + tti_point pdcch_tti; + tti_point pdsch_tti; + tti_point pusch_tti; + tti_point uci_tti; + uint32_t dl_cqi; + uint32_t ul_cqi; + dl_harq_proc* h_dl = nullptr; + harq_proc* h_ul = nullptr; }; class ue_carrier { public: ue_carrier(uint16_t rnti, const ue_cfg_t& cfg, const sched_cell_params& cell_params_); - slot_ue try_reserve(tti_point pdcch_tti, const ue_cfg_t& cfg); - void push_feedback(srsran::move_callback callback); + void new_tti(tti_point pdcch_tti, const ue_cfg_t& uecfg_); + slot_ue try_reserve(tti_point pdcch_tti); const uint16_t rnti; const uint32_t cc; @@ -78,11 +74,6 @@ public: private: bwp_ue_cfg bwp_cfg; const sched_cell_params& cell_params; - - resource_guard busy; - tti_point last_tti_rx; - - srsran::deque > pending_feedback; }; class ue @@ -90,12 +81,16 @@ class ue public: ue(uint16_t rnti, const ue_cfg_t& cfg, const sched_params& sched_cfg_); - slot_ue try_reserve(tti_point tti_rx, uint32_t cc); + slot_ue try_reserve(tti_point pdcch_tti, uint32_t cc); - void set_cfg(const ue_cfg_t& cfg); + void set_cfg(const ue_cfg_t& cfg); + const ue_cfg_t& cfg() const { return ue_cfg; } void ul_sr_info(tti_point tti_rx) { pending_sr = true; } + bool has_ca() const { return ue_cfg.carriers.size() > 1; } + uint32_t pcell_cc() const { return ue_cfg.carriers[0].cc; } + std::array, SCHED_NR_MAX_CARRIERS> carriers; private: @@ -104,8 +99,7 @@ private: bool pending_sr = false; - int current_idx = 0; - std::array ue_cfgs; + ue_cfg_t ue_cfg; }; using ue_map_t = srsran::static_circular_map, SCHED_NR_MAX_USERS>; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h index 0548dedef..bd39285e6 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h @@ -13,7 +13,7 @@ #ifndef SRSRAN_SCHED_NR_WORKER_H #define SRSRAN_SCHED_NR_WORKER_H -#include "sched_nr_bwp.h" +#include "sched_nr_cell.h" #include "sched_nr_cfg.h" #include "sched_nr_rb_grid.h" #include "sched_nr_ue.h" @@ -33,25 +33,41 @@ using ul_sched_t = sched_nr_interface::ul_sched_t; class slot_cc_worker { public: - explicit slot_cc_worker(serv_cell_ctxt& sched); + using feedback_callback_t = srsran::move_callback; - void start(tti_point tti_rx_, ue_map_t& ue_db_); + explicit slot_cc_worker(serv_cell_manager& sched); + + void start(tti_point pdcch_tti, ue_map_t& ue_db_); void run(); - void end_tti(); + void finish(); bool running() const { return tti_rx.is_valid(); } + /// Enqueue feedback directed at a given UE in a given cell + void enqueue_cc_feedback(uint16_t rnti, feedback_callback_t fdbk); + private: + /// Run all pending feedback. This should be called at the beginning of a TTI + void run_feedback(ue_map_t& ue_db); + void alloc_dl_ues(); void alloc_ul_ues(); void log_result() const; const sched_cell_params& cfg; - serv_cell_ctxt& cell; + serv_cell_manager& cell; srslog::basic_logger& logger; tti_point tti_rx; bwp_slot_allocator bwp_alloc; + // Process of UE cell-specific feedback + struct feedback_t { + uint16_t rnti; + feedback_callback_t fdbk; + }; + std::mutex feedback_mutex; + srsran::deque pending_feedback, tmp_feedback_to_run; + srsran::static_circular_map slot_ues; }; @@ -67,28 +83,49 @@ class sched_worker_manager }; public: - explicit sched_worker_manager(ue_map_t& ue_db_, const sched_params& cfg_); + explicit sched_worker_manager(ue_map_t& ue_db_, + const sched_params& cfg_, + srsran::span > cells_); sched_worker_manager(const sched_worker_manager&) = delete; sched_worker_manager(sched_worker_manager&&) = delete; ~sched_worker_manager(); - void start_slot(tti_point tti_rx, srsran::move_callback process_feedback); - bool run_slot(tti_point tti_rx, uint32_t cc); - void release_slot(tti_point tti_rx); + void run_slot(tti_point tti_tx, uint32_t cc); bool save_sched_result(tti_point pdcch_tti, uint32_t cc, dl_sched_t& dl_res, ul_sched_t& ul_res); -private: - const sched_params& cfg; - ue_map_t& ue_db; - srslog::basic_logger& logger; + void enqueue_event(uint16_t rnti, srsran::move_callback ev); + void enqueue_cc_feedback(uint16_t rnti, uint32_t cc, slot_cc_worker::feedback_callback_t fdbk) + { + cc_worker_list[cc]->worker.enqueue_cc_feedback(rnti, std::move(fdbk)); + } - std::mutex ue_db_mutex; +private: + const sched_params& cfg; + ue_map_t& ue_db; + srsran::span > cells; + srslog::basic_logger& logger; + + struct ue_event_t { + uint16_t rnti; + srsran::move_callback callback; + }; + std::mutex event_mutex; + srsran::deque next_slot_events, slot_events; std::vector > slot_worker_ctxts; + struct cc_context { + std::condition_variable cvar; + bool waiting = false; + slot_cc_worker worker; - srsran::bounded_vector cell_grid_list; + cc_context(serv_cell_manager& sched) : worker(sched) {} + }; - slot_worker_ctxt& get_sf(tti_point tti_rx); + std::mutex slot_mutex; + std::condition_variable cvar; + tti_point current_tti; + std::atomic worker_count{0}; // variable shared across slot_cc_workers + std::vector > cc_worker_list; }; } // namespace sched_nr_impl diff --git a/srsenb/src/stack/mac/nr/CMakeLists.txt b/srsenb/src/stack/mac/nr/CMakeLists.txt index 85091bd35..4602c4f73 100644 --- a/srsenb/src/stack/mac/nr/CMakeLists.txt +++ b/srsenb/src/stack/mac/nr/CMakeLists.txt @@ -16,7 +16,7 @@ set(SOURCES mac_nr.cc sched_nr_pdcch.cc sched_nr_cfg.cc sched_nr_helpers.cc - sched_nr_bwp.cc + sched_nr_cell.cc sched_nr_rb.cc harq_softbuffer.cc) diff --git a/srsenb/src/stack/mac/nr/sched_nr.cc b/srsenb/src/stack/mac/nr/sched_nr.cc index 0b6ed58e7..3311942f2 100644 --- a/srsenb/src/stack/mac/nr/sched_nr.cc +++ b/srsenb/src/stack/mac/nr/sched_nr.cc @@ -12,7 +12,7 @@ #include "srsenb/hdr/stack/mac/nr/sched_nr.h" #include "srsenb/hdr/stack/mac/nr/harq_softbuffer.h" -#include "srsenb/hdr/stack/mac/nr/sched_nr_bwp.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr_cell.h" #include "srsenb/hdr/stack/mac/nr/sched_nr_worker.h" #include "srsran/common/thread_pool.h" @@ -22,62 +22,6 @@ using namespace sched_nr_impl; static int assert_ue_cfg_valid(uint16_t rnti, const sched_nr_interface::ue_cfg_t& uecfg); -class ue_event_manager -{ - using callback_t = srsran::move_callback; - using callback_list = srsran::deque; - -public: - explicit ue_event_manager(ue_map_t& ue_db_) : ue_db(ue_db_) {} - - void push_event(srsran::move_callback event) - { - std::lock_guard lock(common_mutex); - common_events.push_back(std::move(event)); - } - void push_cc_feedback(uint16_t rnti, uint32_t cc, srsran::move_callback event) - { - std::lock_guard lock(common_mutex); - feedback_list.emplace_back(); - feedback_list.back().rnti = rnti; - feedback_list.back().cc = cc; - feedback_list.back().callback = std::move(event); - } - void new_slot() - { - { - std::lock_guard lock(common_mutex); - common_events.swap(common_events_tmp); // reuse memory - feedback_list.swap(feedback_list_tmp); - } - while (not common_events_tmp.empty()) { - common_events_tmp.front()(); - common_events_tmp.pop_front(); - } - while (not feedback_list_tmp.empty()) { - auto& e = feedback_list_tmp.front(); - if (ue_db.contains(e.rnti) and ue_db[e.rnti]->carriers[e.cc] != nullptr) { - ue_db[e.rnti]->carriers[e.cc]->push_feedback(std::move(e.callback)); - } - feedback_list_tmp.pop_front(); - } - } - -private: - ue_map_t& ue_db; - - std::mutex common_mutex; - callback_list common_events; - struct ue_feedback { - uint16_t rnti = SCHED_NR_INVALID_RNTI; - uint32_t cc = SCHED_NR_MAX_CARRIERS; - srsran::move_callback callback; - }; - srsran::deque feedback_list; - callback_list common_events_tmp; - srsran::deque feedback_list_tmp; -}; - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class sched_result_manager @@ -142,21 +86,26 @@ private: /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -sched_nr::sched_nr(const sched_cfg_t& sched_cfg) : - cfg(sched_cfg), pending_events(new ue_event_manager(ue_db)), logger(srslog::fetch_basic_logger("MAC")) -{} +sched_nr::sched_nr(const sched_cfg_t& sched_cfg) : cfg(sched_cfg), logger(srslog::fetch_basic_logger("MAC")) {} sched_nr::~sched_nr() {} int sched_nr::cell_cfg(srsran::const_span cell_list) { + // Initiate Common Sched Configuration cfg.cells.reserve(cell_list.size()); for (uint32_t cc = 0; cc < cell_list.size(); ++cc) { cfg.cells.emplace_back(cc, cell_list[cc], cfg.sched_cfg); } + // Initiate cell-specific schedulers + cells.reserve(cell_list.size()); + for (uint32_t cc = 0; cc < cell_list.size(); ++cc) { + cells.emplace_back(new serv_cell_manager{cfg.cells[cc]}); + } + pending_results.reset(new sched_result_manager(cell_list.size())); - sched_workers.reset(new sched_nr_impl::sched_worker_manager(ue_db, cfg)); + sched_workers.reset(new sched_nr_impl::sched_worker_manager(ue_db, cfg, cells)); return SRSRAN_SUCCESS; } @@ -164,7 +113,7 @@ int sched_nr::cell_cfg(srsran::const_span cell_list) void sched_nr::ue_cfg(uint16_t rnti, const ue_cfg_t& uecfg) { srsran_assert(assert_ue_cfg_valid(rnti, uecfg) == SRSRAN_SUCCESS, "Invalid UE configuration"); - pending_events->push_event([this, rnti, uecfg]() { ue_cfg_impl(rnti, uecfg); }); + sched_workers->enqueue_event(rnti, [this, rnti, uecfg]() { ue_cfg_impl(rnti, uecfg); }); } void sched_nr::ue_cfg_impl(uint16_t rnti, const ue_cfg_t& uecfg) @@ -179,22 +128,8 @@ void sched_nr::ue_cfg_impl(uint16_t rnti, const ue_cfg_t& uecfg) /// Generate {tti,cc} scheduling decision int sched_nr::generate_slot_result(tti_point pdcch_tti, uint32_t cc) { - tti_point tti_rx = pdcch_tti - TX_ENB_DELAY; - - // Lock carrier workers for provided tti_rx - sched_workers->start_slot(tti_rx, [this]() { - // In case it is first worker for the given slot - // synchronize {tti,cc} state. e.g. reserve UE resources for {tti,cc} decision, process feedback - pending_events->new_slot(); - }); - - // unlocked, parallel region - bool all_workers_finished = sched_workers->run_slot(tti_rx, cc); - - if (all_workers_finished) { - // once all workers of the same subframe finished, synchronize sched outcome with ue_db - sched_workers->release_slot(tti_rx); - } + // Generate {slot_idx,cc} result + sched_workers->run_slot(pdcch_tti, cc); // Copy results to intermediate buffer dl_sched_t& dl_res = pending_results->add_dl_result(pdcch_tti, cc); @@ -225,17 +160,13 @@ int sched_nr::get_ul_sched(tti_point tti_rx, uint32_t cc, ul_sched_t& result) void sched_nr::dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) { - pending_events->push_cc_feedback( + sched_workers->enqueue_cc_feedback( rnti, cc, [pid, tb_idx, ack](ue_carrier& ue_cc) { ue_cc.harq_ent.dl_ack_info(pid, tb_idx, ack); }); } void sched_nr::ul_sr_info(tti_point tti_rx, uint16_t rnti) { - pending_events->push_event([this, rnti, tti_rx]() { - if (ue_db.contains(rnti)) { - ue_db[rnti]->ul_sr_info(tti_rx); - } - }); + sched_workers->enqueue_event(rnti, [this, rnti, tti_rx]() { ue_db[rnti]->ul_sr_info(tti_rx); }); } #define VERIFY_INPUT(cond, msg, ...) \ diff --git a/srsenb/src/stack/mac/nr/sched_nr_bwp.cc b/srsenb/src/stack/mac/nr/sched_nr_cell.cc similarity index 94% rename from srsenb/src/stack/mac/nr/sched_nr_bwp.cc rename to srsenb/src/stack/mac/nr/sched_nr_cell.cc index 03f7c314b..b30970237 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_bwp.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_cell.cc @@ -10,7 +10,7 @@ * */ -#include "srsenb/hdr/stack/mac/nr/sched_nr_bwp.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr_cell.h" #include "srsran/common/standard_streams.h" #include "srsran/common/string_helpers.h" @@ -147,14 +147,15 @@ bwp_ctxt::bwp_ctxt(const bwp_params& bwp_cfg) : cfg(&bwp_cfg), ra(bwp_cfg), grid ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -serv_cell_ctxt::serv_cell_ctxt(const sched_cell_params& cell_cfg_) : cfg(&cell_cfg_) +serv_cell_manager::serv_cell_manager(const sched_cell_params& cell_cfg_) : + cfg(cell_cfg_), logger(srslog::fetch_basic_logger("MAC")) { - for (uint32_t bwp_id = 0; bwp_id < cfg->cell_cfg.bwps.size(); ++bwp_id) { + for (uint32_t bwp_id = 0; bwp_id < cfg.cell_cfg.bwps.size(); ++bwp_id) { bwps.emplace_back(cell_cfg_.bwps[bwp_id]); } // Pre-allocate HARQs in common pool of softbuffers - harq_softbuffer_pool::get_instance().init_pool(cfg->nof_prb()); + harq_softbuffer_pool::get_instance().init_pool(cfg.nof_prb()); } } // namespace sched_nr_impl diff --git a/srsenb/src/stack/mac/nr/sched_nr_ue.cc b/srsenb/src/stack/mac/nr/sched_nr_ue.cc index 3daa087f0..bf408ec00 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_ue.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_ue.cc @@ -16,9 +16,7 @@ namespace srsenb { namespace sched_nr_impl { -slot_ue::slot_ue(resource_guard::token ue_token_, uint16_t rnti_, tti_point tti_rx_, uint32_t cc_) : - ue_token(std::move(ue_token_)), rnti(rnti_), tti_rx(tti_rx_), cc(cc_) -{} +slot_ue::slot_ue(uint16_t rnti_, tti_point tti_rx_, uint32_t cc_) : rnti(rnti_), tti_rx(tti_rx_), cc(cc_) {} /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -30,40 +28,22 @@ ue_carrier::ue_carrier(uint16_t rnti_, const ue_cfg_t& uecfg_, const sched_cell_ harq_ent(cell_params_.nof_prb()) {} -void ue_carrier::push_feedback(srsran::move_callback callback) -{ - pending_feedback.push_back(std::move(callback)); -} - -slot_ue ue_carrier::try_reserve(tti_point tti_rx, const ue_cfg_t& uecfg_) +void ue_carrier::new_tti(tti_point pdcch_tti, const ue_cfg_t& uecfg_) { - slot_ue sfu(busy, rnti, tti_rx, cc); - if (sfu.empty()) { - return sfu; - } - // successfully acquired. Process any CC-specific pending feedback if (bwp_cfg.ue_cfg() != &uecfg_) { bwp_cfg = bwp_ue_cfg(rnti, cell_params.bwps[0], uecfg_); } - while (not pending_feedback.empty()) { - pending_feedback.front()(*this); - pending_feedback.pop_front(); - } - if (not last_tti_rx.is_valid()) { - last_tti_rx = tti_rx; - harq_ent.new_tti(tti_rx); - } else { - while (last_tti_rx++ < tti_rx) { - harq_ent.new_tti(tti_rx); - } - } + harq_ent.new_tti(pdcch_tti - TX_ENB_DELAY); +} - // set UE parameters common to all carriers - sfu.cfg = &bwp_cfg; +slot_ue ue_carrier::try_reserve(tti_point pdcch_tti) +{ + tti_point tti_rx = pdcch_tti - TX_ENB_DELAY; // copy cc-specific parameters and find available HARQs - sfu.cc_cfg = &uecfg_.carriers[cc]; - sfu.pdcch_tti = tti_rx + TX_ENB_DELAY; + slot_ue sfu(rnti, tti_rx, cc); + sfu.cfg = &bwp_cfg; + sfu.pdcch_tti = pdcch_tti; const uint32_t k0 = 0; sfu.pdsch_tti = sfu.pdcch_tti + k0; uint32_t k1 = @@ -100,9 +80,9 @@ slot_ue ue_carrier::try_reserve(tti_point tti_rx, const ue_cfg_t& uecfg_) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -ue::ue(uint16_t rnti_, const ue_cfg_t& cfg, const sched_params& sched_cfg_) : rnti(rnti_), sched_cfg(sched_cfg_) +ue::ue(uint16_t rnti_, const ue_cfg_t& cfg, const sched_params& sched_cfg_) : + rnti(rnti_), sched_cfg(sched_cfg_), ue_cfg(cfg) { - ue_cfgs[0] = cfg; for (uint32_t cc = 0; cc < cfg.carriers.size(); ++cc) { if (cfg.carriers[cc].active) { carriers[cc].reset(new ue_carrier(rnti, cfg, sched_cfg.cells[cc])); @@ -112,19 +92,19 @@ ue::ue(uint16_t rnti_, const ue_cfg_t& cfg, const sched_params& sched_cfg_) : rn void ue::set_cfg(const ue_cfg_t& cfg) { - current_idx = (current_idx + 1U) % ue_cfgs.size(); - ue_cfgs[current_idx] = ue_cfg_extended(rnti, cfg); + ue_cfg = cfg; } -slot_ue ue::try_reserve(tti_point tti_rx, uint32_t cc) +slot_ue ue::try_reserve(tti_point pdcch_tti, uint32_t cc) { if (carriers[cc] == nullptr) { return slot_ue(); } - slot_ue sfu = carriers[cc]->try_reserve(tti_rx, ue_cfgs[current_idx]); + slot_ue sfu = carriers[cc]->try_reserve(pdcch_tti); if (sfu.empty()) { return slot_ue(); } + // set UE-common parameters sfu.pending_sr = pending_sr; diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index 80ba1ed46..283bd5d9f 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -16,24 +16,57 @@ namespace srsenb { namespace sched_nr_impl { -slot_cc_worker::slot_cc_worker(serv_cell_ctxt& cc_sched) : - cell(cc_sched), cfg(*cc_sched.cfg), bwp_alloc(cc_sched.bwps[0].grid), logger(srslog::fetch_basic_logger("MAC")) +slot_cc_worker::slot_cc_worker(serv_cell_manager& cc_sched) : + cell(cc_sched), cfg(cc_sched.cfg), bwp_alloc(cc_sched.bwps[0].grid), logger(srslog::fetch_basic_logger("MAC")) {} +void slot_cc_worker::enqueue_cc_feedback(uint16_t rnti, feedback_callback_t fdbk) +{ + std::lock_guard lock(feedback_mutex); + pending_feedback.emplace_back(); + pending_feedback.back().rnti = rnti; + pending_feedback.back().fdbk = std::move(fdbk); +} + +void slot_cc_worker::run_feedback(ue_map_t& ue_db) +{ + { + std::lock_guard lock(feedback_mutex); + tmp_feedback_to_run.swap(pending_feedback); + } + + for (feedback_t& f : tmp_feedback_to_run) { + if (ue_db.contains(f.rnti) and ue_db[f.rnti]->carriers[cfg.cc] != nullptr) { + f.fdbk(*ue_db[f.rnti]->carriers[cfg.cc]); + } else { + logger.warning("SCHED: feedback received for invalid rnti=0x%x, cc=%d", f.rnti, cfg.cc); + } + } + tmp_feedback_to_run.clear(); +} + /// Called at the beginning of TTI in a locked context, to reserve available UE resources -void slot_cc_worker::start(tti_point tti_rx_, ue_map_t& ue_db) +void slot_cc_worker::start(tti_point pdcch_tti, ue_map_t& ue_db) { srsran_assert(not running(), "scheduler worker::start() called for active worker"); - tti_rx = tti_rx_; + tti_rx = pdcch_tti - TX_ENB_DELAY; - // Try reserve UE cells for this worker + // Run pending cell feedback + run_feedback(ue_db); + + // Reserve UEs for this worker slot for (auto& ue_pair : ue_db) { uint16_t rnti = ue_pair.first; ue& u = *ue_pair.second; + if (u.carriers[cfg.cc] == nullptr) { + continue; + } - slot_ues.insert(rnti, u.try_reserve(tti_rx, cfg.cc)); + u.carriers[cfg.cc]->new_tti(pdcch_tti, u.cfg()); + + slot_ues.insert(rnti, u.try_reserve(pdcch_tti, cfg.cc)); if (slot_ues[rnti].empty()) { - // Failed to synchronize because UE is being used by another worker + // Failed to generate slot UE because UE has no conditions for DL/UL tx slot_ues.erase(rnti); continue; } @@ -56,18 +89,17 @@ void slot_cc_worker::run() // Log CC scheduler result log_result(); -} - -void slot_cc_worker::end_tti() -{ - srsran_assert(running(), "scheduler worker::end() called for non-active worker"); // releases UE resources slot_ues.clear(); - tti_rx = {}; } +void slot_cc_worker::finish() +{ + // synchronize results +} + void slot_cc_worker::alloc_dl_ues() { if (slot_ues.empty()) { @@ -108,7 +140,7 @@ void slot_cc_worker::log_result() const fmt::format_to(fmtbuf, "SCHED: DL {}, cc={}, rnti=0x{:x}, pid={}, nrtx={}, dai={}, tti_pdsch={}, tti_ack={}", ue.h_dl->nof_retx() == 0 ? "tx" : "retx", - cell.cfg->cc, + cell.cfg.cc, ue.rnti, ue.h_dl->pid, ue.h_dl->nof_retx(), @@ -116,7 +148,7 @@ void slot_cc_worker::log_result() const ue.pdsch_tti, ue.uci_tti); } else if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_ra) { - fmt::format_to(fmtbuf, "SCHED: DL RAR, cc={}", cell.cfg->cc); + fmt::format_to(fmtbuf, "SCHED: DL RAR, cc={}", cell.cfg.cc); } else { fmt::format_to(fmtbuf, "SCHED: unknown format"); } @@ -127,105 +159,112 @@ void slot_cc_worker::log_result() const /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -sched_worker_manager::sched_worker_manager(ue_map_t& ue_db_, const sched_params& cfg_) : - cfg(cfg_), ue_db(ue_db_), logger(srslog::fetch_basic_logger("MAC")) +sched_worker_manager::sched_worker_manager(ue_map_t& ue_db_, + const sched_params& cfg_, + srsran::span > cells_) : + cfg(cfg_), ue_db(ue_db_), logger(srslog::fetch_basic_logger("MAC")), cells(cells_) { + cc_worker_list.reserve(cfg.cells.size()); for (uint32_t cc = 0; cc < cfg.cells.size(); ++cc) { - cell_grid_list.emplace_back(cfg.cells[cc]); - } - - // Note: For now, we only allow parallelism at the sector level - slot_worker_ctxts.resize(cfg.sched_cfg.nof_concurrent_subframes); - for (size_t i = 0; i < cfg.sched_cfg.nof_concurrent_subframes; ++i) { - slot_worker_ctxts[i].reset(new slot_worker_ctxt()); - slot_worker_ctxts[i]->workers.reserve(cfg.cells.size()); - for (uint32_t cc = 0; cc < cfg.cells.size(); ++cc) { - slot_worker_ctxts[i]->workers.emplace_back(cell_grid_list[cc]); - } + cc_worker_list.emplace_back(new cc_context{*cells[cc]}); } } sched_worker_manager::~sched_worker_manager() = default; -sched_worker_manager::slot_worker_ctxt& sched_worker_manager::get_sf(tti_point tti_rx) +void sched_worker_manager::enqueue_event(uint16_t rnti, srsran::move_callback ev) { - return *slot_worker_ctxts[tti_rx.to_uint() % slot_worker_ctxts.size()]; + std::lock_guard lock(event_mutex); + next_slot_events.push_back(ue_event_t{rnti, std::move(ev)}); } -void sched_worker_manager::start_slot(tti_point tti_rx, srsran::move_callback process_feedback) +void sched_worker_manager::run_slot(tti_point tti_tx, uint32_t cc) { - auto& sf_worker_ctxt = get_sf(tti_rx); - - std::unique_lock lock(sf_worker_ctxt.slot_mutex); - while ((sf_worker_ctxt.tti_rx.is_valid() and sf_worker_ctxt.tti_rx != tti_rx)) { - // wait for previous slot to finish - sf_worker_ctxt.nof_workers_waiting++; - sf_worker_ctxt.cvar.wait(lock); - sf_worker_ctxt.nof_workers_waiting--; - } - if (sf_worker_ctxt.tti_rx == tti_rx) { - // another worker with the same slot idx already started - return; - } - + srsran::bounded_vector waiting_cvars; { - std::lock_guard db_lock(ue_db_mutex); - - process_feedback(); + std::unique_lock lock(slot_mutex); + while (current_tti.is_valid() and current_tti != tti_tx) { + // Wait for previous slot to finish + cc_worker_list[cc]->waiting = true; + cc_worker_list[cc]->cvar.wait(lock); + cc_worker_list[cc]->waiting = false; + } + if (not current_tti.is_valid()) { + /* First Worker to start slot */ + + // process non-cc specific feedback if pending (e.g. SRs, buffer updates, UE config) for UEs with CA + // NOTE: there is no parallelism in these operations + slot_events.clear(); + { + std::lock_guard ev_lock(event_mutex); + next_slot_events.swap(slot_events); + } + for (ue_event_t& ev : slot_events) { + if (not ue_db.contains(ev.rnti) or ue_db[ev.rnti]->has_ca()) { + ev.callback(); + } + } - for (uint32_t cc = 0; cc < sf_worker_ctxt.workers.size(); ++cc) { - sf_worker_ctxt.workers[cc].start(tti_rx, ue_db); + // mark the start of slot. awake remaining workers if locking on the mutex + current_tti = tti_tx; + worker_count.store(static_cast(cc_worker_list.size()), std::memory_order_relaxed); + for (auto& w : cc_worker_list) { + if (w->waiting) { + waiting_cvars.push_back(&w->cvar); + } + } + lock.unlock(); + for (auto& w : waiting_cvars) { + w->notify_one(); + } + waiting_cvars.clear(); } } - sf_worker_ctxt.tti_rx = tti_rx; - sf_worker_ctxt.worker_count.store(static_cast(sf_worker_ctxt.workers.size()), std::memory_order_relaxed); - if (sf_worker_ctxt.nof_workers_waiting > 0) { - sf_worker_ctxt.cvar.notify_all(); + /* Parallel Region */ + + // process non-cc specific feedback if pending (e.g. SRs, buffer updates, UE config) for UEs without CA + for (ue_event_t& ev : slot_events) { + if (ue_db.contains(ev.rnti) and not ue_db[ev.rnti]->has_ca() and ue_db[ev.rnti]->pcell_cc() == cc) { + ev.callback(); + } } -} -bool sched_worker_manager::run_slot(tti_point tti_rx_, uint32_t cc) -{ - auto& sf_worker_ctxt = get_sf(tti_rx_); - srsran_assert(sf_worker_ctxt.tti_rx == tti_rx_, "invalid run_tti(tti, cc) arguments"); + // process pending feedback and pre-cache UE state for slot decision + cc_worker_list[cc]->worker.start(tti_tx, ue_db); // Get {tti, cc} scheduling decision - sf_worker_ctxt.workers[cc].run(); + cc_worker_list[cc]->worker.run(); // decrement the number of active workers - int rem_workers = sf_worker_ctxt.worker_count.fetch_sub(1, std::memory_order_release) - 1; + int rem_workers = worker_count.fetch_sub(1, std::memory_order_release) - 1; srsran_assert(rem_workers >= 0, "invalid number of calls to run_tti(tti, cc)"); + if (rem_workers == 0) { + /* Last Worker to finish slot */ - return rem_workers == 0; -} - -void sched_worker_manager::release_slot(tti_point tti_rx_) -{ - auto& sf_worker_ctxt = get_sf(tti_rx_); - srsran_assert(sf_worker_ctxt.tti_rx == tti_rx_, "invalid run_tti(tti, cc) arguments"); - srsran_assert(sf_worker_ctxt.worker_count == 0, "invalid number of calls to run_tti(tti, cc)"); - - { - std::lock_guard lock(ue_db_mutex); + // Signal the release of slot if it is the last worker that finished its own generation + std::unique_lock lock(slot_mutex); + current_tti = {}; // All the workers of the same slot have finished. Synchronize scheduling decisions with UEs state - for (slot_cc_worker& worker : sf_worker_ctxt.workers) { - worker.end_tti(); + for (auto& c : cc_worker_list) { + c->worker.finish(); + if (c->waiting) { + waiting_cvars.push_back(&c->cvar); + } } - } - std::unique_lock lock(sf_worker_ctxt.slot_mutex); - sf_worker_ctxt.tti_rx = {}; - if (sf_worker_ctxt.nof_workers_waiting > 0) { + // Awake waiting workers lock.unlock(); - sf_worker_ctxt.cvar.notify_one(); + for (auto& c : waiting_cvars) { + c->notify_one(); + } } } bool sched_worker_manager::save_sched_result(tti_point pdcch_tti, uint32_t cc, dl_sched_t& dl_res, ul_sched_t& ul_res) { - auto& bwp_slot = cell_grid_list[cc].bwps[0].grid[pdcch_tti]; + auto& bwp_slot = cells[cc]->bwps[0].grid[pdcch_tti]; dl_res.pdcch_dl = bwp_slot.dl_pdcchs; dl_res.pdcch_ul = bwp_slot.ul_pdcchs; diff --git a/srsenb/test/mac/nr/sched_nr_test.cc b/srsenb/test/mac/nr/sched_nr_test.cc index 39fb16437..8daadc738 100644 --- a/srsenb/test/mac/nr/sched_nr_test.cc +++ b/srsenb/test/mac/nr/sched_nr_test.cc @@ -142,7 +142,7 @@ struct task_job_manager { void sched_nr_cfg_serialized_test() { - uint32_t max_nof_ttis = 1000, nof_sectors = 2; + uint32_t max_nof_ttis = 1000, nof_sectors = 4; task_job_manager tasks; sched_nr_interface::sched_cfg_t cfg; @@ -150,7 +150,7 @@ void sched_nr_cfg_serialized_test() sched_nr_sim_base sched_tester(cfg, cells_cfg, "Serialized Test"); - sched_nr_interface::ue_cfg_t uecfg = get_default_ue_cfg(2); + sched_nr_interface::ue_cfg_t uecfg = get_default_ue_cfg(nof_sectors); sched_tester.add_user(0x46, uecfg, 0); @@ -188,7 +188,7 @@ void sched_nr_cfg_serialized_test() void sched_nr_cfg_parallel_cc_test() { - uint32_t nof_sectors = 2; + uint32_t nof_sectors = 4; uint32_t max_nof_ttis = 1000; task_job_manager tasks; @@ -236,64 +236,14 @@ void sched_nr_cfg_parallel_cc_test() printf("Total time taken per slot [usec]: %f\n", final_avg_usec); } -void sched_nr_cfg_parallel_sf_test() -{ - uint32_t max_nof_ttis = 1000; - uint32_t nof_sectors = 2; - task_job_manager tasks; - - sched_nr_interface::sched_cfg_t cfg; - cfg.nof_concurrent_subframes = 2; - std::vector cells_cfg = get_default_cells_cfg(nof_sectors); - - sched_nr_sim_base sched_tester(cfg, cells_cfg, "Parallel SF Test"); - - sched_nr_interface::ue_cfg_t uecfg = get_default_ue_cfg(cells_cfg.size()); - sched_tester.add_user(0x46, uecfg, 0); - - std::array, SRSRAN_MAX_CARRIERS> nano_count{}; - for (uint32_t nof_ttis = 0; nof_ttis < max_nof_ttis; ++nof_ttis) { - tti_point tti_rx(nof_ttis % 10240); - tti_point tti_tx = tti_rx + TX_ENB_DELAY; - tasks.start_slot(tti_tx, nof_sectors); - sched_tester.new_slot(tti_tx); - for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { - srsran::get_background_workers().push_task([cc, tti_tx, &sched_tester, &tasks, &nano_count]() { - sched_nr_interface::dl_sched_t dl_res; - sched_nr_interface::ul_sched_t ul_res; - auto tp1 = std::chrono::steady_clock::now(); - TESTASSERT(sched_tester.get_sched()->get_dl_sched(tti_tx, cc, dl_res) == SRSRAN_SUCCESS); - TESTASSERT(sched_tester.get_sched()->get_ul_sched(tti_tx, cc, ul_res) == SRSRAN_SUCCESS); - auto tp2 = std::chrono::steady_clock::now(); - nano_count[cc].fetch_add(std::chrono::duration_cast(tp2 - tp1).count(), - std::memory_order_relaxed); - sched_nr_cc_output_res_t out{tti_tx, cc, &dl_res, &ul_res}; - sched_tester.update(out); - tasks.finish_cc(tti_tx, dl_res, ul_res); - }); - } - } - - tasks.wait_task_finish(); - - tasks.print_results(); - - double final_avg_usec = 0; - for (uint32_t i = 0; i < nof_sectors; ++i) { - final_avg_usec += nano_count[i]; - } - final_avg_usec = final_avg_usec / 1000.0 / max_nof_ttis / nof_sectors; - printf("Total time taken per slot [usec]: %f\n", final_avg_usec); -} - } // namespace srsenb int main() { auto& test_logger = srslog::fetch_basic_logger("TEST"); - test_logger.set_level(srslog::basic_levels::info); + test_logger.set_level(srslog::basic_levels::warning); auto& mac_logger = srslog::fetch_basic_logger("MAC"); - mac_logger.set_level(srslog::basic_levels::info); + mac_logger.set_level(srslog::basic_levels::warning); auto& pool_logger = srslog::fetch_basic_logger("POOL"); pool_logger.set_level(srslog::basic_levels::info); @@ -304,5 +254,4 @@ int main() srsenb::sched_nr_cfg_serialized_test(); srsenb::sched_nr_cfg_parallel_cc_test(); - srsenb::sched_nr_cfg_parallel_sf_test(); } \ No newline at end of file From 6fb9b6bf9424619006becc687efb731d6c9ecc40 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sat, 17 Jul 2021 23:18:25 +0200 Subject: [PATCH 11/34] Fix sub-band CQI in UE. Refactor variable names --- lib/include/srsran/phy/phch/cqi.h | 8 +++---- lib/src/phy/phch/cqi.c | 37 ++++++++++++++++--------------- lib/src/phy/ue/ue_dl.c | 8 ++++--- srsenb/src/phy/phy_ue_db.cc | 8 +++---- 4 files changed, 32 insertions(+), 29 deletions(-) diff --git a/lib/include/srsran/phy/phch/cqi.h b/lib/include/srsran/phy/phch/cqi.h index 2bab78dfc..9a251f7b8 100644 --- a/lib/include/srsran/phy/phch/cqi.h +++ b/lib/include/srsran/phy/phch/cqi.h @@ -78,7 +78,7 @@ typedef struct SRSRAN_API { uint8_t wideband_cqi; // 4-bit width uint8_t subband_diff_cqi; // 2-bit width uint32_t position_subband; // L-bit width -} srsran_cqi_ue_subband_t; +} srsran_cqi_ue_diff_subband_t; /* Table 5.2.3.3.1-1: Fields for channel quality information feedback for wideband CQI reports (transmission mode 1, transmission mode 2, transmission mode 3, transmission mode 7 and @@ -100,12 +100,12 @@ typedef struct SRSRAN_API { typedef struct SRSRAN_API { uint8_t subband_cqi; // 4-bit width uint8_t subband_label; // 1- or 2-bit width -} srsran_cqi_format2_subband_t; +} srsran_cqi_ue_subband_t; typedef enum { SRSRAN_CQI_TYPE_WIDEBAND = 0, - SRSRAN_CQI_TYPE_SUBBAND, SRSRAN_CQI_TYPE_SUBBAND_UE, + SRSRAN_CQI_TYPE_SUBBAND_UE_DIFF, SRSRAN_CQI_TYPE_SUBBAND_HL } srsran_cqi_type_t; @@ -125,8 +125,8 @@ typedef struct SRSRAN_API { typedef struct { union { srsran_cqi_format2_wideband_t wideband; - srsran_cqi_format2_subband_t subband; srsran_cqi_ue_subband_t subband_ue; + srsran_cqi_ue_diff_subband_t subband_ue_diff; srsran_cqi_hl_subband_t subband_hl; }; bool data_crc; diff --git a/lib/src/phy/phch/cqi.c b/lib/src/phy/phch/cqi.c index d7ef51d34..9d407aae8 100644 --- a/lib/src/phy/phch/cqi.c +++ b/lib/src/phy/phch/cqi.c @@ -65,7 +65,7 @@ static int cqi_hl_subband_pack(srsran_cqi_cfg_t* cfg, srsran_cqi_hl_subband_t* m return bit_count; } -static int cqi_ue_subband_pack(srsran_cqi_cfg_t* cfg, srsran_cqi_ue_subband_t* msg, uint8_t* buff) +static int cqi_ue_subband_pack(srsran_cqi_cfg_t* cfg, srsran_cqi_ue_diff_subband_t* msg, uint8_t* buff) { uint8_t* body_ptr = buff; srsran_bit_unpack(msg->wideband_cqi, &body_ptr, 4); @@ -101,7 +101,7 @@ static int cqi_format2_wideband_pack(srsran_cqi_cfg_t* cfg, srsran_cqi_format2_w return (int)(body_ptr - buff); } -static int cqi_format2_subband_pack(srsran_cqi_cfg_t* cfg, srsran_cqi_format2_subband_t* msg, uint8_t* buff) +static int cqi_format2_subband_pack(srsran_cqi_cfg_t* cfg, srsran_cqi_ue_subband_t* msg, uint8_t* buff) { uint8_t* body_ptr = buff; srsran_bit_unpack(msg->subband_cqi, &body_ptr, 4); @@ -114,10 +114,10 @@ int srsran_cqi_value_pack(srsran_cqi_cfg_t* cfg, srsran_cqi_value_t* value, uint switch (cfg->type) { case SRSRAN_CQI_TYPE_WIDEBAND: return cqi_format2_wideband_pack(cfg, &value->wideband, buff); - case SRSRAN_CQI_TYPE_SUBBAND: - return cqi_format2_subband_pack(cfg, &value->subband, buff); case SRSRAN_CQI_TYPE_SUBBAND_UE: - return cqi_ue_subband_pack(cfg, &value->subband_ue, buff); + return cqi_format2_subband_pack(cfg, &value->subband_ue, buff); + case SRSRAN_CQI_TYPE_SUBBAND_UE_DIFF: + return cqi_ue_subband_pack(cfg, &value->subband_ue_diff, buff); case SRSRAN_CQI_TYPE_SUBBAND_HL: return cqi_hl_subband_pack(cfg, &value->subband_hl, buff); } @@ -163,7 +163,7 @@ int cqi_hl_subband_unpack(srsran_cqi_cfg_t* cfg, uint8_t* buff, srsran_cqi_hl_su return bit_count; } -int cqi_ue_subband_unpack(srsran_cqi_cfg_t* cfg, uint8_t* buff, srsran_cqi_ue_subband_t* msg) +int cqi_ue_subband_unpack(srsran_cqi_cfg_t* cfg, uint8_t* buff, srsran_cqi_ue_diff_subband_t* msg) { uint8_t* body_ptr = buff; msg->wideband_cqi = srsran_bit_pack(&body_ptr, 4); @@ -197,7 +197,7 @@ static int cqi_format2_wideband_unpack(srsran_cqi_cfg_t* cfg, uint8_t* buff, srs return 4; } -static int cqi_format2_subband_unpack(srsran_cqi_cfg_t* cfg, uint8_t* buff, srsran_cqi_format2_subband_t* msg) +static int cqi_format2_subband_unpack(srsran_cqi_cfg_t* cfg, uint8_t* buff, srsran_cqi_ue_subband_t* msg) { uint8_t* body_ptr = buff; msg->subband_cqi = srsran_bit_pack(&body_ptr, 4); @@ -210,10 +210,10 @@ int srsran_cqi_value_unpack(srsran_cqi_cfg_t* cfg, uint8_t buff[SRSRAN_CQI_MAX_B switch (cfg->type) { case SRSRAN_CQI_TYPE_WIDEBAND: return cqi_format2_wideband_unpack(cfg, buff, &value->wideband); - case SRSRAN_CQI_TYPE_SUBBAND: - return cqi_format2_subband_unpack(cfg, buff, &value->subband); case SRSRAN_CQI_TYPE_SUBBAND_UE: - return cqi_ue_subband_unpack(cfg, buff, &value->subband_ue); + return cqi_format2_subband_unpack(cfg, buff, &value->subband_ue); + case SRSRAN_CQI_TYPE_SUBBAND_UE_DIFF: + return cqi_ue_subband_unpack(cfg, buff, &value->subband_ue_diff); case SRSRAN_CQI_TYPE_SUBBAND_HL: return cqi_hl_subband_unpack(cfg, buff, &value->subband_hl); } @@ -242,7 +242,7 @@ cqi_format2_wideband_tostring(srsran_cqi_cfg_t* cfg, srsran_cqi_format2_wideband } static int -cqi_format2_subband_tostring(srsran_cqi_cfg_t* cfg, srsran_cqi_format2_subband_t* msg, char* buff, uint32_t buff_len) +cqi_format2_subband_tostring(srsran_cqi_cfg_t* cfg, srsran_cqi_ue_subband_t* msg, char* buff, uint32_t buff_len) { int n = 0; @@ -252,7 +252,8 @@ cqi_format2_subband_tostring(srsran_cqi_cfg_t* cfg, srsran_cqi_format2_subband_t return n; } -static int cqi_ue_subband_tostring(srsran_cqi_cfg_t* cfg, srsran_cqi_ue_subband_t* msg, char* buff, uint32_t buff_len) +static int +cqi_ue_subband_tostring(srsran_cqi_cfg_t* cfg, srsran_cqi_ue_diff_subband_t* msg, char* buff, uint32_t buff_len) { int n = 0; @@ -292,11 +293,11 @@ int srsran_cqi_value_tostring(srsran_cqi_cfg_t* cfg, srsran_cqi_value_t* value, case SRSRAN_CQI_TYPE_WIDEBAND: ret = cqi_format2_wideband_tostring(cfg, &value->wideband, buff, buff_len); break; - case SRSRAN_CQI_TYPE_SUBBAND: - ret = cqi_format2_subband_tostring(cfg, &value->subband, buff, buff_len); - break; case SRSRAN_CQI_TYPE_SUBBAND_UE: - ret = cqi_ue_subband_tostring(cfg, &value->subband_ue, buff, buff_len); + ret = cqi_format2_subband_tostring(cfg, &value->subband_ue, buff, buff_len); + break; + case SRSRAN_CQI_TYPE_SUBBAND_UE_DIFF: + ret = cqi_ue_subband_tostring(cfg, &value->subband_ue_diff, buff, buff_len); break; case SRSRAN_CQI_TYPE_SUBBAND_HL: ret = cqi_hl_subband_tostring(cfg, &value->subband_hl, buff, buff_len); @@ -339,10 +340,10 @@ int srsran_cqi_size(srsran_cqi_cfg_t* cfg) } } break; - case SRSRAN_CQI_TYPE_SUBBAND: + case SRSRAN_CQI_TYPE_SUBBAND_UE: size = 4 + ((cfg->subband_label_2_bits) ? 2 : 1); break; - case SRSRAN_CQI_TYPE_SUBBAND_UE: + case SRSRAN_CQI_TYPE_SUBBAND_UE_DIFF: size = 4 + 2 + cfg->L; break; case SRSRAN_CQI_TYPE_SUBBAND_HL: diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index 32a3b77aa..24ac0bb54 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -855,9 +855,11 @@ void srsran_ue_dl_gen_cqi_periodic(srsran_ue_dl_t* q, } else if (srsran_cqi_periodic_send(&cfg->cfg.cqi_report, tti, q->cell.frame_type)) { if (cfg->cfg.cqi_report.format_is_subband) { // TODO: Implement subband periodic reports - uci_data->cfg.cqi.type = SRSRAN_CQI_TYPE_SUBBAND; - uci_data->value.cqi.subband.subband_cqi = wideband_value; - uci_data->value.cqi.subband.subband_label = 0; + uci_data->cfg.cqi.type = SRSRAN_CQI_TYPE_SUBBAND_UE; + uci_data->value.cqi.subband_ue.subband_cqi = wideband_value; + uci_data->value.cqi.subband_ue.subband_label = tti / 100 % 2; + uci_data->cfg.cqi.L = srsran_cqi_hl_get_L(q->cell.nof_prb); + uci_data->cfg.cqi.subband_label_2_bits = uci_data->cfg.cqi.L > 1; } else { uci_data->cfg.cqi.type = SRSRAN_CQI_TYPE_WIDEBAND; uci_data->value.cqi.wideband.wideband_cqi = wideband_value; diff --git a/srsenb/src/phy/phy_ue_db.cc b/srsenb/src/phy/phy_ue_db.cc index 0932edb33..837924e76 100644 --- a/srsenb/src/phy/phy_ue_db.cc +++ b/srsenb/src/phy/phy_ue_db.cc @@ -668,14 +668,14 @@ int phy_ue_db::send_uci_data(uint32_t tti, case SRSRAN_CQI_TYPE_WIDEBAND: cqi_value = uci_value.cqi.wideband.wideband_cqi; break; - case SRSRAN_CQI_TYPE_SUBBAND: - cqi_value = uci_value.cqi.subband.subband_cqi; + case SRSRAN_CQI_TYPE_SUBBAND_UE: + cqi_value = uci_value.cqi.subband_ue.subband_cqi; break; case SRSRAN_CQI_TYPE_SUBBAND_HL: cqi_value = uci_value.cqi.subband_hl.wideband_cqi_cw0; break; - case SRSRAN_CQI_TYPE_SUBBAND_UE: - cqi_value = uci_value.cqi.subband_ue.wideband_cqi; + case SRSRAN_CQI_TYPE_SUBBAND_UE_DIFF: + cqi_value = uci_value.cqi.subband_ue_diff.wideband_cqi; break; } stack->cqi_info(tti, rnti, cqi_cc_idx, cqi_value); From c9c3a68fae69a51f3af39267b028d1b77d6bbe87 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Sun, 18 Jul 2021 23:23:20 +0200 Subject: [PATCH 12/34] asn1,rrc_nr: add error code handling to packing/unpacking of pdcch_cfg --- lib/src/asn1/rrc_nr.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/asn1/rrc_nr.cc b/lib/src/asn1/rrc_nr.cc index f940f3375..2267d4ff8 100644 --- a/lib/src/asn1/rrc_nr.cc +++ b/lib/src/asn1/rrc_nr.cc @@ -3039,7 +3039,7 @@ SRSASN_CODE pdcch_cfg_common_s::pack(bit_ref& bref) const if (ext) { ext_groups_packer_guard group_flags; group_flags[0] |= first_pdcch_monitoring_occasion_of_po.is_present(); - group_flags.pack(bref); + HANDLE_CODE(group_flags.pack(bref)); if (group_flags[0]) { varlength_field_pack_guard varlen_scope(bref, false); @@ -3091,7 +3091,7 @@ SRSASN_CODE pdcch_cfg_common_s::unpack(cbit_ref& bref) if (ext) { ext_groups_unpacker_guard group_flags(1); - group_flags.unpack(bref); + HANDLE_CODE(group_flags.unpack(bref)); if (group_flags[0]) { varlength_field_unpack_guard varlen_scope(bref, false); From 60a795acc0982fe651ca0137f2f017bb655aa515 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Sun, 18 Jul 2021 23:25:52 +0200 Subject: [PATCH 13/34] asn1,rrc_nr,test: extend RRC reconf test, add PCAP output test now can write the NR reconfig into a PCAP for easy debugging with Wireshark patch also adds a new test helper to write a RRC PDU into a PCAP file (helper packs PDCP and RLC AM first) --- lib/include/srsran/common/test_pcap.h | 68 ++++++ lib/test/asn1/CMakeLists.txt | 2 +- lib/test/asn1/srsran_asn1_rrc_nr_test.cc | 292 +++++++++++++++++++++-- 3 files changed, 339 insertions(+), 23 deletions(-) create mode 100644 lib/include/srsran/common/test_pcap.h diff --git a/lib/include/srsran/common/test_pcap.h b/lib/include/srsran/common/test_pcap.h new file mode 100644 index 000000000..567fc9ac6 --- /dev/null +++ b/lib/include/srsran/common/test_pcap.h @@ -0,0 +1,68 @@ +/** + * + * \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_TEST_PCAP_H +#define SRSRAN_TEST_PCAP_H + +#if HAVE_PCAP +#include "srsran/common/mac_pcap.h" +#include "srsran/mac/mac_sch_pdu_nr.h" +static std::unique_ptr pcap_handle = nullptr; +#define PCAP_CRNTI (0x1001) +#define PCAP_TTI (666) +#endif + +namespace srsran { + +int write_mac_sdu_nr(const uint32_t lcid, const uint8_t* payload, const uint32_t len); + +int write_rlc_am_sdu_nr(const uint32_t lcid, const uint8_t* payload, const uint32_t len) +{ +#if HAVE_PCAP + if (pcap_handle) { + byte_buffer_t mac_sdu; + // Add dummy RLC AM PDU header + mac_sdu.msg[0] = 0x80; + mac_sdu.msg[1] = 0x00; + + // Add dummy PDCP header + mac_sdu.msg[2] = 0x00; + mac_sdu.msg[3] = 0x00; + + mac_sdu.N_bytes = 4; + memcpy(mac_sdu.msg + 4, payload, len); + mac_sdu.N_bytes += len; + return write_mac_sdu_nr(lcid, mac_sdu.msg, mac_sdu.N_bytes); + } +#endif // HAVE_PCAP + return SRSRAN_ERROR; +} + +int write_mac_sdu_nr(const uint32_t lcid, const uint8_t* payload, const uint32_t len) +{ +#if HAVE_PCAP + if (pcap_handle) { + byte_buffer_t tx_buffer; + srsran::mac_sch_pdu_nr tx_pdu; + tx_pdu.init_tx(&tx_buffer, len + 10); + tx_pdu.add_sdu(lcid, payload, len); + tx_pdu.pack(); + pcap_handle->write_dl_crnti_nr(tx_buffer.msg, tx_buffer.N_bytes, PCAP_CRNTI, 0, PCAP_TTI); + return SRSRAN_SUCCESS; + } +#endif // HAVE_PCAP + return SRSRAN_ERROR; +} + +} // namespace srsran + +#endif // SRSRAN_TEST_COMMON_H diff --git a/lib/test/asn1/CMakeLists.txt b/lib/test/asn1/CMakeLists.txt index 1c7054213..bb72a41f5 100644 --- a/lib/test/asn1/CMakeLists.txt +++ b/lib/test/asn1/CMakeLists.txt @@ -43,7 +43,7 @@ target_link_libraries(rrc_asn1_test rrc_asn1 asn1_utils srsran_common) add_test(rrc_asn1_test rrc_asn1_test) add_executable(srsran_asn1_rrc_nr_test srsran_asn1_rrc_nr_test.cc) -target_link_libraries(srsran_asn1_rrc_nr_test rrc_nr_asn1 asn1_utils srsran_common) +target_link_libraries(srsran_asn1_rrc_nr_test rrc_nr_asn1 asn1_utils srsran_common srsran_mac) add_test(srsran_asn1_rrc_nr_test srsran_asn1_rrc_nr_test) add_executable(ngap_asn1_test ngap_test.cc) diff --git a/lib/test/asn1/srsran_asn1_rrc_nr_test.cc b/lib/test/asn1/srsran_asn1_rrc_nr_test.cc index cb4c2665a..3d00d1063 100644 --- a/lib/test/asn1/srsran_asn1_rrc_nr_test.cc +++ b/lib/test/asn1/srsran_asn1_rrc_nr_test.cc @@ -16,6 +16,9 @@ #define JSON_OUTPUT 0 +#define HAVE_PCAP 0 +#include "srsran/common/test_pcap.h" + using namespace asn1; using namespace asn1::rrc_nr; @@ -365,19 +368,109 @@ int test_cell_group_config() cell_group_cfg_s cell_group_cfg_pack; cell_group_cfg_pack.sp_cell_cfg_present = true; cell_group_cfg_pack.sp_cell_cfg.serv_cell_idx_present = true; + + // SP Cell Dedicated config cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded_present = true; cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp_present = true; + + // PDCCH config + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp.pdcch_cfg_present = true; + auto& pdcch_cfg_dedicated = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp.pdcch_cfg; + pdcch_cfg_dedicated.set_setup(); + pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list_present = true; + pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list.resize(1); + pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list[0].ctrl_res_set_id = 2; + pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list[0].freq_domain_res.from_number( + 0b111111110000000000000000000000000000000000000); + pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list[0].dur = 1; + pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list[0].cce_reg_map_type.set_non_interleaved(); + pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list[0].precoder_granularity = + asn1::rrc_nr::ctrl_res_set_s::precoder_granularity_opts::same_as_reg_bundle; + + // search spaces + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list_present = true; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list.resize(1); + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].search_space_id = 2; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].ctrl_res_set_id_present = true; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].ctrl_res_set_id = 2; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].monitoring_slot_periodicity_and_offset_present = true; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].monitoring_slot_periodicity_and_offset.set_sl1(); + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].monitoring_symbols_within_slot_present = true; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].monitoring_symbols_within_slot.from_number( + 0b10000000000000); + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].nrof_candidates_present = true; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].nrof_candidates.aggregation_level1 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level1_opts::n0; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].nrof_candidates.aggregation_level2 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level2_opts::n2; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].nrof_candidates.aggregation_level4 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level4_opts::n1; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].nrof_candidates.aggregation_level8 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level8_opts::n0; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].nrof_candidates.aggregation_level16 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level16_opts::n0; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].search_space_type_present = true; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].search_space_type.set_ue_specific(); + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].search_space_type.ue_specific().dci_formats = asn1:: + rrc_nr::search_space_s::search_space_type_c_::ue_specific_s_::dci_formats_opts::formats0_minus0_and_minus1_minus0; + + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp.pdsch_cfg_present = true; + auto& pdsch_cfg_dedicated = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp.pdsch_cfg; + + pdsch_cfg_dedicated.set_setup(); + pdsch_cfg_dedicated.setup().dmrs_dl_for_pdsch_map_type_a_present = true; + pdsch_cfg_dedicated.setup().dmrs_dl_for_pdsch_map_type_a.set_setup(); + pdsch_cfg_dedicated.setup().dmrs_dl_for_pdsch_map_type_a.setup().dmrs_add_position_present = true; + pdsch_cfg_dedicated.setup().dmrs_dl_for_pdsch_map_type_a.setup().dmrs_add_position = + asn1::rrc_nr::dmrs_dl_cfg_s::dmrs_add_position_opts::pos1; + pdsch_cfg_dedicated.setup().tci_states_to_add_mod_list_present = true; + pdsch_cfg_dedicated.setup().tci_states_to_add_mod_list.resize(1); + pdsch_cfg_dedicated.setup().tci_states_to_add_mod_list[0].tci_state_id = 0; + pdsch_cfg_dedicated.setup().tci_states_to_add_mod_list[0].qcl_type1.ref_sig.set_ssb(); + pdsch_cfg_dedicated.setup().tci_states_to_add_mod_list[0].qcl_type1.ref_sig.ssb() = 0; + pdsch_cfg_dedicated.setup().tci_states_to_add_mod_list[0].qcl_type1.qcl_type = + asn1::rrc_nr::qcl_info_s::qcl_type_opts::type_d; + pdsch_cfg_dedicated.setup().res_alloc = pdsch_cfg_s::res_alloc_opts::res_alloc_type1; + pdsch_cfg_dedicated.setup().rbg_size = asn1::rrc_nr::pdsch_cfg_s::rbg_size_opts::cfg1; + pdsch_cfg_dedicated.setup().prb_bundling_type.set_static_bundling(); + pdsch_cfg_dedicated.setup().prb_bundling_type.static_bundling().bundle_size_present = true; + pdsch_cfg_dedicated.setup().prb_bundling_type.static_bundling().bundle_size = + asn1::rrc_nr::pdsch_cfg_s::prb_bundling_type_c_::static_bundling_s_::bundle_size_opts::wideband; + + // ZP-CSI + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list_present = true; + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list.resize(1); + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].zp_csi_rs_res_id = 0; + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].res_map.freq_domain_alloc.set_row4(); + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].res_map.freq_domain_alloc.row4().from_number(0x100); + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].res_map.nrof_ports = + asn1::rrc_nr::csi_rs_res_map_s::nrof_ports_opts::p4; + + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].res_map.first_ofdm_symbol_in_time_domain = 8; + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].res_map.cdm_type = + asn1::rrc_nr::csi_rs_res_map_s::cdm_type_opts::fd_cdm2; + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].res_map.density.set_one(); + + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].res_map.freq_band.start_rb = 0; + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].res_map.freq_band.nrof_rbs = 52; + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].periodicity_and_offset_present = true; + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].periodicity_and_offset.set_slots80(); + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].periodicity_and_offset.slots80() = 1; + pdsch_cfg_dedicated.setup().p_zp_csi_rs_res_set_present = true; + pdsch_cfg_dedicated.setup().p_zp_csi_rs_res_set.set_setup(); + pdsch_cfg_dedicated.setup().p_zp_csi_rs_res_set.setup().zp_csi_rs_res_set_id = 0; + pdsch_cfg_dedicated.setup().p_zp_csi_rs_res_set.setup().zp_csi_rs_res_id_list.resize(1); + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.first_active_dl_bwp_id_present = true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.first_active_dl_bwp_id = 1; cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg_present = true; - // TODO: add setup + // Serving cell config (only to setup) cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.pdcch_serving_cell_cfg_present = true; - auto& pdcch_cfg = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.pdcch_serving_cell_cfg.set_setup(); - // TODO: add PDCCH config + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.pdcch_serving_cell_cfg.set_setup(); cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.pdsch_serving_cell_cfg_present = true; - auto& pdsch_cfg = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.pdsch_serving_cell_cfg.set_setup(); - // TODO: add PDSCH config + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.pdsch_serving_cell_cfg.set_setup(); cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg_present = true; cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.set_setup(); @@ -424,15 +517,60 @@ int test_cell_group_config() .subcarrier_spacing = subcarrier_spacing_opts::khz15; cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp .pdcch_cfg_common_present = true; - cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp.pdcch_cfg_common - .set_setup(); - // TODO: add PDCCH config - + auto& pdcch_cfg_common = + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp.pdcch_cfg_common; + pdcch_cfg_common.set_setup(); + pdcch_cfg_common.setup().ext = false; + pdcch_cfg_common.setup().common_ctrl_res_set_present = true; + pdcch_cfg_common.setup().common_ctrl_res_set.ctrl_res_set_id = 1; + pdcch_cfg_common.setup().common_ctrl_res_set.freq_domain_res.from_number( + 0b111111110000000000000000000000000000000000000); + pdcch_cfg_common.setup().common_ctrl_res_set.dur = 1; + pdcch_cfg_common.setup().common_ctrl_res_set.cce_reg_map_type.set_non_interleaved(); + pdcch_cfg_common.setup().common_ctrl_res_set.precoder_granularity = + asn1::rrc_nr::ctrl_res_set_s::precoder_granularity_opts::same_as_reg_bundle; + + // common search space list + pdcch_cfg_common.setup().common_search_space_list_present = true; + pdcch_cfg_common.setup().common_search_space_list.resize(1); + pdcch_cfg_common.setup().common_search_space_list[0].search_space_id = 1; + pdcch_cfg_common.setup().common_search_space_list[0].ctrl_res_set_id_present = true; + pdcch_cfg_common.setup().common_search_space_list[0].ctrl_res_set_id = 1; + pdcch_cfg_common.setup().common_search_space_list[0].search_space_type_present = true; + pdcch_cfg_common.setup().common_search_space_list[0].search_space_type.set_common(); + pdcch_cfg_common.setup() + .common_search_space_list[0] + .search_space_type.common() + .dci_format0_minus0_and_format1_minus0_present = true; + pdcch_cfg_common.setup().common_search_space_list[0].nrof_candidates_present = true; + pdcch_cfg_common.setup().common_search_space_list[0].nrof_candidates.aggregation_level1 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level1_opts::n1; + pdcch_cfg_common.setup().common_search_space_list[0].nrof_candidates.aggregation_level2 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level2_opts::n1; + pdcch_cfg_common.setup().common_search_space_list[0].nrof_candidates.aggregation_level4 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level4_opts::n1; + pdcch_cfg_common.setup().common_search_space_list[0].nrof_candidates.aggregation_level8 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level8_opts::n0; + pdcch_cfg_common.setup().common_search_space_list[0].nrof_candidates.aggregation_level16 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level16_opts::n0; + pdcch_cfg_common.setup().common_search_space_list[0].monitoring_slot_periodicity_and_offset_present = true; + pdcch_cfg_common.setup().common_search_space_list[0].monitoring_slot_periodicity_and_offset.set_sl1(); + pdcch_cfg_common.setup().common_search_space_list[0].monitoring_symbols_within_slot_present = true; + pdcch_cfg_common.setup().common_search_space_list[0].monitoring_symbols_within_slot.from_number(0b10000000000000); + pdcch_cfg_common.setup().ra_search_space_present = true; + pdcch_cfg_common.setup().ra_search_space = 1; + + // PDSCH config common cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp .pdsch_cfg_common_present = true; cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp.pdsch_cfg_common .set_setup(); - // TODO: add PDSCH config + auto& pdsch_cfg_common = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp + .pdsch_cfg_common.setup(); + pdsch_cfg_common.pdsch_time_domain_alloc_list_present = true; + pdsch_cfg_common.pdsch_time_domain_alloc_list.resize(1); + pdsch_cfg_common.pdsch_time_domain_alloc_list[0].map_type = pdsch_time_domain_res_alloc_s::map_type_opts::type_a; + pdsch_cfg_common.pdsch_time_domain_alloc_list[0].start_symbol_and_len = 40; // UL config cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common_present = true; @@ -452,24 +590,122 @@ int test_cell_group_config() cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.generic_params .subcarrier_spacing = subcarrier_spacing_opts::khz15; - // TODO: add config field for RACH -#if 0 + // RACH config cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common_present=true; - cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common.set_setup(); - cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common.setup().prach_root_seq_idx = 10; -#endif - - uint8_t buffer[1024]; - asn1::bit_ref bref_pack(buffer, sizeof(buffer)); + auto& rach_cfg_common_pack = + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common; + + rach_cfg_common_pack.set_setup(); + rach_cfg_common_pack.setup().rach_cfg_generic.prach_cfg_idx = 0; + rach_cfg_common_pack.setup().rach_cfg_generic.msg1_fdm = rach_cfg_generic_s::msg1_fdm_opts::one; + rach_cfg_common_pack.setup().rach_cfg_generic.msg1_freq_start = 1; + rach_cfg_common_pack.setup().rach_cfg_generic.zero_correlation_zone_cfg = 0; + rach_cfg_common_pack.setup().rach_cfg_generic.preamb_rx_target_pwr = -110; + rach_cfg_common_pack.setup().rach_cfg_generic.preamb_trans_max = + asn1::rrc_nr::rach_cfg_generic_s::preamb_trans_max_opts::n7; + rach_cfg_common_pack.setup().rach_cfg_generic.pwr_ramp_step = + asn1::rrc_nr::rach_cfg_generic_s::pwr_ramp_step_opts::db4; + rach_cfg_common_pack.setup().rach_cfg_generic.ra_resp_win = asn1::rrc_nr::rach_cfg_generic_s::ra_resp_win_opts::sl10; + rach_cfg_common_pack.setup().ra_contention_resolution_timer = + asn1::rrc_nr::rach_cfg_common_s::ra_contention_resolution_timer_opts::sf64; + rach_cfg_common_pack.setup().prach_root_seq_idx.set( + asn1::rrc_nr::rach_cfg_common_s::prach_root_seq_idx_c_::types_opts::l839); + rach_cfg_common_pack.setup().prach_root_seq_idx.set_l839() = 1; + rach_cfg_common_pack.setup().restricted_set_cfg = + asn1::rrc_nr::rach_cfg_common_s::restricted_set_cfg_opts::unrestricted_set; + + // PUSCH config common + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp + .pusch_cfg_common_present = true; + auto& pusch_cfg_common_pack = + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.pusch_cfg_common; + pusch_cfg_common_pack.set_setup(); + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list_present = true; + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list.resize(2); + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list[0].k2_present = true; + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list[0].k2 = 4; + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list[0].map_type = + asn1::rrc_nr::pusch_time_domain_res_alloc_s::map_type_opts::type_a; + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list[0].start_symbol_and_len = 27; + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list[1].k2_present = true; + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list[1].k2 = 3; + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list[1].map_type = + asn1::rrc_nr::pusch_time_domain_res_alloc_s::map_type_opts::type_a; + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list[1].start_symbol_and_len = 27; + pusch_cfg_common_pack.setup().p0_nominal_with_grant = -90; + + // PUCCH config common + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp + .pucch_cfg_common_present = true; + auto& pucch_cfg_common_pack = + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.pucch_cfg_common; + pucch_cfg_common_pack.set_setup(); + pucch_cfg_common_pack.setup().pucch_group_hop = asn1::rrc_nr::pucch_cfg_common_s::pucch_group_hop_opts::neither; + pucch_cfg_common_pack.setup().p0_nominal_present = true; + pucch_cfg_common_pack.setup().p0_nominal = -90; + + // SSB config (optional) + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_positions_in_burst_present = true; + auto& ssb_pos_in_burst = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_positions_in_burst; + ssb_pos_in_burst.set_medium_bitmap().from_number(0b10000000); + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_periodicity_serving_cell_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_periodicity_serving_cell = + serving_cell_cfg_common_s::ssb_periodicity_serving_cell_opts::ms20; + + // TDD UL-DL config + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common_present = true; + auto& tdd_config = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common; + tdd_config.ref_subcarrier_spacing = subcarrier_spacing_e::khz15; + tdd_config.pattern1.dl_ul_tx_periodicity = asn1::rrc_nr::tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms10; + tdd_config.pattern1.nrof_dl_slots = 6; + tdd_config.pattern1.nrof_dl_symbols = 0; + tdd_config.pattern1.nrof_ul_slots = 3; + tdd_config.pattern1.nrof_ul_symbols = 0; + + // pack only cell group info + asn1::dyn_octstring packed_cell_group; + packed_cell_group.resize(256); + asn1::bit_ref bref_pack(packed_cell_group.data(), packed_cell_group.size()); TESTASSERT(cell_group_cfg_pack.pack(bref_pack) == asn1::SRSASN_SUCCESS); TESTASSERT(test_pack_unpack_consistency(cell_group_cfg_pack) == SRSASN_SUCCESS); + packed_cell_group.resize(bref_pack.distance_bytes()); #if JSON_OUTPUT - int packed_len = bref_pack.distance_bytes(); asn1::json_writer json_writer2; cell_group_cfg_pack.to_json(json_writer2); - srslog::fetch_basic_logger("RRC").info( - buffer, packed_len, "Cell group config repacked (%d B): \n %s", packed_len, json_writer2.to_string().c_str()); + srslog::fetch_basic_logger("RRC").info(packed_cell_group.data(), + packed_cell_group.size(), + "Cell group config repacked (%d B): \n %s", + packed_cell_group.size(), + json_writer2.to_string().c_str()); +#endif + +#if HAVE_PCAP + // pack full DL-DCCH with RRC reconfig for PCAP output + dl_dcch_msg_s dcch; + dcch.msg.set_c1().set_rrc_recfg(); + rrc_recfg_s& reconfig = dcch.msg.c1().rrc_recfg(); + reconfig.rrc_transaction_id = 0; + reconfig.crit_exts.set_rrc_recfg(); + rrc_recfg_ies_s& recfg_ies = reconfig.crit_exts.rrc_recfg(); + recfg_ies.secondary_cell_group_present = true; + recfg_ies.secondary_cell_group = packed_cell_group; + + asn1::dyn_octstring packed_dcch; + packed_dcch.resize(1024); + asn1::bit_ref bref_dcch_pack(packed_dcch.data(), packed_dcch.size()); + TESTASSERT(dcch.pack(bref_dcch_pack) == asn1::SRSASN_SUCCESS); + packed_dcch.resize(bref_dcch_pack.distance_bytes() + 10); + + asn1::json_writer json_writer3; + dcch.to_json(json_writer3); + srslog::fetch_basic_logger("RRC").info(packed_dcch.data(), + packed_dcch.size(), + "Full DCCH repacked (%d B): \n %s", + packed_dcch.size(), + json_writer3.to_string().c_str()); + + srsran::write_rlc_am_sdu_nr(1, packed_dcch.data(), packed_dcch.size()); #endif return SRSRAN_SUCCESS; @@ -487,6 +723,11 @@ int main() // Start the log backend. srslog::init(); +#if HAVE_PCAP + pcap_handle = std::unique_ptr(new srsran::mac_pcap()); + pcap_handle->open("srsran_asn1_rrc_nr_test.pcap"); +#endif + TESTASSERT(test_eutra_nr_capabilities() == SRSRAN_SUCCESS); TESTASSERT(test_ue_mrdc_capabilities() == SRSRAN_SUCCESS); TESTASSERT(test_ue_rrc_reconfiguration() == SRSRAN_SUCCESS); @@ -496,5 +737,12 @@ int main() srslog::flush(); printf("Success\n"); - return 0; + +#if HAVE_PCAP + if (pcap_handle) { + pcap_handle->close(); + } +#endif + + return SRSRAN_SUCCESS; } From fc8fe032ff1559b53ccfdffb3018a50d8a12ce0d Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Sun, 18 Jul 2021 23:27:59 +0200 Subject: [PATCH 14/34] rrc_nr,endc: add more fields to NR RRC Reconfig for EN-DC activation adds a big chunk of new fields to the reconfig packing code, tested with srsUE --- srsenb/hdr/stack/rrc/rrc_nr.h | 6 + srsenb/src/stack/rrc/rrc_endc.cc | 5 + srsenb/src/stack/rrc/rrc_nr.cc | 387 +++++++++++++++++++++++++++++-- srsue/src/stack/rrc/rrc_nr.cc | 6 +- 4 files changed, 380 insertions(+), 24 deletions(-) diff --git a/srsenb/hdr/stack/rrc/rrc_nr.h b/srsenb/hdr/stack/rrc/rrc_nr.h index 87c225bef..676074dc7 100644 --- a/srsenb/hdr/stack/rrc/rrc_nr.h +++ b/srsenb/hdr/stack/rrc/rrc_nr.h @@ -99,10 +99,16 @@ public: // setters + int pack_rrc_reconfiguraiton(); + private: rrc_nr* parent = nullptr; uint16_t rnti = SRSRAN_INVALID_RNTI; + int pack_rrc_reconfiguraiton(asn1::dyn_octstring& packed_rrc_reconfig); + int pack_secondary_cell_group_config(asn1::dyn_octstring& packed_secondary_cell_config); + 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; diff --git a/srsenb/src/stack/rrc/rrc_endc.cc b/srsenb/src/stack/rrc/rrc_endc.cc index 46ca65ca4..71245c05e 100644 --- a/srsenb/src/stack/rrc/rrc_endc.cc +++ b/srsenb/src/stack/rrc/rrc_endc.cc @@ -248,6 +248,11 @@ void rrc::ue::rrc_endc::handle_sgnb_addition_ack(const asn1::dyn_octstring& nr_s nr_secondary_cell_group_cfg_r15 = nr_secondary_cell_group_cfg_r15_; nr_radio_bearer_cfg1_r15 = nr_radio_bearer_cfg1_r15_; + logger.debug(nr_secondary_cell_group_cfg_r15.data(), + nr_secondary_cell_group_cfg_r15.size(), + "nr-SecondaryCellGroupConfig-r15:"); + logger.debug(nr_radio_bearer_cfg1_r15.data(), nr_radio_bearer_cfg1_r15.size(), "nr-RadioBearerConfig1-r15:"); + sgnb_add_req_ack_ev sgnb_add_ack{}; trigger(sgnb_add_ack); } diff --git a/srsenb/src/stack/rrc/rrc_nr.cc b/srsenb/src/stack/rrc/rrc_nr.cc index a7fdd459c..10b02cd36 100644 --- a/srsenb/src/stack/rrc/rrc_nr.cc +++ b/srsenb/src/stack/rrc/rrc_nr.cc @@ -457,21 +457,348 @@ void rrc_nr::ue::send_dl_ccch(dl_ccch_msg_s* dl_ccch_msg) parent->rlc->write_sdu(rnti, (uint32_t)srsran::nr_srb::srb0, std::move(pdu)); } -int rrc_nr::ue::handle_sgnb_addition_request(uint16_t eutra_rnti) +// Helper for the RRC Reconfiguration sender to pack hard-coded config +int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_secondary_cell_config) { - // provide hard-coded NR configs - asn1::dyn_octstring nr_config; + cell_group_cfg_s cell_group_cfg_pack; + cell_group_cfg_pack.sp_cell_cfg_present = true; + cell_group_cfg_pack.sp_cell_cfg.serv_cell_idx_present = true; + + // SP Cell Dedicated config + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded_present = true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp_present = true; + + // PDCCH config + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp.pdcch_cfg_present = true; + auto& pdcch_cfg_dedicated = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp.pdcch_cfg; + pdcch_cfg_dedicated.set_setup(); + pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list_present = true; + pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list.resize(1); + pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list[0].ctrl_res_set_id = 2; + pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list[0].freq_domain_res.from_number( + 0b111111110000000000000000000000000000000000000); + pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list[0].dur = 1; + pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list[0].cce_reg_map_type.set_non_interleaved(); + pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list[0].precoder_granularity = + asn1::rrc_nr::ctrl_res_set_s::precoder_granularity_opts::same_as_reg_bundle; + + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.first_active_dl_bwp_id_present = true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.first_active_dl_bwp_id = 1; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg_present = true; + + // search spaces + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list_present = true; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list.resize(1); + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].search_space_id = 2; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].ctrl_res_set_id_present = true; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].ctrl_res_set_id = 2; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].monitoring_slot_periodicity_and_offset_present = true; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].monitoring_slot_periodicity_and_offset.set_sl1(); + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].monitoring_symbols_within_slot_present = true; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].monitoring_symbols_within_slot.from_number( + 0b10000000000000); + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].nrof_candidates_present = true; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].nrof_candidates.aggregation_level1 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level1_opts::n0; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].nrof_candidates.aggregation_level2 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level2_opts::n2; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].nrof_candidates.aggregation_level4 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level4_opts::n1; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].nrof_candidates.aggregation_level8 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level8_opts::n0; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].nrof_candidates.aggregation_level16 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level16_opts::n0; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].search_space_type_present = true; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].search_space_type.set_ue_specific(); + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].search_space_type.ue_specific().dci_formats = asn1:: + rrc_nr::search_space_s::search_space_type_c_::ue_specific_s_::dci_formats_opts::formats0_minus0_and_minus1_minus0; + + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp.pdsch_cfg_present = true; + auto& pdsch_cfg_dedicated = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp.pdsch_cfg; + + pdsch_cfg_dedicated.set_setup(); + pdsch_cfg_dedicated.setup().dmrs_dl_for_pdsch_map_type_a_present = true; + pdsch_cfg_dedicated.setup().dmrs_dl_for_pdsch_map_type_a.set_setup(); + pdsch_cfg_dedicated.setup().dmrs_dl_for_pdsch_map_type_a.setup().dmrs_add_position_present = true; + pdsch_cfg_dedicated.setup().dmrs_dl_for_pdsch_map_type_a.setup().dmrs_add_position = + asn1::rrc_nr::dmrs_dl_cfg_s::dmrs_add_position_opts::pos1; + pdsch_cfg_dedicated.setup().tci_states_to_add_mod_list_present = true; + pdsch_cfg_dedicated.setup().tci_states_to_add_mod_list.resize(1); + pdsch_cfg_dedicated.setup().tci_states_to_add_mod_list[0].tci_state_id = 0; + pdsch_cfg_dedicated.setup().tci_states_to_add_mod_list[0].qcl_type1.ref_sig.set_ssb(); + pdsch_cfg_dedicated.setup().tci_states_to_add_mod_list[0].qcl_type1.ref_sig.ssb() = 0; + pdsch_cfg_dedicated.setup().tci_states_to_add_mod_list[0].qcl_type1.qcl_type = + asn1::rrc_nr::qcl_info_s::qcl_type_opts::type_d; + pdsch_cfg_dedicated.setup().res_alloc = pdsch_cfg_s::res_alloc_opts::res_alloc_type1; + pdsch_cfg_dedicated.setup().rbg_size = asn1::rrc_nr::pdsch_cfg_s::rbg_size_opts::cfg1; + pdsch_cfg_dedicated.setup().prb_bundling_type.set_static_bundling(); + pdsch_cfg_dedicated.setup().prb_bundling_type.static_bundling().bundle_size_present = true; + pdsch_cfg_dedicated.setup().prb_bundling_type.static_bundling().bundle_size = + asn1::rrc_nr::pdsch_cfg_s::prb_bundling_type_c_::static_bundling_s_::bundle_size_opts::wideband; + + // ZP-CSI + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list_present = true; + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list.resize(1); + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].zp_csi_rs_res_id = 0; + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].res_map.freq_domain_alloc.set_row4(); + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].res_map.freq_domain_alloc.row4().from_number(0x100); + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].res_map.nrof_ports = + asn1::rrc_nr::csi_rs_res_map_s::nrof_ports_opts::p4; + + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].res_map.first_ofdm_symbol_in_time_domain = 8; + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].res_map.cdm_type = + asn1::rrc_nr::csi_rs_res_map_s::cdm_type_opts::fd_cdm2; + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].res_map.density.set_one(); + + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].res_map.freq_band.start_rb = 0; + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].res_map.freq_band.nrof_rbs = 52; + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].periodicity_and_offset_present = true; + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].periodicity_and_offset.set_slots80(); + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].periodicity_and_offset.slots80() = 1; + pdsch_cfg_dedicated.setup().p_zp_csi_rs_res_set_present = true; + pdsch_cfg_dedicated.setup().p_zp_csi_rs_res_set.set_setup(); + pdsch_cfg_dedicated.setup().p_zp_csi_rs_res_set.setup().zp_csi_rs_res_set_id = 0; + pdsch_cfg_dedicated.setup().p_zp_csi_rs_res_set.setup().zp_csi_rs_res_id_list.resize(1); + // pdsch_cfg_dedicated.setup().p_zp_csi_rs_res_set.setup().zp_csi_rs_res_id_list[0]= + // pdsch_cfg_dedicated.setup().p_zp_csi_rs_res_set.setup().zp_csi_rs_res_id_list + + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg_present = true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.set_setup(); + + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.new_ue_id = 17943; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.smtc.release(); + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.t304 = recfg_with_sync_s::t304_opts::ms1000; + + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ss_pbch_block_pwr = 0; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dmrs_type_a_position = + asn1::rrc_nr::serving_cell_cfg_common_s::dmrs_type_a_position_opts::pos2; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.pci_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.pci = 500; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_subcarrier_spacing_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_subcarrier_spacing = + subcarrier_spacing_opts::khz30; + + // DL config + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl + .absolute_freq_ssb_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.absolute_freq_ssb = + 632640; + + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.freq_band_list + .push_back(78); + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.absolute_freq_point_a = + 632316; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl + .scs_specific_carrier_list.resize(1); + auto& dl_carrier = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl + .scs_specific_carrier_list[0]; + dl_carrier.offset_to_carrier = 0; + dl_carrier.subcarrier_spacing = subcarrier_spacing_opts::khz15; + dl_carrier.carrier_bw = 52; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp.generic_params + .location_and_bw = 14025; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp.generic_params + .subcarrier_spacing = subcarrier_spacing_opts::khz15; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp + .pdcch_cfg_common_present = true; + auto& pdcch_cfg_common = + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp.pdcch_cfg_common; + pdcch_cfg_common.set_setup(); + pdcch_cfg_common.setup().ext = false; + pdcch_cfg_common.setup().common_ctrl_res_set_present = true; + pdcch_cfg_common.setup().common_ctrl_res_set.ctrl_res_set_id = 1; + pdcch_cfg_common.setup().common_ctrl_res_set.freq_domain_res.from_number( + 0b111111110000000000000000000000000000000000000); + pdcch_cfg_common.setup().common_ctrl_res_set.dur = 1; + pdcch_cfg_common.setup().common_ctrl_res_set.cce_reg_map_type.set_non_interleaved(); + pdcch_cfg_common.setup().common_ctrl_res_set.precoder_granularity = + asn1::rrc_nr::ctrl_res_set_s::precoder_granularity_opts::same_as_reg_bundle; + + // common search space list + pdcch_cfg_common.setup().common_search_space_list_present = true; + pdcch_cfg_common.setup().common_search_space_list.resize(1); + pdcch_cfg_common.setup().common_search_space_list[0].search_space_id = 1; + pdcch_cfg_common.setup().common_search_space_list[0].ctrl_res_set_id_present = true; + pdcch_cfg_common.setup().common_search_space_list[0].ctrl_res_set_id = 1; + pdcch_cfg_common.setup().common_search_space_list[0].search_space_type_present = true; + pdcch_cfg_common.setup().common_search_space_list[0].search_space_type.set_common(); + pdcch_cfg_common.setup() + .common_search_space_list[0] + .search_space_type.common() + .dci_format0_minus0_and_format1_minus0_present = true; + pdcch_cfg_common.setup().common_search_space_list[0].nrof_candidates_present = true; + pdcch_cfg_common.setup().common_search_space_list[0].nrof_candidates.aggregation_level1 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level1_opts::n1; + pdcch_cfg_common.setup().common_search_space_list[0].nrof_candidates.aggregation_level2 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level2_opts::n1; + pdcch_cfg_common.setup().common_search_space_list[0].nrof_candidates.aggregation_level4 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level4_opts::n1; + pdcch_cfg_common.setup().common_search_space_list[0].nrof_candidates.aggregation_level8 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level8_opts::n0; + pdcch_cfg_common.setup().common_search_space_list[0].nrof_candidates.aggregation_level16 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level16_opts::n0; + pdcch_cfg_common.setup().common_search_space_list[0].monitoring_slot_periodicity_and_offset_present = true; + pdcch_cfg_common.setup().common_search_space_list[0].monitoring_slot_periodicity_and_offset.set_sl1(); + pdcch_cfg_common.setup().common_search_space_list[0].monitoring_symbols_within_slot_present = true; + pdcch_cfg_common.setup().common_search_space_list[0].monitoring_symbols_within_slot.from_number(0b10000000000000); + pdcch_cfg_common.setup().ra_search_space_present = true; + pdcch_cfg_common.setup().ra_search_space = 1; + + // PDSCH config common + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp + .pdsch_cfg_common_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp.pdsch_cfg_common + .set_setup(); + auto& pdsch_cfg_common = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp + .pdsch_cfg_common.setup(); + pdsch_cfg_common.pdsch_time_domain_alloc_list_present = true; + pdsch_cfg_common.pdsch_time_domain_alloc_list.resize(1); + pdsch_cfg_common.pdsch_time_domain_alloc_list[0].map_type = pdsch_time_domain_res_alloc_s::map_type_opts::type_a; + pdsch_cfg_common.pdsch_time_domain_alloc_list[0].start_symbol_and_len = 40; + + // UL config + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.dummy = time_align_timer_opts::ms500; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.freq_info_ul_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.freq_info_ul + .scs_specific_carrier_list.resize(1); + auto& ul_carrier = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.freq_info_ul + .scs_specific_carrier_list[0]; + ul_carrier.offset_to_carrier = 0; + ul_carrier.subcarrier_spacing = subcarrier_spacing_opts::khz15; + ul_carrier.carrier_bw = 52; + + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.generic_params + .location_and_bw = 14025; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.generic_params + .subcarrier_spacing = subcarrier_spacing_opts::khz15; + + // RACH config + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common_present = + true; + auto& rach_cfg_common_pack = + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common; + + rach_cfg_common_pack.set_setup(); + rach_cfg_common_pack.setup().rach_cfg_generic.prach_cfg_idx = 0; + rach_cfg_common_pack.setup().rach_cfg_generic.msg1_fdm = rach_cfg_generic_s::msg1_fdm_opts::one; + rach_cfg_common_pack.setup().rach_cfg_generic.msg1_freq_start = 1; + rach_cfg_common_pack.setup().rach_cfg_generic.zero_correlation_zone_cfg = 0; + rach_cfg_common_pack.setup().rach_cfg_generic.preamb_rx_target_pwr = -110; + rach_cfg_common_pack.setup().rach_cfg_generic.preamb_trans_max = + asn1::rrc_nr::rach_cfg_generic_s::preamb_trans_max_opts::n7; + rach_cfg_common_pack.setup().rach_cfg_generic.pwr_ramp_step = + asn1::rrc_nr::rach_cfg_generic_s::pwr_ramp_step_opts::db4; + rach_cfg_common_pack.setup().rach_cfg_generic.ra_resp_win = asn1::rrc_nr::rach_cfg_generic_s::ra_resp_win_opts::sl10; + rach_cfg_common_pack.setup().ra_contention_resolution_timer = + asn1::rrc_nr::rach_cfg_common_s::ra_contention_resolution_timer_opts::sf64; + rach_cfg_common_pack.setup().prach_root_seq_idx.set( + asn1::rrc_nr::rach_cfg_common_s::prach_root_seq_idx_c_::types_opts::l839); + rach_cfg_common_pack.setup().prach_root_seq_idx.set_l839() = 1; + rach_cfg_common_pack.setup().restricted_set_cfg = + asn1::rrc_nr::rach_cfg_common_s::restricted_set_cfg_opts::unrestricted_set; + + // PUSCH config common + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp + .pusch_cfg_common_present = true; + auto& pusch_cfg_common_pack = + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.pusch_cfg_common; + pusch_cfg_common_pack.set_setup(); + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list_present = true; + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list.resize(2); + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list[0].k2_present = true; + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list[0].k2 = 4; + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list[0].map_type = + asn1::rrc_nr::pusch_time_domain_res_alloc_s::map_type_opts::type_a; + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list[0].start_symbol_and_len = 27; + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list[1].k2_present = true; + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list[1].k2 = 3; + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list[1].map_type = + asn1::rrc_nr::pusch_time_domain_res_alloc_s::map_type_opts::type_a; + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list[1].start_symbol_and_len = 27; + pusch_cfg_common_pack.setup().p0_nominal_with_grant = -90; + + // PUCCH config common + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp + .pucch_cfg_common_present = true; + auto& pucch_cfg_common_pack = + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.pucch_cfg_common; + pucch_cfg_common_pack.set_setup(); + pucch_cfg_common_pack.setup().pucch_group_hop = asn1::rrc_nr::pucch_cfg_common_s::pucch_group_hop_opts::neither; + pucch_cfg_common_pack.setup().p0_nominal_present = true; + pucch_cfg_common_pack.setup().p0_nominal = -90; + + // SSB config (optional) + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_positions_in_burst_present = true; + auto& ssb_pos_in_burst = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_positions_in_burst; + ssb_pos_in_burst.set_medium_bitmap().from_number(0b10000000); + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_periodicity_serving_cell_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_periodicity_serving_cell = + serving_cell_cfg_common_s::ssb_periodicity_serving_cell_opts::ms20; + + // TDD UL-DL config + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common_present = true; + auto& tdd_config = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common; + tdd_config.ref_subcarrier_spacing = subcarrier_spacing_e::khz15; + tdd_config.pattern1.dl_ul_tx_periodicity = asn1::rrc_nr::tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms10; + tdd_config.pattern1.nrof_dl_slots = 6; + tdd_config.pattern1.nrof_dl_symbols = 0; + tdd_config.pattern1.nrof_ul_slots = 3; + tdd_config.pattern1.nrof_ul_symbols = 0; + + // make sufficiant space + packed_secondary_cell_config.resize(256); + asn1::bit_ref bref_pack(packed_secondary_cell_config.data(), packed_secondary_cell_config.size()); + if (cell_group_cfg_pack.pack(bref_pack) != asn1::SRSASN_SUCCESS) { + parent->logger.error("Failed to pack NR secondary cell config"); + return SRSRAN_ERROR; + } + packed_secondary_cell_config.resize(bref_pack.distance_bytes()); + return SRSRAN_SUCCESS; +} + +// Packs a hard-coded RRC Reconfiguration with fixed params for all layers (for now) +int rrc_nr::ue::pack_rrc_reconfiguraiton(asn1::dyn_octstring& packed_rrc_reconfig) +{ rrc_recfg_s reconfig; reconfig.rrc_transaction_id = ((transaction_id++) % 4u); rrc_recfg_ies_s& recfg_ies = reconfig.crit_exts.set_rrc_recfg(); - recfg_ies.radio_bearer_cfg_present = true; - recfg_ies.radio_bearer_cfg.drb_to_add_mod_list_present = true; - recfg_ies.radio_bearer_cfg.drb_to_add_mod_list.resize(1); + // add secondary cell group config + recfg_ies.secondary_cell_group_present = true; + if (pack_secondary_cell_group_config(recfg_ies.secondary_cell_group) == SRSRAN_ERROR) { + parent->logger.error("Failed to pack RRC Reconfiguration"); + return SRSRAN_ERROR; + } + + // now pack .. + packed_rrc_reconfig.resize(512); + asn1::bit_ref bref_pack(packed_rrc_reconfig.data(), packed_rrc_reconfig.size()); + if (reconfig.pack(bref_pack) != asn1::SRSASN_SUCCESS) { + parent->logger.error("Failed to pack RRC Reconfiguration"); + return SRSRAN_ERROR; + } + packed_rrc_reconfig.resize(bref_pack.distance_bytes()); + + return SRSRAN_SUCCESS; +} + +// Packs a hard-coded NR radio bearer config with fixed params for RLC/PDCP (for now) +int rrc_nr::ue::pack_nr_radio_bearer_config(asn1::dyn_octstring& packed_nr_bearer_config) +{ + radio_bearer_cfg_s radio_bearer_cfg; + radio_bearer_cfg.drb_to_add_mod_list_present = true; + radio_bearer_cfg.drb_to_add_mod_list.resize(1); // configure fixed DRB1 - auto& drb_item = recfg_ies.radio_bearer_cfg.drb_to_add_mod_list[0]; + auto& drb_item = radio_bearer_cfg.drb_to_add_mod_list[0]; drb_item.drb_id = 1; drb_item.cn_assoc_present = true; drb_item.cn_assoc.set_eps_bearer_id() = 5; @@ -488,27 +815,45 @@ int rrc_nr::ue::handle_sgnb_addition_request(uint16_t eutra_rnti) drb_item.pdcp_cfg.t_reordering_present = true; drb_item.pdcp_cfg.t_reordering = asn1::rrc_nr::pdcp_cfg_s::t_reordering_opts::ms0; - recfg_ies.radio_bearer_cfg.security_cfg_present = true; - recfg_ies.radio_bearer_cfg.security_cfg.key_to_use_present = true; - recfg_ies.radio_bearer_cfg.security_cfg.key_to_use = asn1::rrc_nr::security_cfg_s::key_to_use_opts::secondary; - recfg_ies.radio_bearer_cfg.security_cfg.security_algorithm_cfg_present = true; - recfg_ies.radio_bearer_cfg.security_cfg.security_algorithm_cfg.ciphering_algorithm = ciphering_algorithm_opts::nea2; - - uint8_t buffer[1024]; + radio_bearer_cfg.security_cfg_present = true; + radio_bearer_cfg.security_cfg.key_to_use_present = true; + radio_bearer_cfg.security_cfg.key_to_use = asn1::rrc_nr::security_cfg_s::key_to_use_opts::secondary; + radio_bearer_cfg.security_cfg.security_algorithm_cfg_present = true; + radio_bearer_cfg.security_cfg.security_algorithm_cfg.ciphering_algorithm = ciphering_algorithm_opts::nea2; - asn1::bit_ref bref_pack(buffer, sizeof(buffer)); - radio_bearer_cfg_s& radio_bearer_cfg_pack = recfg_ies.radio_bearer_cfg; - if (radio_bearer_cfg_pack.pack(bref_pack) != asn1::SRSASN_SUCCESS) { + // pack it + packed_nr_bearer_config.resize(128); + asn1::bit_ref bref_pack(packed_nr_bearer_config.data(), packed_nr_bearer_config.size()); + if (radio_bearer_cfg.pack(bref_pack) != asn1::SRSASN_SUCCESS) { parent->logger.error("Failed to pack NR radio bearer config"); - parent->rrc_eutra->sgnb_addition_reject(eutra_rnti); return SRSRAN_ERROR; } - // TODO: fill configs + // resize to packed length + packed_nr_bearer_config.resize(bref_pack.distance_bytes()); + + return SRSRAN_SUCCESS; +} + +int rrc_nr::ue::handle_sgnb_addition_request(uint16_t eutra_rnti) +{ + // provide hard-coded NR configs asn1::dyn_octstring nr_secondary_cell_group_cfg; - asn1::dyn_octstring nr_radio_bearer_config; + if (pack_rrc_reconfiguraiton(nr_secondary_cell_group_cfg) == SRSRAN_ERROR) { + parent->logger.error("Failed to pack RRC Reconfiguration. Sending SgNB addition reject."); + parent->rrc_eutra->sgnb_addition_reject(eutra_rnti); + return SRSRAN_ERROR; + } + + asn1::dyn_octstring radio_bearer_config_buffer; + if (pack_nr_radio_bearer_config(radio_bearer_config_buffer) == SRSRAN_ERROR) { + parent->logger.error("Failed to pack NR radio bearer config. Sending SgNB addition reject."); + parent->rrc_eutra->sgnb_addition_reject(eutra_rnti); + return SRSRAN_ERROR; + } - parent->rrc_eutra->sgnb_addition_ack(eutra_rnti, nr_secondary_cell_group_cfg, nr_radio_bearer_config); + // send response to EUTRA + parent->rrc_eutra->sgnb_addition_ack(eutra_rnti, nr_secondary_cell_group_cfg, radio_bearer_config_buffer); return SRSRAN_SUCCESS; } diff --git a/srsue/src/stack/rrc/rrc_nr.cc b/srsue/src/stack/rrc/rrc_nr.cc index 27be3d7e6..b9a9f4115 100644 --- a/srsue/src/stack/rrc/rrc_nr.cc +++ b/srsue/src/stack/rrc/rrc_nr.cc @@ -574,7 +574,7 @@ bool rrc_nr::apply_sp_cell_init_dl_pdcch(const asn1::rrc_nr::pdcch_cfg_s& pdcch_ phy_cfg.pdcch.search_space[search_space.id] = search_space; phy_cfg.pdcch.search_space_present[search_space.id] = true; } else { - logger.warning("Warning while building search_space structure"); + logger.warning("Warning while building search_space structure id=%d", i); return false; } } @@ -801,7 +801,7 @@ bool rrc_nr::apply_dl_common_cfg(const asn1::rrc_nr::dl_cfg_common_s& dl_cfg_com phy_cfg.pdcch.search_space[search_space.id] = search_space; phy_cfg.pdcch.search_space_present[search_space.id] = true; } else { - logger.warning("Warning while building search_space structure"); + logger.warning("Warning while building search_space structure for common search space"); return false; } } @@ -1137,7 +1137,7 @@ bool rrc_nr::apply_sp_cell_cfg(const sp_cell_cfg_s& sp_cell_cfg) if (make_phy_ssb_cfg(recfg_with_sync.sp_cell_cfg_common, &ssb_cfg) == true) { phy_cfg.ssb = ssb_cfg; } else { - logger.warning("Warning while building ssb structure"); + logger.warning("Warning while building SSB config structure"); return false; } From 64f4767c4fd18981fce28b663e3412bda50843bb Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 16 Jul 2021 15:53:46 +0200 Subject: [PATCH 15/34] Fix NR PUCCH decoder memory access --- lib/src/phy/phch/pucch_nr.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/src/phy/phch/pucch_nr.c b/lib/src/phy/phch/pucch_nr.c index 58264f449..926db626a 100644 --- a/lib/src/phy/phch/pucch_nr.c +++ b/lib/src/phy/phch/pucch_nr.c @@ -560,7 +560,7 @@ static int pucch_nr_format2_encode(srsran_pucch_nr_t* q, return SRSRAN_ERROR; } - // Calculate number of encoded symbols + // Calculate number of encoded bits int e = srsran_uci_nr_pucch_format_2_3_4_E(resource); if (e < SRSRAN_SUCCESS) { ERROR("Error selecting E"); @@ -605,8 +605,13 @@ static int pucch_nr_format2_decode(srsran_pucch_nr_t* q, return SRSRAN_ERROR; } - // Calculate number of encoded symbols - uint32_t E = srsran_uci_nr_pucch_format_2_3_4_E(resource); + // Calculate number of encoded bits + int e = srsran_uci_nr_pucch_format_2_3_4_E(resource); + if (e < SRSRAN_SUCCESS) { + ERROR("Error selecting E"); + return SRSRAN_ERROR; + } + uint32_t E = (uint32_t)e; // Undo mapping to physical resources uint32_t l_start = resource->start_symbol_idx; @@ -634,13 +639,13 @@ static int pucch_nr_format2_decode(srsran_pucch_nr_t* q, } // Equalise - if (srsran_predecoding_single(q->d, q->ce, q->d, NULL, E, 1.0f, chest_res->noise_estimate) < SRSRAN_SUCCESS) { + if (srsran_predecoding_single(q->d, q->ce, q->d, NULL, E / 2, 1.0f, chest_res->noise_estimate) < SRSRAN_SUCCESS) { ERROR("Error Pre-decoding"); return SRSRAN_ERROR; } // Soft-demodulate - if (srsran_demod_soft_demodulate_b(SRSRAN_MOD_QPSK, q->d, llr, E) < SRSRAN_SUCCESS) { + if (srsran_demod_soft_demodulate_b(SRSRAN_MOD_QPSK, q->d, llr, E / 2) < SRSRAN_SUCCESS) { ERROR("Error soft-demodulate"); return SRSRAN_ERROR; } From b264f8fa1e9ee05baf12f8da4fe22a16cc82567c Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 16 Jul 2021 17:08:02 +0200 Subject: [PATCH 16/34] Fix nr_phy_test TSAN warnings --- srsenb/src/phy/nr/slot_worker.cc | 1 - test/phy/CMakeLists.txt | 14 ++++++++++++- test/phy/dummy_gnb_stack.h | 21 ++++++++------------ test/phy/dummy_rx_harq_proc.h | 3 +++ test/phy/dummy_tx_harq_proc.h | 34 +++++++++++++++++++++++++++++--- test/phy/dummy_ue_stack.h | 8 +++----- 6 files changed, 58 insertions(+), 23 deletions(-) diff --git a/srsenb/src/phy/nr/slot_worker.cc b/srsenb/src/phy/nr/slot_worker.cc index 44ff4271f..e7323b33f 100644 --- a/srsenb/src/phy/nr/slot_worker.cc +++ b/srsenb/src/phy/nr/slot_worker.cc @@ -67,7 +67,6 @@ bool slot_worker::init(const args_t& args) return false; } - // Prepare UL arguments srsran_gnb_ul_args_t ul_args = {}; ul_args.pusch.measure_time = true; diff --git a/test/phy/CMakeLists.txt b/test/phy/CMakeLists.txt index 1a071a115..5f797acb9 100644 --- a/test/phy/CMakeLists.txt +++ b/test/phy/CMakeLists.txt @@ -7,6 +7,9 @@ # if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) + set(NR_PHY_TEST_GNB_NOF_THREADS 3) + set(NR_PHY_TEST_UE_NOF_THREADS 3) + add_executable(nr_phy_test nr_phy_test.cc) target_link_libraries(nr_phy_test srsue_phy @@ -23,7 +26,10 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) add_nr_test(nr_phy_test_10MHz_dl_only nr_phy_test --duration=100 --gnb.stack.pdsch.slots=\"0,1,2,3,4,5\" - --gnb.stack.pusch.slots=\"\") + --gnb.stack.pusch.slots=\"\" + --gnb.phy.nof_threads=${NR_PHY_TEST_GNB_NOF_THREADS} + --ue.phy.nof_threads=${NR_PHY_TEST_UE_NOF_THREADS} + ) add_nr_test(nr_phy_test_10MHz_ul_only nr_phy_test --duration=100 # 100 slots @@ -32,6 +38,8 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) --gnb.stack.pusch.start=0 # Start at RB 0 --gnb.stack.pusch.length=52 # Full 10 MHz BW --gnb.stack.pusch.mcs=28 # Maximum MCS + --gnb.phy.nof_threads=${NR_PHY_TEST_GNB_NOF_THREADS} + --ue.phy.nof_threads=${NR_PHY_TEST_UE_NOF_THREADS} ) add_nr_test(nr_phy_test_10MHz_bidir nr_phy_test @@ -44,13 +52,17 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) --gnb.stack.pusch.start=0 # Start at RB 0 --gnb.stack.pusch.length=52 # Full 10 MHz BW --gnb.stack.pusch.mcs=28 # Maximum MCS + --gnb.phy.nof_threads=${NR_PHY_TEST_GNB_NOF_THREADS} + --ue.phy.nof_threads=${NR_PHY_TEST_UE_NOF_THREADS} ) add_nr_test(nr_phy_test_10MHz_prach nr_phy_test --duration=1000 # 100 slots --gnb.stack.pdsch.slots=6 # No PDSCH --gnb.stack.pusch.slots=0 # No PUSCH + --gnb.phy.nof_threads=${NR_PHY_TEST_GNB_NOF_THREADS} --ue.stack.prach.period=30 # Transmit PRACH every 30 radio frames --ue.stack.prach.preamble=10 # Use preamble 10 + --ue.phy.nof_threads=${NR_PHY_TEST_UE_NOF_THREADS} ) endif () diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index e7568ab4d..9d6258ffc 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -47,10 +47,9 @@ private: std::set slots; } dl, ul; srsran::circular_array dl_data_to_ul_ack; - uint32_t ss_id = 0; - srsran_random_t random_gen = nullptr; - srsran::phy_cfg_nr_t phy_cfg = {}; - bool valid = false; + uint32_t ss_id = 0; + srsran::phy_cfg_nr_t phy_cfg = {}; + bool valid = false; std::mutex metrics_mutex; metrics_t metrics = {}; @@ -124,9 +123,8 @@ private: }; std::array pending_pusch = {}; - srsran::circular_array tx_harq_proc; - - srsran::circular_array rx_harq_proc; + dummy_tx_harq_entity tx_harq_proc; + dummy_rx_harq_entity rx_harq_proc; bool schedule_pdsch(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) { @@ -180,9 +178,6 @@ private: // Select grant and set data pdsch.data[0] = tx_harq_proc[slot_cfg.idx].get_tb(pdsch.sch.grant.tb[0].tbs).data(); - // Generate random data - srsran_random_byte_vector(random_gen, pdsch.data[0], pdsch.sch.grant.tb[0].tbs / 8); - // Set softbuffer pdsch.sch.grant.tb[0].softbuffer.tx = &tx_harq_proc[slot_cfg.idx].get_softbuffer(dci.ndi); @@ -292,7 +287,6 @@ public: gnb_dummy_stack(const args_t& args) : rnti(args.rnti), phy_cfg(args.phy_cfg), ss_id(args.ss_id) { - random_gen = srsran_random_init(0x1234); logger.set_level(srslog::str_to_basic_level(args.log_level)); dl.mcs = args.pdsch.mcs; @@ -347,7 +341,7 @@ public: valid = true; } - ~gnb_dummy_stack() { srsran_random_free(random_gen); } + ~gnb_dummy_stack() {} bool is_valid() const { return valid; } int rx_data_indication(rx_data_ind_t& grant) override { return 0; } @@ -411,7 +405,6 @@ public: // Generate data pusch.data[0] = rx_harq_proc[pusch.pid].get_tb(pusch.sch.grant.tb[0].tbs).data(); pusch.data[1] = nullptr; - srsran_random_byte_vector(random_gen, pusch.data[0], pusch.sch.grant.tb[0].tbs / 8); // Put UCI configuration in PUSCH config if (not phy_cfg.get_pusch_uci_cfg(slot_cfg, uci_cfg, pusch.sch)) { @@ -462,6 +455,8 @@ public: return SRSRAN_ERROR; } + // Handle UL-SCH metrics + std::unique_lock lock(metrics_mutex); if (not pusch_info.pusch_data.tb[0].crc) { metrics.mac.rx_errors++; } diff --git a/test/phy/dummy_rx_harq_proc.h b/test/phy/dummy_rx_harq_proc.h index 77ca5c6fa..300553547 100644 --- a/test/phy/dummy_rx_harq_proc.h +++ b/test/phy/dummy_rx_harq_proc.h @@ -61,4 +61,7 @@ public: uint32_t get_tbs() const { return tbs; } }; +class dummy_rx_harq_entity : public srsran::circular_array +{}; + #endif // SRSRAN_DUMMY_RX_HARQ_PROC_H diff --git a/test/phy/dummy_tx_harq_proc.h b/test/phy/dummy_tx_harq_proc.h index 6ae47d873..d3a1631d2 100644 --- a/test/phy/dummy_tx_harq_proc.h +++ b/test/phy/dummy_tx_harq_proc.h @@ -23,9 +23,11 @@ class dummy_tx_harq_proc { private: + mutable std::mutex mutex; + srsran_random_t random_gen = nullptr; srsran::byte_buffer_t data; srsran_softbuffer_tx_t softbuffer = {}; - std::atomic tbs = {0}; + uint32_t tbs = 0; bool first = true; uint32_t ndi = 0; @@ -39,16 +41,26 @@ public: } } - ~dummy_tx_harq_proc() { srsran_softbuffer_tx_free(&softbuffer); } + void init(uint32_t pid) { random_gen = srsran_random_init(pid * 1234); } + + ~dummy_tx_harq_proc() + { + srsran_softbuffer_tx_free(&softbuffer); + srsran_random_free(random_gen); + } srsran::byte_buffer_t& get_tb(uint32_t tbs_) { + std::unique_lock lock(mutex); tbs = tbs_; + srsran_random_byte_vector(random_gen, data.msg, tbs / 8); return data; } srsran_softbuffer_tx_t& get_softbuffer(uint32_t ndi_) { + std::unique_lock lock(mutex); + if (ndi_ != ndi || first) { srsran_softbuffer_tx_reset(&softbuffer); ndi = ndi_; @@ -58,7 +70,23 @@ public: return softbuffer; } - uint32_t get_tbs() const { return tbs; } + uint32_t get_tbs() const + { + std::unique_lock lock(mutex); + return tbs; + } +}; + +class dummy_tx_harq_entity : public srsran::circular_array +{ +public: + dummy_tx_harq_entity() : srsran::circular_array() + { + uint32_t pid = 0; + for (dummy_tx_harq_proc& proc : *this) { + proc.init(pid++); + } + } }; #endif // SRSRAN_TX_DUMMY_HARQ_PROC_H diff --git a/test/phy/dummy_ue_stack.h b/test/phy/dummy_ue_stack.h index 286960c3d..51580aba8 100644 --- a/test/phy/dummy_ue_stack.h +++ b/test/phy/dummy_ue_stack.h @@ -27,7 +27,6 @@ public: }; private: - srsran_random_t random_gen = srsran_random_init(0x4567); uint16_t rnti = 0; bool valid = false; uint32_t sr_period = 0; @@ -37,8 +36,8 @@ private: metrics_t metrics = {}; srsue::phy_interface_stack_nr& phy; - srsran::circular_array tx_harq_proc; - srsran::circular_array rx_harq_proc; + dummy_tx_harq_entity tx_harq_proc; + dummy_rx_harq_entity rx_harq_proc; public: struct args_t { @@ -56,7 +55,7 @@ public: { valid = true; } - ~ue_dummy_stack() { srsran_random_free(random_gen); } + ~ue_dummy_stack() = default; void in_sync() override {} void out_of_sync() override {} void run_tti(const uint32_t tti) override @@ -88,7 +87,6 @@ public: action->tb.enabled = true; action->tb.payload = &tx_harq_proc[grant.pid].get_tb(grant.tbs); action->tb.softbuffer = &tx_harq_proc[grant.pid].get_softbuffer(grant.ndi); - srsran_random_byte_vector(random_gen, action->tb.payload->msg, grant.tbs); } void prach_sent(uint32_t tti, uint32_t s_id, uint32_t t_id, uint32_t f_id, uint32_t ul_carrier_id) override {} bool sr_opportunity(uint32_t tti, uint32_t sr_id, bool meas_gap, bool ul_sch_tx) override From bc072f07d66e13592d6635eecbcffb04ee81f093 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 19 Jul 2021 10:04:56 +0200 Subject: [PATCH 17/34] NR PHY test use 1 PHY thread --- test/phy/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/phy/CMakeLists.txt b/test/phy/CMakeLists.txt index 5f797acb9..034f235fb 100644 --- a/test/phy/CMakeLists.txt +++ b/test/phy/CMakeLists.txt @@ -7,8 +7,8 @@ # if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) - set(NR_PHY_TEST_GNB_NOF_THREADS 3) - set(NR_PHY_TEST_UE_NOF_THREADS 3) + set(NR_PHY_TEST_GNB_NOF_THREADS 1) + set(NR_PHY_TEST_UE_NOF_THREADS 1) add_executable(nr_phy_test nr_phy_test.cc) target_link_libraries(nr_phy_test From 660b66dbe391cb1b4e5aab12897fe86b4d0235b5 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 16 Jul 2021 15:53:12 +0100 Subject: [PATCH 18/34] sched,nr: add option to run phy nr test with real NR scheduler --- srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 4 +- srsenb/src/stack/mac/nr/sched_nr.cc | 3 +- srsenb/src/stack/mac/nr/sched_nr_cfg.cc | 4 +- srsenb/src/stack/mac/nr/sched_nr_helpers.cc | 2 +- srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc | 10 ++- srsenb/src/stack/mac/nr/sched_nr_worker.cc | 25 +++++- srsenb/test/mac/nr/sched_nr_cfg_generators.h | 95 ++++++++++++++++++++ srsenb/test/mac/nr/sched_nr_test.cc | 72 ++------------- test/phy/CMakeLists.txt | 1 + test/phy/dummy_gnb_stack.h | 53 ++++++++++- test/phy/nr_phy_test.cc | 1 + 11 files changed, 191 insertions(+), 79 deletions(-) create mode 100644 srsenb/test/mac/nr/sched_nr_cfg_generators.h diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index 44e140ddf..2c99fa06d 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -71,7 +71,9 @@ public: }; struct ue_cfg_t { - uint32_t maxharq_tx = 4; + uint32_t maxharq_tx = 4; + int fixed_dl_mcs = -1; + int fixed_ul_mcs = -1; srsran::bounded_vector carriers; srsran::phy_cfg_nr_t phy_cfg = {}; }; diff --git a/srsenb/src/stack/mac/nr/sched_nr.cc b/srsenb/src/stack/mac/nr/sched_nr.cc index 3311942f2..77460f88a 100644 --- a/srsenb/src/stack/mac/nr/sched_nr.cc +++ b/srsenb/src/stack/mac/nr/sched_nr.cc @@ -151,7 +151,8 @@ int sched_nr::get_dl_sched(tti_point tti_tx, uint32_t cc, dl_sched_t& result) int sched_nr::get_ul_sched(tti_point tti_rx, uint32_t cc, ul_sched_t& result) { if (not pending_results->has_ul_result(tti_rx, cc)) { - return SRSRAN_ERROR; + // sched result hasn't been generated + return SRSRAN_SUCCESS; } result = pending_results->pop_ul_result(tti_rx, cc); diff --git a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc index 89ad86a49..da954d094 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc @@ -29,8 +29,8 @@ sched_cell_params::sched_cell_params(uint32_t cc_, const cell_cfg_t& cell, const cc(cc_), cell_cfg(cell), sched_cfg(sched_cfg_) { bwps.reserve(cell.bwps.size()); - for (uint32_t i = 0; i < cell.bwps.size(); ++i) { - bwps.emplace_back(cell, sched_cfg_, cc, i); + for (uint32_t i = 0; i < cell_cfg.bwps.size(); ++i) { + bwps.emplace_back(cell_cfg, sched_cfg_, cc, i); } srsran_assert(not bwps.empty(), "No BWPs were configured"); } diff --git a/srsenb/src/stack/mac/nr/sched_nr_helpers.cc b/srsenb/src/stack/mac/nr/sched_nr_helpers.cc index cc9469fa7..a9f4efe4a 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_helpers.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_helpers.cc @@ -75,7 +75,7 @@ void fill_ul_dci_ue_fields(const slot_ue& ue, srsran_dci_location_t dci_pos, srsran_dci_ul_nr_t& dci) { - bool ret = ue.cfg->phy().get_dci_ctx_pdsch_rnti_c(ss_id, dci_pos, ue.rnti, dci.ctx); + bool ret = ue.cfg->phy().get_dci_ctx_pusch_rnti_c(ss_id, dci_pos, ue.rnti, dci.ctx); srsran_assert(ret, "Invalid DL DCI format"); fill_dci_common(ue, bwp_cfg, dci); diff --git a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc index edee6804b..fafa3cd62 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc @@ -45,6 +45,8 @@ void bwp_slot_grid::reset() ul_prbs.reset(); dl_pdcchs.clear(); ul_pdcchs.clear(); + pdschs.clear(); + puschs.clear(); pending_acks.clear(); } @@ -157,7 +159,8 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, const prb_grant& dl_gr // Allocate HARQ if (ue.h_dl->empty()) { - int mcs = 20; + srsran_assert(ue.cfg->ue_cfg()->fixed_dl_mcs >= 0, "Dynamic MCS not yet supported"); + int mcs = ue.cfg->ue_cfg()->fixed_dl_mcs; int tbs = 100; bool ret = ue.h_dl->new_tx(ue.pdsch_tti, ue.uci_tti, dl_grant, mcs, tbs, 4); srsran_assert(ret, "Failed to allocate DL HARQ"); @@ -176,6 +179,7 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, const prb_grant& dl_gr bwp_uci_slot.pending_acks.end(), [&ue](const harq_ack_t& p) { return p.res.rnti == ue.rnti; }); pdcch.dci.dai %= 4; + pdcch.dci_cfg = ue.cfg->phy().get_dci_cfg(); // Generate PUCCH bwp_uci_slot.pending_acks.emplace_back(); @@ -230,7 +234,8 @@ alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, const rbg_bitmap& ul_m } if (ue.h_ul->empty()) { - int mcs = 20; + srsran_assert(ue.cfg->ue_cfg()->fixed_ul_mcs >= 0, "Dynamic MCS not yet supported"); + int mcs = ue.cfg->ue_cfg()->fixed_ul_mcs; int tbs = 100; bool ret = ue.h_ul->new_tx(ue.pusch_tti, ue.pusch_tti, ul_mask, mcs, tbs, ue.cfg->ue_cfg()->maxharq_tx); srsran_assert(ret, "Failed to allocate UL HARQ"); @@ -242,6 +247,7 @@ alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, const rbg_bitmap& ul_m // Generate PDCCH pdcch_ul_t& pdcch = pdcchs.back(); fill_ul_dci_ue_fields(ue, *bwp_grid.cfg, ss_id, pdcch.dci.ctx.location, pdcch.dci); + pdcch.dci_cfg = ue.cfg->phy().get_dci_cfg(); // Generate PUSCH bwp_pusch_slot.ul_prbs.add(ul_mask); diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index 283bd5d9f..e8a1f544d 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -138,12 +138,13 @@ void slot_cc_worker::log_result() const if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_c) { const slot_ue& ue = slot_ues[pdcch.dci.ctx.rnti]; fmt::format_to(fmtbuf, - "SCHED: DL {}, cc={}, rnti=0x{:x}, pid={}, nrtx={}, dai={}, tti_pdsch={}, tti_ack={}", + "SCHED: DL {}, cc={}, rnti=0x{:x}, pid={}, nrtx={}, f={}, dai={}, tti_pdsch={}, tti_ack={}", ue.h_dl->nof_retx() == 0 ? "tx" : "retx", cell.cfg.cc, ue.rnti, - ue.h_dl->pid, + pdcch.dci.pid, ue.h_dl->nof_retx(), + srsran_dci_format_nr_string(pdcch.dci.ctx.format), pdcch.dci.dai, ue.pdsch_tti, ue.uci_tti); @@ -153,6 +154,26 @@ void slot_cc_worker::log_result() const fmt::format_to(fmtbuf, "SCHED: unknown format"); } + logger.info("%s", srsran::to_c_str(fmtbuf)); + } + for (const pdcch_ul_t& pdcch : bwp_slot.ul_pdcchs) { + fmt::memory_buffer fmtbuf; + if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_c) { + const slot_ue& ue = slot_ues[pdcch.dci.ctx.rnti]; + fmt::format_to(fmtbuf, + "SCHED: UL {}, cc={}, rnti=0x{:x}, pid={}, nrtx={}, f={}, tti_pusch={}, tti_ack={}", + ue.h_dl->nof_retx() == 0 ? "tx" : "retx", + cell.cfg.cc, + ue.rnti, + pdcch.dci.pid, + ue.h_dl->nof_retx(), + srsran_dci_format_nr_string(pdcch.dci.ctx.format), + ue.pusch_tti, + ue.uci_tti); + } else { + fmt::format_to(fmtbuf, "SCHED: unknown rnti format"); + } + logger.info("%s", srsran::to_c_str(fmtbuf)); } } diff --git a/srsenb/test/mac/nr/sched_nr_cfg_generators.h b/srsenb/test/mac/nr/sched_nr_cfg_generators.h new file mode 100644 index 000000000..2587b8c24 --- /dev/null +++ b/srsenb/test/mac/nr/sched_nr_cfg_generators.h @@ -0,0 +1,95 @@ +/** + * + * \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_SCHED_NR_CFG_GENERATORS_H +#define SRSRAN_SCHED_NR_CFG_GENERATORS_H + +#include "srsenb/hdr/stack/mac/nr/sched_nr_interface.h" +#include "srsran/common/phy_cfg_nr_default.h" + +namespace srsenb { + +srsran_coreset_t get_default_coreset0() +{ + srsran_coreset_t coreset{}; + coreset.id = 0; + coreset.duration = 1; + coreset.precoder_granularity = srsran_coreset_precoder_granularity_reg_bundle; + for (uint32_t i = 0; i < SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE; ++i) { + coreset.freq_resources[i] = i < 8; + } + return coreset; +} + +sched_nr_interface::cell_cfg_t get_default_cell_cfg(const srsran::phy_cfg_nr_t& phy_cfg) +{ + sched_nr_interface::cell_cfg_t cell_cfg{}; + + cell_cfg.carrier = phy_cfg.carrier; + cell_cfg.tdd = phy_cfg.tdd; + + cell_cfg.bwps.resize(1); + cell_cfg.bwps[0].pdcch = phy_cfg.pdcch; + cell_cfg.bwps[0].pdsch = phy_cfg.pdsch; + cell_cfg.bwps[0].rb_width = phy_cfg.carrier.nof_prb; + + cell_cfg.bwps[0].pdcch.coreset_present[0] = true; + cell_cfg.bwps[0].pdcch.coreset[0] = get_default_coreset0(); + cell_cfg.bwps[0].pdcch.search_space_present[0] = true; + auto& ss = cell_cfg.bwps[0].pdcch.search_space[0]; + ss.id = 0; + ss.coreset_id = 0; + ss.duration = 1; + ss.type = srsran_search_space_type_common_0; + ss.nof_candidates[0] = 1; + ss.nof_candidates[1] = 1; + ss.nof_candidates[2] = 1; + ss.nof_candidates[3] = 0; + ss.nof_candidates[4] = 0; + ss.nof_formats = 1; + ss.formats[0] = srsran_dci_format_nr_1_0; + cell_cfg.bwps[0].pdcch.ra_search_space_present = true; + cell_cfg.bwps[0].pdcch.ra_search_space = cell_cfg.bwps[0].pdcch.search_space[1]; + + return cell_cfg; +} + +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{}}) +{ + std::vector cells; + cells.reserve(nof_sectors); + for (uint32_t i = 0; i < nof_sectors; ++i) { + cells.push_back(get_default_cell_cfg(phy_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{}}) +{ + sched_nr_interface::ue_cfg_t uecfg{}; + uecfg.carriers.resize(nof_cc); + for (uint32_t cc = 0; cc < nof_cc; ++cc) { + uecfg.carriers[cc].cc = cc; + uecfg.carriers[cc].active = true; + } + uecfg.phy_cfg = phy_cfg; + + return uecfg; +} + +} // namespace srsenb + +#endif // SRSRAN_SCHED_NR_CFG_GENERATORS_H diff --git a/srsenb/test/mac/nr/sched_nr_test.cc b/srsenb/test/mac/nr/sched_nr_test.cc index 8daadc738..2704ad637 100644 --- a/srsenb/test/mac/nr/sched_nr_test.cc +++ b/srsenb/test/mac/nr/sched_nr_test.cc @@ -10,6 +10,7 @@ * */ +#include "sched_nr_cfg_generators.h" #include "sched_nr_sim_ue.h" #include "srsenb/hdr/stack/mac/nr/sched_nr.h" #include "srsran/common/phy_cfg_nr_default.h" @@ -24,72 +25,6 @@ using dl_sched_t = sched_nr_interface::dl_sched_t; static const srsran::phy_cfg_nr_t default_phy_cfg = srsran::phy_cfg_nr_default_t{srsran::phy_cfg_nr_default_t::reference_cfg_t{}}; -srsran_coreset_t get_default_coreset0() -{ - srsran_coreset_t coreset{}; - coreset.id = 0; - coreset.duration = 1; - coreset.precoder_granularity = srsran_coreset_precoder_granularity_reg_bundle; - for (uint32_t i = 0; i < SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE; ++i) { - coreset.freq_resources[i] = i < 8; - } - return coreset; -} - -sched_nr_interface::cell_cfg_t get_default_cell_cfg() -{ - sched_nr_interface::cell_cfg_t cell_cfg{}; - - cell_cfg.carrier = default_phy_cfg.carrier; - cell_cfg.tdd = default_phy_cfg.tdd; - - cell_cfg.bwps.resize(1); - cell_cfg.bwps[0].pdcch = default_phy_cfg.pdcch; - cell_cfg.bwps[0].pdsch = default_phy_cfg.pdsch; - cell_cfg.bwps[0].rb_width = default_phy_cfg.carrier.nof_prb; - - cell_cfg.bwps[0].pdcch.coreset_present[0] = true; - cell_cfg.bwps[0].pdcch.coreset[0] = get_default_coreset0(); - cell_cfg.bwps[0].pdcch.search_space_present[0] = true; - auto& ss = cell_cfg.bwps[0].pdcch.search_space[0]; - ss.id = 0; - ss.coreset_id = 0; - ss.duration = 1; - ss.type = srsran_search_space_type_common_0; - ss.nof_candidates[0] = 1; - ss.nof_candidates[1] = 1; - ss.nof_candidates[2] = 1; - ss.nof_candidates[3] = 0; - ss.nof_candidates[4] = 0; - ss.nof_formats = 1; - ss.formats[0] = srsran_dci_format_nr_1_0; - cell_cfg.bwps[0].pdcch.ra_search_space_present = true; - cell_cfg.bwps[0].pdcch.ra_search_space = cell_cfg.bwps[0].pdcch.search_space[1]; - - return cell_cfg; -} -std::vector get_default_cells_cfg(uint32_t nof_sectors) -{ - std::vector cells; - cells.reserve(nof_sectors); - for (uint32_t i = 0; i < nof_sectors; ++i) { - cells.push_back(get_default_cell_cfg()); - } - return cells; -} - -sched_nr_interface::ue_cfg_t get_default_ue_cfg(uint32_t nof_cc) -{ - sched_nr_interface::ue_cfg_t uecfg{}; - uecfg.carriers.resize(nof_cc); - for (uint32_t cc = 0; cc < nof_cc; ++cc) { - uecfg.carriers[cc].active = true; - } - uecfg.phy_cfg = default_phy_cfg; - - return uecfg; -} - struct task_job_manager { std::mutex mutex; int res_count = 0; @@ -151,7 +86,8 @@ void sched_nr_cfg_serialized_test() sched_nr_sim_base sched_tester(cfg, cells_cfg, "Serialized Test"); sched_nr_interface::ue_cfg_t uecfg = get_default_ue_cfg(nof_sectors); - + uecfg.fixed_dl_mcs = 15; + uecfg.fixed_ul_mcs = 15; sched_tester.add_user(0x46, uecfg, 0); std::vector count_per_cc(nof_sectors, 0); @@ -198,6 +134,8 @@ void sched_nr_cfg_parallel_cc_test() sched_nr_sim_base sched_tester(cfg, cells_cfg, "Parallel CC Test"); sched_nr_interface::ue_cfg_t uecfg = get_default_ue_cfg(cells_cfg.size()); + uecfg.fixed_dl_mcs = 15; + uecfg.fixed_ul_mcs = 15; sched_tester.add_user(0x46, uecfg, 0); std::array, SRSRAN_MAX_CARRIERS> nano_count{}; diff --git a/test/phy/CMakeLists.txt b/test/phy/CMakeLists.txt index 034f235fb..bfce9bf25 100644 --- a/test/phy/CMakeLists.txt +++ b/test/phy/CMakeLists.txt @@ -17,6 +17,7 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) srsran_phy srsran_radio srsenb_phy + srsgnb_mac ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index 9d6258ffc..a5828c23d 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -15,6 +15,8 @@ #include "dummy_rx_harq_proc.h" #include "dummy_tx_harq_proc.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr.h" +#include "srsenb/test/mac/nr/sched_nr_cfg_generators.h" #include #include #include @@ -38,8 +40,9 @@ public: }; private: - srslog::basic_logger& logger = srslog::fetch_basic_logger("GNB STK"); - const uint16_t rnti = 0x1234; + srslog::basic_logger& logger = srslog::fetch_basic_logger("GNB STK"); + bool use_dummy_sched = true; + const uint16_t rnti = 0x1234; struct { srsran::circular_array dci_location; uint32_t mcs; @@ -51,6 +54,9 @@ private: srsran::phy_cfg_nr_t phy_cfg = {}; bool valid = false; + srsenb::sched_nr sched; + srsran::tti_point pdsch_tti, pusch_tti; + std::mutex metrics_mutex; metrics_t metrics = {}; @@ -271,6 +277,7 @@ private: public: struct args_t { srsran::phy_cfg_nr_t phy_cfg; ///< Physical layer configuration + bool use_dummy_sched = false; ///< 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 @@ -285,10 +292,21 @@ public: std::string log_level = "warning"; }; - gnb_dummy_stack(const args_t& args) : rnti(args.rnti), phy_cfg(args.phy_cfg), ss_id(args.ss_id) + gnb_dummy_stack(const args_t& args) : + rnti(args.rnti), phy_cfg(args.phy_cfg), ss_id(args.ss_id), sched(srsenb::sched_nr_interface::sched_cfg_t{}) { logger.set_level(srslog::str_to_basic_level(args.log_level)); + // create sched object + std::vector cells_cfg = srsenb::get_default_cells_cfg(1, phy_cfg); + sched.cell_cfg(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); + dl.mcs = args.pdsch.mcs; ul.mcs = args.pusch.mcs; @@ -351,6 +369,26 @@ public: int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) override { logger.set_context(slot_cfg.idx); + if (not pdsch_tti.is_valid()) { + pdsch_tti = srsran::tti_point{slot_cfg.idx}; + } else { + pdsch_tti++; + } + + if (not use_dummy_sched) { + int ret = sched.get_dl_sched(pdsch_tti, 0, dl_sched); + + for (pdsch_t& pdsch : dl_sched.pdsch) { + // Set TBS + // Select grant and set data + pdsch.data[0] = tx_harq_proc[slot_cfg.idx].get_tb(pdsch.sch.grant.tb[0].tbs).data(); + + // Generate random data + srsran_random_byte_vector(random_gen, pdsch.data[0], pdsch.sch.grant.tb[0].tbs / 8); + } + + return ret; + } // Check if it is TDD DL slot and PDSCH mask, if no PDSCH shall be scheduled, do not set any grant and skip if (not srsran_tdd_nr_is_dl(&phy_cfg.tdd, phy_cfg.carrier.scs, slot_cfg.idx)) { @@ -378,6 +416,15 @@ public: int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) override { logger.set_context(slot_cfg.idx); + if (not pusch_tti.is_valid()) { + pusch_tti = srsran::tti_point{slot_cfg.idx}; + } else { + pusch_tti++; + } + + if (not use_dummy_sched) { + return sched.get_ul_sched(pusch_tti, 0, ul_sched); + } // Get ACK information srsran_pdsch_ack_nr_t ack = pending_ack[slot_cfg.idx % pending_ack.size()].get_ack(); diff --git a/test/phy/nr_phy_test.cc b/test/phy/nr_phy_test.cc index 2f2d25a77..6ba631cc1 100644 --- a/test/phy/nr_phy_test.cc +++ b/test/phy/nr_phy_test.cc @@ -54,6 +54,7 @@ test_bench::args_t::args_t(int argc, char** argv) ("gnb.stack.pusch.slots", bpo::value(&gnb_stack.pusch.slots)->default_value(gnb_stack.pusch.slots), "Slots enabled for PUSCH") ("gnb.stack.pusch.mcs", bpo::value(&gnb_stack.pusch.mcs)->default_value(gnb_stack.pusch.mcs), "PUSCH scheduling modulation code scheme") ("gnb.stack.log.level", bpo::value(&gnb_stack.log_level)->default_value(gnb_stack.log_level), "Stack log level") + ("gnb.stack.use_dummy_sched", bpo::value(&gnb_stack.use_dummy_sched)->default_value(true), "Use dummy or real NR scheduler") ; options_gnb_phy.add_options() From c9a5180a09ca27e16248791edaa57fad18e460f3 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 16 Jul 2021 18:19:43 +0100 Subject: [PATCH 19/34] sched,nr: integrate NR scheduler in nr_phy_test The scheduler can be activated via a command line flag --- srsenb/hdr/stack/mac/nr/sched_nr.h | 2 +- srsenb/hdr/stack/mac/nr/sched_nr_harq.h | 18 ++++++++++++------ srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h | 4 ++++ srsenb/hdr/stack/mac/nr/sched_nr_ue.h | 2 +- srsenb/hdr/stack/mac/nr/sched_nr_worker.h | 5 +++-- srsenb/src/stack/mac/nr/sched_nr.cc | 13 ++++++------- srsenb/src/stack/mac/nr/sched_nr_helpers.cc | 11 ++++++----- srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc | 11 +++++++++-- srsenb/src/stack/mac/nr/sched_nr_worker.cc | 19 +++++++++++-------- test/phy/dummy_gnb_stack.h | 19 ++++++++++++++++--- 10 files changed, 69 insertions(+), 35 deletions(-) diff --git a/srsenb/hdr/stack/mac/nr/sched_nr.h b/srsenb/hdr/stack/mac/nr/sched_nr.h index 731897fbe..cccd50e5c 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr.h @@ -45,7 +45,7 @@ public: void ul_sr_info(tti_point tti_rx, uint16_t rnti) override; int get_dl_sched(tti_point pdsch_tti, uint32_t cc, dl_sched_t& result) override; - int get_ul_sched(tti_point pdcch_tti, uint32_t cc, ul_sched_t& result) override; + int get_ul_sched(tti_point pusch_tti, uint32_t cc, ul_sched_t& result) override; private: int generate_slot_result(tti_point pdcch_tti, uint32_t cc); diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_harq.h b/srsenb/hdr/stack/mac/nr/sched_nr_harq.h index 6371f322d..15dee8aaf 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_harq.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_harq.h @@ -80,6 +80,12 @@ public: tx_harq_softbuffer& get_softbuffer() { return *softbuffer; } + bool set_tbs(uint32_t tbs) + { + softbuffer->reset(); + return harq_proc::set_tbs(tbs); + } + private: srsran::unique_pool_ptr softbuffer; }; @@ -115,17 +121,17 @@ public: { return find_dl([this](const dl_harq_proc& h) { return h.has_pending_retx(tti_rx); }); } - harq_proc* find_pending_ul_retx() + ul_harq_proc* find_pending_ul_retx() { - return find_ul([this](const harq_proc& h) { return h.has_pending_retx(tti_rx); }); + return find_ul([this](const ul_harq_proc& h) { return h.has_pending_retx(tti_rx); }); } dl_harq_proc* find_empty_dl_harq() { - return find_dl([](const harq_proc& h) { return h.empty(); }); + return find_dl([](const dl_harq_proc& h) { return h.empty(); }); } - harq_proc* find_empty_ul_harq() + ul_harq_proc* find_empty_ul_harq() { - return find_ul([](const harq_proc& h) { return h.empty(); }); + return find_ul([](const ul_harq_proc& h) { return h.empty(); }); } private: @@ -136,7 +142,7 @@ private: return (it == dl_harqs.end()) ? nullptr : &(*it); } template - harq_proc* find_ul(Predicate p) + ul_harq_proc* find_ul(Predicate p) { auto it = std::find_if(ul_harqs.begin(), ul_harqs.end(), p); return (it == ul_harqs.end()) ? nullptr : &(*it); diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h index ceddac4a1..a1425baf1 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h @@ -72,6 +72,10 @@ private: srsran::bounded_vector slots; }; +/** + * Class responsible for jointly filling the DL/UL sched result fields and allocate RB/PDCCH resources in the RB grid + * to avoid potential RB/PDCCH collisions + */ class bwp_slot_allocator { public: diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h index 53e11dc44..041aa2566 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h @@ -52,7 +52,7 @@ public: uint32_t dl_cqi; uint32_t ul_cqi; dl_harq_proc* h_dl = nullptr; - harq_proc* h_ul = nullptr; + ul_harq_proc* h_ul = nullptr; }; class ue_carrier diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h index bd39285e6..a08d4df8e 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h @@ -90,8 +90,7 @@ public: sched_worker_manager(sched_worker_manager&&) = delete; ~sched_worker_manager(); - void run_slot(tti_point tti_tx, uint32_t cc); - bool save_sched_result(tti_point pdcch_tti, uint32_t cc, dl_sched_t& dl_res, ul_sched_t& ul_res); + void run_slot(tti_point tti_tx, uint32_t cc, dl_sched_t& dl_res, ul_sched_t& ul_res); void enqueue_event(uint16_t rnti, srsran::move_callback ev); void enqueue_cc_feedback(uint16_t rnti, uint32_t cc, slot_cc_worker::feedback_callback_t fdbk) @@ -100,6 +99,8 @@ public: } private: + bool save_sched_result(tti_point pdcch_tti, uint32_t cc, dl_sched_t& dl_res, ul_sched_t& ul_res); + const sched_params& cfg; ue_map_t& ue_db; srsran::span > cells; diff --git a/srsenb/src/stack/mac/nr/sched_nr.cc b/srsenb/src/stack/mac/nr/sched_nr.cc index 77460f88a..b97523623 100644 --- a/srsenb/src/stack/mac/nr/sched_nr.cc +++ b/srsenb/src/stack/mac/nr/sched_nr.cc @@ -128,13 +128,12 @@ void sched_nr::ue_cfg_impl(uint16_t rnti, const ue_cfg_t& uecfg) /// Generate {tti,cc} scheduling decision int sched_nr::generate_slot_result(tti_point pdcch_tti, uint32_t cc) { - // Generate {slot_idx,cc} result - sched_workers->run_slot(pdcch_tti, cc); - // Copy results to intermediate buffer dl_sched_t& dl_res = pending_results->add_dl_result(pdcch_tti, cc); ul_sched_t& ul_res = pending_results->add_ul_result(pdcch_tti, cc); - sched_workers->save_sched_result(pdcch_tti, cc, dl_res, ul_res); + + // Generate {slot_idx,cc} result + sched_workers->run_slot(pdcch_tti, cc, dl_res, ul_res); return SRSRAN_SUCCESS; } @@ -148,14 +147,14 @@ int sched_nr::get_dl_sched(tti_point tti_tx, uint32_t cc, dl_sched_t& result) result = pending_results->pop_dl_result(tti_tx, cc); return SRSRAN_SUCCESS; } -int sched_nr::get_ul_sched(tti_point tti_rx, uint32_t cc, ul_sched_t& result) +int sched_nr::get_ul_sched(tti_point pusch_tti, uint32_t cc, ul_sched_t& result) { - if (not pending_results->has_ul_result(tti_rx, cc)) { + if (not pending_results->has_ul_result(pusch_tti, cc)) { // sched result hasn't been generated return SRSRAN_SUCCESS; } - result = pending_results->pop_ul_result(tti_rx, cc); + result = pending_results->pop_ul_result(pusch_tti, cc); return SRSRAN_SUCCESS; } diff --git a/srsenb/src/stack/mac/nr/sched_nr_helpers.cc b/srsenb/src/stack/mac/nr/sched_nr_helpers.cc index a9f4efe4a..32a901272 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_helpers.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_helpers.cc @@ -34,11 +34,12 @@ void fill_dci_common(const slot_ue& ue, const bwp_params& bwp_cfg, DciDlOrUl& dc dci.cc_id = ue.cc; dci.tpc = 1; // harq - harq_proc* h = std::is_same::value ? ue.h_dl : ue.h_ul; - dci.pid = h->pid; - dci.ndi = h->ndi(); - dci.mcs = h->mcs(); - dci.rv = rv_idx[h->nof_retx() % 4]; + harq_proc* h = std::is_same::value ? static_cast(ue.h_dl) + : static_cast(ue.h_ul); + dci.pid = h->pid; + dci.ndi = h->ndi(); + dci.mcs = h->mcs(); + dci.rv = rv_idx[h->nof_retx() % 4]; // PRB assignment const prb_grant& grant = h->prbs(); if (grant.is_alloc_type0()) { diff --git a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc index fafa3cd62..49affafa3 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc @@ -195,12 +195,12 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, const prb_grant& dl_gr slot_cfg.idx = ue.pdsch_tti.sf_idx(); bool ret = ue.cfg->phy().get_pdsch_cfg(slot_cfg, pdcch.dci, pdsch.sch); srsran_assert(ret, "Error converting DCI to grant"); + pdsch.sch.grant.tb[0].softbuffer.tx = ue.h_dl->get_softbuffer().get(); if (ue.h_dl->nof_retx() == 0) { ue.h_dl->set_tbs(pdsch.sch.grant.tb[0].tbs); // update HARQ with correct TBS } else { srsran_assert(pdsch.sch.grant.tb[0].tbs == (int)ue.h_dl->tbs(), "The TBS did not remain constant in retx"); } - pdsch.sch.grant.tb[0].softbuffer.tx = ue.h_dl->get_softbuffer().get(); return alloc_result::success; } @@ -249,7 +249,14 @@ alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, const rbg_bitmap& ul_m fill_ul_dci_ue_fields(ue, *bwp_grid.cfg, ss_id, pdcch.dci.ctx.location, pdcch.dci); pdcch.dci_cfg = ue.cfg->phy().get_dci_cfg(); // Generate PUSCH - bwp_pusch_slot.ul_prbs.add(ul_mask); + bwp_pusch_slot.ul_prbs |= ul_mask; + bwp_pusch_slot.puschs.emplace_back(); + pusch_t& pusch = bwp_pusch_slot.puschs.back(); + srsran_slot_cfg_t slot_cfg; + slot_cfg.idx = ue.pusch_tti.sf_idx(); + bool ret = ue.cfg->phy().get_pusch_cfg(slot_cfg, pdcch.dci, pusch.sch); + srsran_assert(ret, "Error converting DCI to PUSCH grant"); + pusch.sch.grant.tb[0].softbuffer.rx = ue.h_ul->get_softbuffer().get(); return alloc_result::success; } diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index e8a1f544d..7c25a02fd 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -161,15 +161,14 @@ void slot_cc_worker::log_result() const if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_c) { const slot_ue& ue = slot_ues[pdcch.dci.ctx.rnti]; fmt::format_to(fmtbuf, - "SCHED: UL {}, cc={}, rnti=0x{:x}, pid={}, nrtx={}, f={}, tti_pusch={}, tti_ack={}", + "SCHED: UL {}, cc={}, rnti=0x{:x}, pid={}, nrtx={}, f={}, tti_pusch={}", ue.h_dl->nof_retx() == 0 ? "tx" : "retx", cell.cfg.cc, ue.rnti, pdcch.dci.pid, ue.h_dl->nof_retx(), srsran_dci_format_nr_string(pdcch.dci.ctx.format), - ue.pusch_tti, - ue.uci_tti); + ue.pusch_tti); } else { fmt::format_to(fmtbuf, "SCHED: unknown rnti format"); } @@ -199,7 +198,7 @@ void sched_worker_manager::enqueue_event(uint16_t rnti, srsran::move_callback waiting_cvars; { @@ -281,10 +280,14 @@ void sched_worker_manager::run_slot(tti_point tti_tx, uint32_t cc) c->notify_one(); } } + + // Copy results to intermediate buffer + save_sched_result(tti_tx, cc, dl_res, ul_res); } bool sched_worker_manager::save_sched_result(tti_point pdcch_tti, uint32_t cc, dl_sched_t& dl_res, ul_sched_t& ul_res) { + // NOTE: Unlocked region auto& bwp_slot = cells[cc]->bwps[0].grid[pdcch_tti]; dl_res.pdcch_dl = bwp_slot.dl_pdcchs; @@ -313,15 +316,15 @@ bool sched_worker_manager::save_sched_result(tti_point pdcch_tti, uint32_t cc, d if (uci_cfg.ack.count > 0 || uci_cfg.nof_csi > 0 || uci_cfg.o_sr > 0) { if (not ul_res.pusch.empty()) { // Put UCI configuration in PUSCH config - srsran_assert(phy_cfg->get_pusch_uci_cfg(slot_cfg, uci_cfg, ul_res.pusch[0].sch), - "Error setting UCI configuration in PUSCH"); + bool ret = phy_cfg->get_pusch_uci_cfg(slot_cfg, uci_cfg, ul_res.pusch[0].sch); + srsran_assert(ret, "Error setting UCI configuration in PUSCH"); } else { // Put UCI configuration in PUCCH config ul_res.pucch.emplace_back(); pucch_t& pucch = ul_res.pucch.back(); pucch.uci_cfg = uci_cfg; - srsran_assert(phy_cfg->get_pucch_uci_cfg(slot_cfg, pucch.uci_cfg, pucch.pucch_cfg, pucch.resource), - "Error getting PUCCH UCI cfg"); + bool ret = phy_cfg->get_pucch_uci_cfg(slot_cfg, pucch.uci_cfg, pucch.pucch_cfg, pucch.resource); + srsran_assert(ret, "Error getting PUCCH UCI cfg"); } } } diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index a5828c23d..98fdd533e 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -277,7 +277,7 @@ private: public: struct args_t { srsran::phy_cfg_nr_t phy_cfg; ///< Physical layer configuration - bool use_dummy_sched = false; ///< Use dummy or real NR scheduler + 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 @@ -293,7 +293,11 @@ public: }; gnb_dummy_stack(const args_t& args) : - rnti(args.rnti), phy_cfg(args.phy_cfg), ss_id(args.ss_id), sched(srsenb::sched_nr_interface::sched_cfg_t{}) + rnti(args.rnti), + phy_cfg(args.phy_cfg), + ss_id(args.ss_id), + sched(srsenb::sched_nr_interface::sched_cfg_t{}), + use_dummy_sched(args.use_dummy_sched) { logger.set_level(srslog::str_to_basic_level(args.log_level)); @@ -382,6 +386,7 @@ public: // Set TBS // Select grant and set data pdsch.data[0] = tx_harq_proc[slot_cfg.idx].get_tb(pdsch.sch.grant.tb[0].tbs).data(); + pdsch.data[1] = nullptr; // Generate random data srsran_random_byte_vector(random_gen, pdsch.data[0], pdsch.sch.grant.tb[0].tbs / 8); @@ -423,7 +428,15 @@ public: } if (not use_dummy_sched) { - return sched.get_ul_sched(pusch_tti, 0, ul_sched); + int ret = sched.get_ul_sched(pusch_tti, 0, ul_sched); + + for (pusch_t& pusch : ul_sched.pusch) { + pusch.data[0] = rx_harq_proc[pusch.pid].get_tb(pusch.sch.grant.tb[0].tbs).data(); + pusch.data[1] = nullptr; + srsran_random_byte_vector(random_gen, pusch.data[0], pusch.sch.grant.tb[0].tbs / 8); + } + + return ret; } // Get ACK information From 7842cedb753584f949da6dd3a3ada6cfc80ac690 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 19 Jul 2021 16:36:36 +0200 Subject: [PATCH 20/34] Fix compilation. --- test/phy/dummy_gnb_stack.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index 98fdd533e..828332142 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -387,9 +387,6 @@ public: // Select grant and set data pdsch.data[0] = tx_harq_proc[slot_cfg.idx].get_tb(pdsch.sch.grant.tb[0].tbs).data(); pdsch.data[1] = nullptr; - - // Generate random data - srsran_random_byte_vector(random_gen, pdsch.data[0], pdsch.sch.grant.tb[0].tbs / 8); } return ret; @@ -433,7 +430,6 @@ public: for (pusch_t& pusch : ul_sched.pusch) { pusch.data[0] = rx_harq_proc[pusch.pid].get_tb(pusch.sch.grant.tb[0].tbs).data(); pusch.data[1] = nullptr; - srsran_random_byte_vector(random_gen, pusch.data[0], pusch.sch.grant.tb[0].tbs / 8); } return ret; From 4f0f6169f5047dd27f7ebb9f4775e812941b3890 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Thu, 15 Jul 2021 15:43:24 +0200 Subject: [PATCH 21/34] Added NGAP Metrics --- srsenb/hdr/stack/ngap/ngap.h | 2 ++ srsenb/hdr/stack/ngap/ngap_metrics.h | 30 ++++++++++++++++++++++++++++ srsenb/src/stack/ngap/ngap.cc | 13 ++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 srsenb/hdr/stack/ngap/ngap_metrics.h diff --git a/srsenb/hdr/stack/ngap/ngap.h b/srsenb/hdr/stack/ngap/ngap.h index 9ee160629..8556be68f 100644 --- a/srsenb/hdr/stack/ngap/ngap.h +++ b/srsenb/hdr/stack/ngap/ngap.h @@ -12,6 +12,7 @@ #ifndef SRSENB_NGAP_H #define SRSENB_NGAP_H +#include "ngap_metrics.h" #include "srsenb/hdr/common/common_enb.h" #include "srsran/adt/circular_map.h" #include "srsran/adt/optional.h" @@ -66,6 +67,7 @@ public: // Stack interface bool handle_amf_rx_msg(srsran::unique_byte_buffer_t pdu, const sockaddr_in& from, const sctp_sndrcvinfo& sri, int flags); + void get_metrics(ngap_metrics_t& m); private: static const int AMF_PORT = 38412; diff --git a/srsenb/hdr/stack/ngap/ngap_metrics.h b/srsenb/hdr/stack/ngap/ngap_metrics.h new file mode 100644 index 000000000..fb3dc843a --- /dev/null +++ b/srsenb/hdr/stack/ngap/ngap_metrics.h @@ -0,0 +1,30 @@ +/** + * + * \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 SRSENB_NGAP_METRICS_H +#define SRSENB_NGAP_METRICS_H + +namespace srsenb { + +typedef enum { + ngap_attaching = 0, // Attempting to create NG connection + ngap_connected, // NG connected + ngap_error // Failure +} ngap_status_t; + +struct ngap_metrics_t { + ngap_status_t status; +}; + +} // namespace srsenb + +#endif // SRSENB_NGAP_METRICS_H diff --git a/srsenb/src/stack/ngap/ngap.cc b/srsenb/src/stack/ngap/ngap.cc index 8cbca6fee..7aa2390a8 100644 --- a/srsenb/src/stack/ngap/ngap.cc +++ b/srsenb/src/stack/ngap/ngap.cc @@ -143,6 +143,19 @@ void ngap::stop() amf_socket.close(); } +void ngap::get_metrics(ngap_metrics_t& m) +{ + if (!running) { + m.status = ngap_error; + return; + } + if (amf_connected) { + m.status = ngap_connected; + } else { + m.status = ngap_attaching; + } +} + bool ngap::is_amf_connected() { return amf_connected; From 880eb6fc14d38a9890f288a3dad6f3c1fa5b837c Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Fri, 16 Jul 2021 16:41:52 +0200 Subject: [PATCH 22/34] Added git args --- srsenb/hdr/stack/ngap/ngap.h | 1 + srsenb/src/stack/ngap/ngap.cc | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/srsenb/hdr/stack/ngap/ngap.h b/srsenb/hdr/stack/ngap/ngap.h index 8556be68f..8220285fb 100644 --- a/srsenb/hdr/stack/ngap/ngap.h +++ b/srsenb/hdr/stack/ngap/ngap.h @@ -68,6 +68,7 @@ public: bool handle_amf_rx_msg(srsran::unique_byte_buffer_t pdu, const sockaddr_in& from, const sctp_sndrcvinfo& sri, int flags); void get_metrics(ngap_metrics_t& m); + void get_args(ngap_args_t& args_); private: static const int AMF_PORT = 38412; diff --git a/srsenb/src/stack/ngap/ngap.cc b/srsenb/src/stack/ngap/ngap.cc index 7aa2390a8..1410e2cf0 100644 --- a/srsenb/src/stack/ngap/ngap.cc +++ b/srsenb/src/stack/ngap/ngap.cc @@ -156,6 +156,11 @@ void ngap::get_metrics(ngap_metrics_t& m) } } +void ngap::get_args(ngap_args_t& args_) +{ + args_ = args; +} + bool ngap::is_amf_connected() { return amf_connected; From d783fbf3a0457900fc153b3dcd162e1bdb0b1ad6 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 16 Jul 2021 19:08:10 +0200 Subject: [PATCH 23/34] Reviewed NR procedure for PUCCH resource sselection and reviewed gNb PUCCH interface --- .../srsran/interfaces/gnb_interfaces.h | 16 ++++-- lib/src/phy/phch/ra_ul_nr.c | 54 +++++++++++++++++-- srsenb/src/phy/nr/slot_worker.cc | 7 +-- test/phy/dummy_gnb_stack.h | 4 +- 4 files changed, 70 insertions(+), 11 deletions(-) diff --git a/lib/include/srsran/interfaces/gnb_interfaces.h b/lib/include/srsran/interfaces/gnb_interfaces.h index 9f41130d8..a78c1b50b 100644 --- a/lib/include/srsran/interfaces/gnb_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_interfaces.h @@ -243,10 +243,20 @@ public: std::array data = {}; ///< Data pointer }; + /** + * @brief Describes a possible PUCCH candidate transmission + * @note The physical layer shall try decoding all the possible PUCCH candidates and report back to the stack the + * strongest of the candidates. This is thought to be used in the case of SR opportunities in which the UE could + * transmit HARQ-ACK in two possible resources. + */ + struct pucch_candidate_t { + srsran_uci_cfg_nr_t uci_cfg; ///< UCI configuration for the opportunity + srsran_pucch_nr_resource_t resource; ///< PUCCH resource to use + }; + struct pucch_t { - srsran_uci_cfg_nr_t uci_cfg; ///< UCI configuration - srsran_pucch_nr_common_cfg_t pucch_cfg; ///< UE dedicated PUCCH configuration - srsran_pucch_nr_resource_t resource; ///< PUCCH resource + srsran_pucch_nr_common_cfg_t pucch_cfg; ///< UE dedicated PUCCH configuration + srsran::bounded_vector candidates; ///< PUCCH candidates to decode }; struct ul_sched_t { diff --git a/lib/src/phy/phch/ra_ul_nr.c b/lib/src/phy/phch/ra_ul_nr.c index 1f6a03332..4654d759f 100644 --- a/lib/src/phy/phch/ra_ul_nr.c +++ b/lib/src/phy/phch/ra_ul_nr.c @@ -528,10 +528,9 @@ int srsran_ra_ul_nr_pucch_resource(const srsran_pucch_nr_hl_cfg_t* pucch_cfg, // Use SR PUCCH resource // - At least one positive SR - // - up to 2 HARQ-ACK + // - No HARQ-ACK // - No CSI report - if (uci_cfg->sr_positive_present > 0 && uci_cfg->ack.count <= SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS && - uci_cfg->nof_csi == 0) { + if (uci_cfg->sr_positive_present > 0 && uci_cfg->ack.count == 0 && uci_cfg->nof_csi == 0) { uint32_t sr_resource_id = uci_cfg->pucch.sr_resource_id; if (sr_resource_id >= SRSRAN_PUCCH_MAX_NOF_SR_RESOURCES) { ERROR("SR resource ID (%d) exceeds the maximum ID (%d)", sr_resource_id, SRSRAN_PUCCH_MAX_NOF_SR_RESOURCES); @@ -550,6 +549,55 @@ int srsran_ra_ul_nr_pucch_resource(const srsran_pucch_nr_hl_cfg_t* pucch_cfg, return SRSRAN_SUCCESS; } + // Use SR PUCCH resource + // - At least one positive SR + // - up to 2 HARQ-ACK + // - No CSI report + if (uci_cfg->sr_positive_present > 0 && uci_cfg->ack.count <= SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS && + uci_cfg->nof_csi == 0) { + uint32_t sr_resource_id = uci_cfg->pucch.sr_resource_id; + if (sr_resource_id >= SRSRAN_PUCCH_MAX_NOF_SR_RESOURCES) { + ERROR("SR resource ID (%d) exceeds the maximum ID (%d)", sr_resource_id, SRSRAN_PUCCH_MAX_NOF_SR_RESOURCES); + return SRSRAN_ERROR; + } + + if (!pucch_cfg->sr_resources[sr_resource_id].configured) { + ERROR("SR resource ID (%d) is not configured", sr_resource_id); + return SRSRAN_ERROR; + } + + // Select PUCCH resource for SR + srsran_pucch_nr_resource_t resource_sr = pucch_cfg->sr_resources[sr_resource_id].resource; + + // Select PUCCH resource for HARQ-ACK + srsran_pucch_nr_resource_t resource_harq = {}; + if (ra_ul_nr_pucch_resource_hl(pucch_cfg, O_uci, uci_cfg->pucch.resource_id, &resource_harq) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + + // If a UE would transmit positive or negative SR in a resource using PUCCH format 0 and HARQ-ACK information bits + // in a resource using PUCCH format 1 in a slot, the UE transmits only a PUCCH with the HARQ-ACK information bits + // in the resource using PUCCH format 1. + if (resource_sr.format == SRSRAN_PUCCH_NR_FORMAT_0 && resource_harq.format == SRSRAN_PUCCH_NR_FORMAT_1) { + *resource = resource_harq; + return SRSRAN_SUCCESS; + } + + // If the UE would transmit positive SR in a first resource using PUCCH format 1 and at most two HARQ-ACK + // information bits in a second resource using PUCCH format 1 in a slot, the UE transmits a PUCCH with HARQ-ACK + // information bits in the first resource using PUCCH format 1 as described in Clause 9.2.3. If a UE would transmit + // negative SR in a resource using PUCCH format 1 and at most two HARQ-ACK information bits in a resource using + // PUCCH format 1 in a slot, the UE transmits a PUCCH in the resource using PUCCH format 1 for HARQ-ACK + // information as described in Clause 9.2.3. + if (resource_sr.format == SRSRAN_PUCCH_NR_FORMAT_1 && resource_harq.format == SRSRAN_PUCCH_NR_FORMAT_1) { + *resource = resource_sr; + return SRSRAN_SUCCESS; + } + + // The impossible happened... + return SRSRAN_ERROR; + } + // Use format 2, 3 or 4 resource from higher layers // - Irrelevant SR opportunities // - More than 2 HARQ-ACK diff --git a/srsenb/src/phy/nr/slot_worker.cc b/srsenb/src/phy/nr/slot_worker.cc index e7323b33f..64bcead67 100644 --- a/srsenb/src/phy/nr/slot_worker.cc +++ b/srsenb/src/phy/nr/slot_worker.cc @@ -149,13 +149,13 @@ bool slot_worker::work_ul() // For each PUCCH... for (stack_interface_phy_nr::pucch_t& pucch : ul_sched.pucch) { stack_interface_phy_nr::pucch_info_t pucch_info = {}; - pucch_info.uci_data.cfg = pucch.uci_cfg; + pucch_info.uci_data.cfg = pucch.candidates[0].uci_cfg; // Decode PUCCH if (srsran_gnb_ul_get_pucch(&gnb_ul, &ul_slot_cfg, &pucch.pucch_cfg, - &pucch.resource, + &pucch.candidates[0].resource, &pucch_info.uci_data.cfg, &pucch_info.uci_data.value) < SRSRAN_SUCCESS) { logger.error("Error getting PUCCH"); @@ -171,7 +171,8 @@ bool slot_worker::work_ul() // Log PUCCH decoding if (logger.info.enabled()) { std::array str; - srsran_gnb_ul_pucch_info(&gnb_ul, &pucch.resource, &pucch_info.uci_data, str.data(), (uint32_t)str.size()); + srsran_gnb_ul_pucch_info( + &gnb_ul, &pucch.candidates[0].resource, &pucch_info.uci_data, str.data(), (uint32_t)str.size()); logger.info("PUCCH: %s", str.data()); } diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index 828332142..ad2a23fb2 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -475,8 +475,8 @@ public: // If any UCI information is triggered, schedule PUCCH if (uci_cfg.ack.count > 0 || uci_cfg.nof_csi > 0 || uci_cfg.o_sr > 0) { mac_interface_phy_nr::pucch_t pucch = {}; - pucch.uci_cfg = uci_cfg; - if (not phy_cfg.get_pucch_uci_cfg(slot_cfg, uci_cfg, pucch.pucch_cfg, pucch.resource)) { + pucch.candidates[0].uci_cfg = uci_cfg; + if (not phy_cfg.get_pucch_uci_cfg(slot_cfg, uci_cfg, pucch.pucch_cfg, pucch.candidates[0].resource)) { logger.error("Error getting UCI CFG"); return SRSRAN_ERROR; } From 6a9baef11ddfe8d4d4cd18d9424ebb0f728b77ef Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 19 Jul 2021 15:44:08 +0200 Subject: [PATCH 24/34] Limit DMRS PUCCH SNR to void NAN/INF --- lib/src/phy/ch_estimation/dmrs_pucch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/phy/ch_estimation/dmrs_pucch.c b/lib/src/phy/ch_estimation/dmrs_pucch.c index 7a045c325..cae4cac58 100644 --- a/lib/src/phy/ch_estimation/dmrs_pucch.c +++ b/lib/src/phy/ch_estimation/dmrs_pucch.c @@ -238,7 +238,7 @@ int srsran_dmrs_pucch_format1_estimate(const srsran_pucch_nr_t* q, res->rsrp_dBfs = srsran_convert_power_to_dB(rsrp); res->epre = epre; res->epre_dBfs = srsran_convert_power_to_dB(epre); - res->noise_estimate = epre - rsrp; + res->noise_estimate = SRSRAN_MAX(epre - rsrp, 1e-6f); res->noise_estimate_dbm = srsran_convert_power_to_dB(res->noise_estimate); res->snr = rsrp / res->noise_estimate; res->snr_db = srsran_convert_power_to_dB(res->snr); @@ -398,7 +398,7 @@ int srsran_dmrs_pucch_format2_estimate(const srsran_pucch_nr_t* q, res->rsrp_dBfs = srsran_convert_power_to_dB(rsrp); res->epre = epre; res->epre_dBfs = srsran_convert_power_to_dB(epre); - res->noise_estimate = epre - rsrp; + res->noise_estimate = SRSRAN_MAX(epre - rsrp, 1e-6f); res->noise_estimate_dbm = srsran_convert_power_to_dB(res->noise_estimate); res->snr = rsrp / res->noise_estimate; res->snr_db = srsran_convert_power_to_dB(res->snr); From bb4f4697947c456e7def6b774b835739fb6b0078 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 19 Jul 2021 15:46:16 +0200 Subject: [PATCH 25/34] Integrated SR decoder in gNb --- .../srsran/interfaces/gnb_interfaces.h | 16 ++-- lib/include/srsran/phy/gnb/gnb_ul.h | 3 +- lib/src/common/phy_cfg_nr.cc | 15 +++- lib/src/phy/gnb/gnb_ul.c | 36 +++++++- lib/src/phy/phch/ra_ul_nr.c | 24 +++--- srsenb/src/phy/nr/slot_worker.cc | 48 +++++++---- srsenb/src/stack/mac/nr/sched_nr_worker.cc | 27 +++++- srsue/src/phy/nr/sf_worker.cc | 2 +- test/phy/CMakeLists.txt | 32 ++++++- test/phy/dummy_gnb_stack.h | 86 ++++++++++++++++--- test/phy/dummy_ue_stack.h | 12 ++- test/phy/nr_phy_test.cc | 42 ++++++++- 12 files changed, 277 insertions(+), 66 deletions(-) diff --git a/lib/include/srsran/interfaces/gnb_interfaces.h b/lib/include/srsran/interfaces/gnb_interfaces.h index a78c1b50b..9c6387f7d 100644 --- a/lib/include/srsran/interfaces/gnb_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_interfaces.h @@ -206,9 +206,11 @@ public: class mac_interface_phy_nr { public: - const static int MAX_SSB = 4; - const static int MAX_GRANTS = 64; - const static int MAX_NZP_CSI_RS = 4; + const static int MAX_SSB = 4; + const static int MAX_GRANTS = 64; + const static int MAX_PUCCH_MSG = 64; + const static int MAX_PUCCH_CANDIDATES = 2; + const static int MAX_NZP_CSI_RS = 4; struct pdcch_dl_t { srsran_dci_cfg_nr_t dci_cfg = {}; @@ -255,8 +257,8 @@ public: }; struct pucch_t { - srsran_pucch_nr_common_cfg_t pucch_cfg; ///< UE dedicated PUCCH configuration - srsran::bounded_vector candidates; ///< PUCCH candidates to decode + srsran_pucch_nr_common_cfg_t pucch_cfg; ///< UE dedicated PUCCH configuration + srsran::bounded_vector candidates; ///< PUCCH candidates to decode }; struct ul_sched_t { @@ -265,8 +267,8 @@ public: }; struct pucch_info_t { - srsran_uci_data_nr_t uci_data; ///< RNTI is available under cfg->pucch->rnti - // ... add signal measurements here + srsran_uci_data_nr_t uci_data; ///< RNTI is available under cfg->pucch->rnti + srsran_csi_trs_measurements_t csi; ///< DMRS based signal Channel State Information (CSI) }; struct pusch_info_t { diff --git a/lib/include/srsran/phy/gnb/gnb_ul.h b/lib/include/srsran/phy/gnb/gnb_ul.h index c0fbcfa13..95c37116e 100644 --- a/lib/include/srsran/phy/gnb/gnb_ul.h +++ b/lib/include/srsran/phy/gnb/gnb_ul.h @@ -57,7 +57,8 @@ SRSRAN_API int srsran_gnb_ul_get_pucch(srsran_gnb_ul_t* q, const srsran_pucch_nr_common_cfg_t* cfg, const srsran_pucch_nr_resource_t* resource, const srsran_uci_cfg_nr_t* uci_cfg, - srsran_uci_value_nr_t* uci_value); + srsran_uci_value_nr_t* uci_value, + srsran_csi_trs_measurements_t* meas); SRSRAN_API uint32_t srsran_gnb_ul_pucch_info(srsran_gnb_ul_t* q, const srsran_pucch_nr_resource_t* resource, diff --git a/lib/src/common/phy_cfg_nr.cc b/lib/src/common/phy_cfg_nr.cc index 1ab321feb..907beaacd 100644 --- a/lib/src/common/phy_cfg_nr.cc +++ b/lib/src/common/phy_cfg_nr.cc @@ -290,7 +290,18 @@ bool phy_cfg_nr_t::get_uci_cfg(const srsran_slot_cfg_t& slot_cfg, } // Generate configuration for SR - // ... + uint32_t sr_resource_id[SRSRAN_PUCCH_MAX_NOF_SR_RESOURCES] = {}; + int n = srsran_ue_ul_nr_sr_send_slot(pucch.sr_resources, slot_cfg.idx, sr_resource_id); + if (n < SRSRAN_SUCCESS) { + ERROR("Calculating SR opportunities"); + return false; + } + + if (n > 0) { + uci_cfg.pucch.sr_resource_id = sr_resource_id[0]; + uci_cfg.o_sr = srsran_ra_ul_nr_nof_sr_bits((uint32_t)n); + uci_cfg.sr_positive_present = true; + } // Generate configuration for CSI reports // ... @@ -324,4 +335,4 @@ bool phy_cfg_nr_t::get_pusch_uci_cfg(const srsran_slot_cfg_t& slot_cfg, return true; } -} // namespace srsran \ No newline at end of file +} // namespace srsran diff --git a/lib/src/phy/gnb/gnb_ul.c b/lib/src/phy/gnb/gnb_ul.c index 22bc57ee5..aa7727dd1 100644 --- a/lib/src/phy/gnb/gnb_ul.c +++ b/lib/src/phy/gnb/gnb_ul.c @@ -210,6 +210,11 @@ static int gnb_ul_decode_pucch_format1(srsran_gnb_ul_t* q, return SRSRAN_ERROR; } + // As format 1 with positive SR is not encoded with any payload, set SR to 1 + if (uci_cfg->sr_positive_present) { + uci_value->sr = 1; + } + // Take valid decision uci_value->valid = (norm_corr > 0.5f); @@ -248,7 +253,8 @@ int srsran_gnb_ul_get_pucch(srsran_gnb_ul_t* q, const srsran_pucch_nr_common_cfg_t* cfg, const srsran_pucch_nr_resource_t* resource, const srsran_uci_cfg_nr_t* uci_cfg, - srsran_uci_value_nr_t* uci_value) + srsran_uci_value_nr_t* uci_value, + srsran_csi_trs_measurements_t* meas) { if (q == NULL || slot_cfg == NULL || cfg == NULL || resource == NULL || uci_cfg == NULL || uci_value == NULL) { return SRSRAN_ERROR_INVALID_INPUTS; @@ -257,17 +263,39 @@ int srsran_gnb_ul_get_pucch(srsran_gnb_ul_t* q, // Estimate channel switch (resource->format) { case SRSRAN_PUCCH_NR_FORMAT_1: - return gnb_ul_decode_pucch_format1(q, slot_cfg, cfg, resource, uci_cfg, uci_value); + if (gnb_ul_decode_pucch_format1(q, slot_cfg, cfg, resource, uci_cfg, uci_value) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + break; case SRSRAN_PUCCH_NR_FORMAT_2: - return gnb_ul_decode_pucch_format2(q, slot_cfg, cfg, resource, uci_cfg, uci_value); + if (gnb_ul_decode_pucch_format2(q, slot_cfg, cfg, resource, uci_cfg, uci_value) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + break; case SRSRAN_PUCCH_NR_FORMAT_0: case SRSRAN_PUCCH_NR_FORMAT_3: case SRSRAN_PUCCH_NR_FORMAT_4: case SRSRAN_PUCCH_NR_FORMAT_ERROR: ERROR("Invalid or not implemented PUCCH-NR format %d", (int)resource->format); + return SRSRAN_ERROR; } - return SRSRAN_ERROR; + // Copy DMRS measurements + if (meas != NULL) { + meas->rsrp = q->chest_pucch.rsrp; + meas->rsrp_dB = q->chest_pucch.rsrp_dBfs; + meas->epre = q->chest_pucch.epre; + meas->epre_dB = q->chest_pucch.epre_dBfs; + meas->n0 = q->chest_pucch.noise_estimate; + meas->n0_dB = q->chest_pucch.noise_estimate_dbm; + meas->snr_dB = q->chest_pucch.snr_db; + meas->cfo_hz = q->chest_pucch.cfo_hz; + meas->cfo_hz_max = NAN; // Unavailable + meas->delay_us = q->chest_pucch.ta_us; + meas->nof_re = 0; // Unavailable + } + + return SRSRAN_SUCCESS; } uint32_t srsran_gnb_ul_pucch_info(srsran_gnb_ul_t* q, diff --git a/lib/src/phy/phch/ra_ul_nr.c b/lib/src/phy/phch/ra_ul_nr.c index 4654d759f..23ce7226e 100644 --- a/lib/src/phy/phch/ra_ul_nr.c +++ b/lib/src/phy/phch/ra_ul_nr.c @@ -478,17 +478,21 @@ static int ra_ul_nr_pucch_resource_default(uint32_t r_pucch, srsran_pucch_nr_res } static int ra_ul_nr_pucch_resource_hl(const srsran_pucch_nr_hl_cfg_t* cfg, - uint32_t O_uci, + const srsran_uci_cfg_nr_t* uci_cfg, uint32_t pucch_resource_id, srsran_pucch_nr_resource_t* resource) { - uint32_t N2 = cfg->sets[1].max_payload_size > 0 ? cfg->sets[1].max_payload_size : SRSRAN_UCI_NR_MAX_NOF_BITS; - uint32_t N3 = cfg->sets[2].max_payload_size > 0 ? cfg->sets[2].max_payload_size : SRSRAN_UCI_NR_MAX_NOF_BITS; + uint32_t O_uci = srsran_uci_nr_total_bits(uci_cfg); + uint32_t N2 = cfg->sets[1].max_payload_size > 0 ? cfg->sets[1].max_payload_size : SRSRAN_UCI_NR_MAX_NOF_BITS; + uint32_t N3 = cfg->sets[2].max_payload_size > 0 ? cfg->sets[2].max_payload_size : SRSRAN_UCI_NR_MAX_NOF_BITS; // If the UE transmits O UCI UCI information bits, that include HARQ-ACK information bits, the UE determines a PUCCH // resource set to be... uint32_t resource_set_id = 3; - if (O_uci <= 2 && cfg->sets[0].nof_resources > 0) { + if (uci_cfg->nof_csi == 0 && uci_cfg->ack.count <= 2) { + // a first set of PUCCH resources with pucch-ResourceSetId = 0 if O_UCI ≤ 2 including 1 or 2 HARQ-ACK + // information bits and a positive or negative SR on one SR transmission occasion if transmission of HARQ-ACK + // information and SR occurs simultaneously, or resource_set_id = 0; } else if (O_uci <= N2 && cfg->sets[1].nof_resources > 0) { resource_set_id = 1; @@ -524,8 +528,6 @@ int srsran_ra_ul_nr_pucch_resource(const srsran_pucch_nr_hl_cfg_t* pucch_cfg, return SRSRAN_ERROR_INVALID_INPUTS; } - uint32_t O_uci = srsran_uci_nr_total_bits(uci_cfg); - // Use SR PUCCH resource // - At least one positive SR // - No HARQ-ACK @@ -553,7 +555,7 @@ int srsran_ra_ul_nr_pucch_resource(const srsran_pucch_nr_hl_cfg_t* pucch_cfg, // - At least one positive SR // - up to 2 HARQ-ACK // - No CSI report - if (uci_cfg->sr_positive_present > 0 && uci_cfg->ack.count <= SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS && + if (uci_cfg->sr_positive_present && uci_cfg->ack.count <= SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS && uci_cfg->nof_csi == 0) { uint32_t sr_resource_id = uci_cfg->pucch.sr_resource_id; if (sr_resource_id >= SRSRAN_PUCCH_MAX_NOF_SR_RESOURCES) { @@ -571,7 +573,8 @@ int srsran_ra_ul_nr_pucch_resource(const srsran_pucch_nr_hl_cfg_t* pucch_cfg, // Select PUCCH resource for HARQ-ACK srsran_pucch_nr_resource_t resource_harq = {}; - if (ra_ul_nr_pucch_resource_hl(pucch_cfg, O_uci, uci_cfg->pucch.resource_id, &resource_harq) < SRSRAN_SUCCESS) { + if (ra_ul_nr_pucch_resource_hl(pucch_cfg, uci_cfg, uci_cfg->pucch.resource_id, &resource_harq) < SRSRAN_SUCCESS) { + ERROR("Error selecting HARQ-ACK resource"); return SRSRAN_ERROR; } @@ -595,6 +598,7 @@ int srsran_ra_ul_nr_pucch_resource(const srsran_pucch_nr_hl_cfg_t* pucch_cfg, } // The impossible happened... + ERROR("The impossible happened..."); return SRSRAN_ERROR; } @@ -603,7 +607,7 @@ int srsran_ra_ul_nr_pucch_resource(const srsran_pucch_nr_hl_cfg_t* pucch_cfg, // - More than 2 HARQ-ACK // - No CSI report if (uci_cfg->o_sr > 0 && uci_cfg->ack.count > SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS && uci_cfg->nof_csi == 0) { - return ra_ul_nr_pucch_resource_hl(pucch_cfg, O_uci, uci_cfg->pucch.resource_id, resource); + return ra_ul_nr_pucch_resource_hl(pucch_cfg, uci_cfg, uci_cfg->pucch.resource_id, resource); } // Use format 2, 3 or 4 CSI report resource from higher layers @@ -622,7 +626,7 @@ int srsran_ra_ul_nr_pucch_resource(const srsran_pucch_nr_hl_cfg_t* pucch_cfg, uint32_t r_pucch = (2 * uci_cfg->pucch.n_cce_0) + 2 * uci_cfg->pucch.resource_id; return ra_ul_nr_pucch_resource_default(r_pucch, resource); } - return ra_ul_nr_pucch_resource_hl(pucch_cfg, O_uci, uci_cfg->pucch.resource_id, resource); + return ra_ul_nr_pucch_resource_hl(pucch_cfg, uci_cfg, uci_cfg->pucch.resource_id, resource); } uint32_t srsran_ra_ul_nr_nof_sr_bits(uint32_t K) diff --git a/srsenb/src/phy/nr/slot_worker.cc b/srsenb/src/phy/nr/slot_worker.cc index 64bcead67..50949e1c4 100644 --- a/srsenb/src/phy/nr/slot_worker.cc +++ b/srsenb/src/phy/nr/slot_worker.cc @@ -148,22 +148,37 @@ bool slot_worker::work_ul() // For each PUCCH... for (stack_interface_phy_nr::pucch_t& pucch : ul_sched.pucch) { - stack_interface_phy_nr::pucch_info_t pucch_info = {}; - pucch_info.uci_data.cfg = pucch.candidates[0].uci_cfg; - - // Decode PUCCH - if (srsran_gnb_ul_get_pucch(&gnb_ul, - &ul_slot_cfg, - &pucch.pucch_cfg, - &pucch.candidates[0].resource, - &pucch_info.uci_data.cfg, - &pucch_info.uci_data.value) < SRSRAN_SUCCESS) { - logger.error("Error getting PUCCH"); - return false; + srsran::bounded_vector + pucch_info(pucch.candidates.size()); + + // For each candidate decode PUCCH + for (uint32_t i = 0; i < (uint32_t)pucch.candidates.size(); i++) { + pucch_info[i].uci_data.cfg = pucch.candidates[i].uci_cfg; + + // Decode PUCCH + if (srsran_gnb_ul_get_pucch(&gnb_ul, + &ul_slot_cfg, + &pucch.pucch_cfg, + &pucch.candidates[i].resource, + &pucch_info[i].uci_data.cfg, + &pucch_info[i].uci_data.value, + &pucch_info[i].csi) < SRSRAN_SUCCESS) { + logger.error("Error getting PUCCH"); + return false; + } + } + + // Find most suitable PUCCH candidate + uint32_t best_candidate = 0; + for (uint32_t i = 1; i < (uint32_t)pucch_info.size(); i++) { + // Select candidate if exceeds the previous best candidate SNR + if (pucch_info[i].csi.snr_dB > pucch_info[best_candidate].csi.snr_dB) { + best_candidate = i; + } } // Inform stack - if (stack.pucch_info(ul_slot_cfg, pucch_info) < SRSRAN_SUCCESS) { + if (stack.pucch_info(ul_slot_cfg, pucch_info[best_candidate]) < SRSRAN_SUCCESS) { logger.error("Error pushing PUCCH information to stack"); return false; } @@ -171,8 +186,11 @@ bool slot_worker::work_ul() // Log PUCCH decoding if (logger.info.enabled()) { std::array str; - srsran_gnb_ul_pucch_info( - &gnb_ul, &pucch.candidates[0].resource, &pucch_info.uci_data, str.data(), (uint32_t)str.size()); + srsran_gnb_ul_pucch_info(&gnb_ul, + &pucch.candidates[0].resource, + &pucch_info[best_candidate].uci_data, + str.data(), + (uint32_t)str.size()); logger.info("PUCCH: %s", str.data()); } diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index 7c25a02fd..af7191a47 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -322,9 +322,28 @@ bool sched_worker_manager::save_sched_result(tti_point pdcch_tti, uint32_t cc, d // Put UCI configuration in PUCCH config ul_res.pucch.emplace_back(); pucch_t& pucch = ul_res.pucch.back(); - pucch.uci_cfg = uci_cfg; - bool ret = phy_cfg->get_pucch_uci_cfg(slot_cfg, pucch.uci_cfg, pucch.pucch_cfg, pucch.resource); - srsran_assert(ret, "Error getting PUCCH UCI cfg"); + pucch.candidates.emplace_back(); + pucch.candidates.back().uci_cfg = uci_cfg; + srsran_assert(phy_cfg->get_pucch_uci_cfg( + slot_cfg, pucch.candidates.back().uci_cfg, pucch.pucch_cfg, pucch.candidates.back().resource), + "Error getting PUCCH UCI cfg"); + + // If this slot has a SR opportunity and the selected PUCCH format is 1, consider positive SR. + if (uci_cfg.sr_positive_present and uci_cfg.ack.count > 0 and + pucch.candidates.back().resource.format == SRSRAN_PUCCH_NR_FORMAT_1) { + // Set SR negative + if (uci_cfg.o_sr > 0) { + uci_cfg.sr_positive_present = false; + } + + // Append new resource + pucch.candidates.emplace_back(); + pucch.candidates.back().uci_cfg = uci_cfg; + srsran_assert( + phy_cfg->get_pucch_uci_cfg( + slot_cfg, pucch.candidates.back().uci_cfg, pucch.pucch_cfg, pucch.candidates.back().resource), + "Error getting PUCCH UCI cfg"); + } } } } @@ -336,4 +355,4 @@ bool sched_worker_manager::save_sched_result(tti_point pdcch_tti, uint32_t cc, d } } // namespace sched_nr_impl -} // namespace srsenb \ No newline at end of file +} // namespace srsenb diff --git a/srsue/src/phy/nr/sf_worker.cc b/srsue/src/phy/nr/sf_worker.cc index 8a6bf8030..0e0a31e69 100644 --- a/srsue/src/phy/nr/sf_worker.cc +++ b/srsue/src/phy/nr/sf_worker.cc @@ -110,7 +110,7 @@ void sf_worker::work_imp() // Perform UL processing for (auto& w : cc_workers) { - w->work_ul(); + w.get()->work_ul(); } // Set Tx buffers diff --git a/test/phy/CMakeLists.txt b/test/phy/CMakeLists.txt index bfce9bf25..a89a27329 100644 --- a/test/phy/CMakeLists.txt +++ b/test/phy/CMakeLists.txt @@ -27,14 +27,17 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) add_nr_test(nr_phy_test_10MHz_dl_only nr_phy_test --duration=100 --gnb.stack.pdsch.slots=\"0,1,2,3,4,5\" - --gnb.stack.pusch.slots=\"\" + --gnb.stack.pdsch.start=0 # Start at RB 0 + --gnb.stack.pdsch.length=52 # Full 10 MHz BW + --gnb.stack.pdsch.mcs=28 # Maximum MCS + --gnb.stack.pusch.slots=none --gnb.phy.nof_threads=${NR_PHY_TEST_GNB_NOF_THREADS} --ue.phy.nof_threads=${NR_PHY_TEST_UE_NOF_THREADS} ) add_nr_test(nr_phy_test_10MHz_ul_only nr_phy_test --duration=100 # 100 slots - --gnb.stack.pdsch.slots=6 # No PDSCH + --gnb.stack.pdsch.slots=none --gnb.stack.pusch.slots=6,7,8,9 # All possible UL slots --gnb.stack.pusch.start=0 # Start at RB 0 --gnb.stack.pusch.length=52 # Full 10 MHz BW @@ -59,11 +62,32 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) add_nr_test(nr_phy_test_10MHz_prach nr_phy_test --duration=1000 # 100 slots - --gnb.stack.pdsch.slots=6 # No PDSCH - --gnb.stack.pusch.slots=0 # No PUSCH + --gnb.stack.pdsch.slots=none # No PDSCH + --gnb.stack.pusch.slots=none # No PUSCH --gnb.phy.nof_threads=${NR_PHY_TEST_GNB_NOF_THREADS} --ue.stack.prach.period=30 # Transmit PRACH every 30 radio frames --ue.stack.prach.preamble=10 # Use preamble 10 --ue.phy.nof_threads=${NR_PHY_TEST_UE_NOF_THREADS} ) + + add_nr_test(nr_phy_test_10MHz_sr nr_phy_test + --duration=1000 # 100 slots + --gnb.stack.pdsch.slots=none # No PDSCH + --gnb.stack.pusch.slots=none # No PUSCH + --gnb.phy.nof_threads=${NR_PHY_TEST_GNB_NOF_THREADS} + --ue.stack.sr.period=1 # Transmit SR every candidate + --ue.phy.nof_threads=${NR_PHY_TEST_UE_NOF_THREADS} + ) + + add_nr_test(nr_phy_test_10MHz_dl_sr nr_phy_test + --duration=100 + --gnb.stack.pdsch.slots=\"0,1,2,3,4,5\" + --gnb.stack.pdsch.start=0 # Start at RB 0 + --gnb.stack.pdsch.length=2 # Full 10 MHz BW + --gnb.stack.pdsch.mcs=1 # Minimum MCS + --gnb.stack.pusch.slots=none + --gnb.phy.nof_threads=${NR_PHY_TEST_GNB_NOF_THREADS} + --ue.stack.sr.period=1 # Transmit SR every candidate + --ue.phy.nof_threads=${NR_PHY_TEST_UE_NOF_THREADS} + ) endif () diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index ad2a23fb2..d2ce46c4b 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -33,10 +33,27 @@ public: uint32_t count; float avg_ta; }; + struct pucch_metrics_t { + float epre_db_avg = 0.0f; + float epre_db_min = +INFINITY; + float epre_db_max = -INFINITY; + float rsrp_db_avg = 0.0f; + float rsrp_db_min = +INFINITY; + float rsrp_db_max = -INFINITY; + float snr_db_avg = 0.0f; + float snr_db_min = +INFINITY; + float snr_db_max = -INFINITY; + float ta_us_avg = 0.0f; + float ta_us_min = +INFINITY; + float ta_us_max = -INFINITY; + uint32_t count = 0; + }; struct metrics_t { - std::map prach = {}; ///< PRACH metrics indexed with premable index - srsenb::mac_ue_metrics_t mac = {}; ///< MAC metrics + std::map prach = {}; ///< PRACH metrics indexed with premable index + srsenb::mac_ue_metrics_t mac = {}; ///< MAC metrics + uint32_t sr_count = 0; ///< SR counter + pucch_metrics_t pucch = {}; }; private: @@ -44,10 +61,10 @@ private: bool use_dummy_sched = true; const uint16_t rnti = 0x1234; struct { - srsran::circular_array dci_location; - uint32_t mcs; - uint32_t freq_res = 0; - std::set slots; + srsran::circular_array dci_location = {}; + uint32_t mcs = 0; + uint32_t freq_res = 0; + std::set slots = {}; } dl, ul; srsran::circular_array dl_data_to_ul_ack; uint32_t ss_id = 0; @@ -259,6 +276,7 @@ private: { std::unique_lock lock(metrics_mutex); + // Process HARQ-ACK for (uint32_t i = 0; i < cfg.ack.count; i++) { const srsran_harq_ack_bit_t* ack_bit = &cfg.ack.bits[i]; bool is_ok = (value.ack[i] == 1) and value.valid; @@ -271,6 +289,11 @@ private: } } + // Process SR + if (value.valid and value.sr > 0) { + metrics.sr_count++; + } + return true; } @@ -314,8 +337,12 @@ public: dl.mcs = args.pdsch.mcs; ul.mcs = args.pusch.mcs; - srsran::string_parse_list(args.pdsch.slots, ',', dl.slots); - srsran::string_parse_list(args.pusch.slots, ',', ul.slots); + if (args.pdsch.slots != "none" and not args.pdsch.slots.empty()) { + srsran::string_parse_list(args.pdsch.slots, ',', dl.slots); + } + if (args.pusch.slots != "none" and not args.pusch.slots.empty()) { + srsran::string_parse_list(args.pusch.slots, ',', ul.slots); + } // Select DCI locations for (uint32_t slot = 0; slot < SRSRAN_NOF_SF_X_FRAME; slot++) { @@ -474,14 +501,35 @@ public: // If any UCI information is triggered, schedule PUCCH if (uci_cfg.ack.count > 0 || uci_cfg.nof_csi > 0 || uci_cfg.o_sr > 0) { - mac_interface_phy_nr::pucch_t pucch = {}; - pucch.candidates[0].uci_cfg = uci_cfg; - if (not phy_cfg.get_pucch_uci_cfg(slot_cfg, uci_cfg, pucch.pucch_cfg, pucch.candidates[0].resource)) { + ul_sched.pucch.emplace_back(); + + uci_cfg.pucch.rnti = rnti; + + mac_interface_phy_nr::pucch_t& pucch = ul_sched.pucch.back(); + pucch.candidates.emplace_back(); + pucch.candidates.back().uci_cfg = uci_cfg; + if (not phy_cfg.get_pucch_uci_cfg(slot_cfg, uci_cfg, pucch.pucch_cfg, pucch.candidates.back().resource)) { logger.error("Error getting UCI CFG"); return SRSRAN_ERROR; } - ul_sched.pucch.push_back(pucch); + // If this slot has a SR opportunity and the selected PUCCH format is 1, consider positive SR. + if (uci_cfg.o_sr > 0 and uci_cfg.ack.count > 0 and + pucch.candidates.back().resource.format == SRSRAN_PUCCH_NR_FORMAT_1) { + // Set SR negative + if (uci_cfg.o_sr > 0) { + uci_cfg.sr_positive_present = false; + } + + // Append new resource + pucch.candidates.emplace_back(); + pucch.candidates.back().uci_cfg = uci_cfg; + if (not phy_cfg.get_pucch_uci_cfg(slot_cfg, uci_cfg, pucch.pucch_cfg, pucch.candidates.back().resource)) { + logger.error("Error getting UCI CFG"); + return SRSRAN_ERROR; + } + } + return SRSRAN_SUCCESS; } @@ -498,7 +546,19 @@ public: } // Handle PHY metrics - // ... + metrics.pucch.epre_db_avg = SRSRAN_VEC_CMA(pucch_info.csi.epre_dB, metrics.pucch.epre_db_avg, metrics.pucch.count); + metrics.pucch.epre_db_min = SRSRAN_MIN(metrics.pucch.epre_db_min, pucch_info.csi.epre_dB); + metrics.pucch.epre_db_max = SRSRAN_MAX(metrics.pucch.epre_db_max, pucch_info.csi.epre_dB); + metrics.pucch.rsrp_db_avg = SRSRAN_VEC_CMA(pucch_info.csi.rsrp_dB, metrics.pucch.rsrp_db_avg, metrics.pucch.count); + metrics.pucch.rsrp_db_min = SRSRAN_MIN(metrics.pucch.rsrp_db_min, pucch_info.csi.rsrp_dB); + metrics.pucch.rsrp_db_max = SRSRAN_MAX(metrics.pucch.rsrp_db_max, pucch_info.csi.rsrp_dB); + metrics.pucch.snr_db_avg = SRSRAN_VEC_CMA(pucch_info.csi.snr_dB, metrics.pucch.snr_db_avg, metrics.pucch.count); + metrics.pucch.snr_db_min = SRSRAN_MIN(metrics.pucch.snr_db_min, pucch_info.csi.snr_dB); + metrics.pucch.snr_db_max = SRSRAN_MAX(metrics.pucch.snr_db_max, pucch_info.csi.snr_dB); + metrics.pucch.ta_us_avg = SRSRAN_VEC_CMA(pucch_info.csi.delay_us, metrics.pucch.ta_us_avg, metrics.pucch.count); + metrics.pucch.ta_us_min = SRSRAN_MIN(metrics.pucch.ta_us_min, pucch_info.csi.delay_us); + metrics.pucch.ta_us_max = SRSRAN_MAX(metrics.pucch.ta_us_max, pucch_info.csi.delay_us); + metrics.pucch.count++; return SRSRAN_SUCCESS; } diff --git a/test/phy/dummy_ue_stack.h b/test/phy/dummy_ue_stack.h index 51580aba8..e3d7eced9 100644 --- a/test/phy/dummy_ue_stack.h +++ b/test/phy/dummy_ue_stack.h @@ -23,7 +23,8 @@ public: }; struct metrics_t { - std::map prach = {}; ///< PRACH metrics indexed with premable index + std::map prach = {}; ///< PRACH metrics indexed with premable index + uint32_t sr_count = 0; ///< Counts number of transmitted SR }; private: @@ -95,11 +96,14 @@ public: return false; } - bool ret = (sr_count % sr_period == 0); + if (sr_count >= (sr_period - 1) and not ul_sch_tx) { + metrics.sr_count++; + sr_count = 0; + return true; + } sr_count++; - - return ret; + return false; } bool is_valid() const { return valid; } diff --git a/test/phy/nr_phy_test.cc b/test/phy/nr_phy_test.cc index 6ba631cc1..e742af6f7 100644 --- a/test/phy/nr_phy_test.cc +++ b/test/phy/nr_phy_test.cc @@ -225,14 +225,54 @@ int main(int argc, char** argv) TESTASSERT(metrics.ue_stack.prach.count(p.first) > 0); } srsran::console(" +------------+------------+------------+\n\n"); + } + + // Print PUCCH + if (metrics.gnb_stack.pucch.count > 0) { + srsran::console("PUCCH DMRS Receiver metrics:\n"); + srsran::console(" +------------+------------+------------+------------+\n"); + srsran::console(" | %10s | %10s | %10s | %10s |\n", "Measure", "Average", "Min", "Max"); + srsran::console(" +------------+------------+------------+------------+\n"); + srsran::console(" | %10s | %+10.2f | %+10.2f | %+10.2f |\n", + "EPRE (dB)", + metrics.gnb_stack.pucch.epre_db_avg, + metrics.gnb_stack.pucch.epre_db_min, + metrics.gnb_stack.pucch.epre_db_min); + srsran::console(" | %10s | %+10.2f | %+10.2f | %+10.2f |\n", + "RSRP (dB)", + metrics.gnb_stack.pucch.rsrp_db_avg, + metrics.gnb_stack.pucch.rsrp_db_min, + metrics.gnb_stack.pucch.rsrp_db_max); + srsran::console(" | %10s | %+10.2f | %+10.2f | %+10.2f |\n", + "SINR (dB)", + metrics.gnb_stack.pucch.snr_db_avg, + metrics.gnb_stack.pucch.snr_db_min, + metrics.gnb_stack.pucch.snr_db_max); + srsran::console(" | %10s | %+10.2f | %+10.2f | %+10.2f |\n", + "TA (us)", + metrics.gnb_stack.pucch.ta_us_avg, + metrics.gnb_stack.pucch.ta_us_min, + metrics.gnb_stack.pucch.ta_us_max); + srsran::console(" +------------+------------+------------+------------+\n"); } else { - // In this case no PRACH should + // In this case the gNb should not have detected any TESTASSERT(metrics.gnb_stack.prach.empty()); } + // Print SR + if (metrics.ue_stack.sr_count > 0) { + srsran::console("SR:\n"); + srsran::console(" +------------+------------+\n"); + srsran::console(" | %10s | %10s |\n", "Transmit'd", "Received"); + srsran::console(" +------------+------------+\n"); + srsran::console(" | %10d | %10d |\n", metrics.ue_stack.sr_count, metrics.gnb_stack.sr_count); + srsran::console(" +------------+------------+\n"); + } + // Assert metrics TESTASSERT(metrics.gnb_stack.mac.tx_errors == 0); TESTASSERT(metrics.gnb_stack.mac.rx_errors == 0); + TESTASSERT(metrics.ue_stack.sr_count == metrics.gnb_stack.sr_count); // If reached here, the test is successful return SRSRAN_SUCCESS; From bc5a548fe8797c28f2ba9a0e65fb833a27454a3f Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Mon, 19 Jul 2021 16:17:21 +0100 Subject: [PATCH 26/34] sched: scheduler now accounts for prachs with different durations --- lib/include/srsran/phy/phch/prach.h | 2 ++ lib/src/phy/phch/prach.c | 17 +++++++++++++++++ srsenb/src/stack/mac/sched_grid.cc | 2 +- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/include/srsran/phy/phch/prach.h b/lib/include/srsran/phy/phch/prach.h index c5188a3e6..942c5aad5 100644 --- a/lib/include/srsran/phy/phch/prach.h +++ b/lib/include/srsran/phy/phch/prach.h @@ -170,6 +170,8 @@ SRSRAN_API bool srsran_prach_tti_opportunity(srsran_prach_t* p, uint32_t current SRSRAN_API bool srsran_prach_tti_opportunity_config_fdd(uint32_t config_idx, uint32_t current_tti, int allowed_subframe); +SRSRAN_API bool srsran_prach_in_window_config_fdd(uint32_t config_idx, uint32_t current_tti, int allowed_subframe); + SRSRAN_API bool srsran_prach_tti_opportunity_config_tdd(uint32_t config_idx, uint32_t tdd_ul_dl_config, uint32_t current_tti, diff --git a/lib/src/phy/phch/prach.c b/lib/src/phy/phch/prach.c index 210561f55..bfbd84e0d 100644 --- a/lib/src/phy/phch/prach.c +++ b/lib/src/phy/phch/prach.c @@ -154,6 +154,23 @@ bool srsran_prach_tti_opportunity_config_fdd(uint32_t config_idx, uint32_t curre return false; } +bool srsran_prach_in_window_config_fdd(uint32_t config_idx, uint32_t current_tti, int allowed_subframe) +{ + if (srsran_prach_tti_opportunity_config_fdd(config_idx, current_tti, allowed_subframe)) { + return true; + } + + uint32_t preamble_format = srsran_prach_get_preamble_format(config_idx); + float T_tot = (prach_Tseq[preamble_format] + prach_Tcp[preamble_format]) * SRSRAN_LTE_TS; + uint32_t tti_dur = (uint32_t)ceilf(T_tot * 1000); + for (uint32_t i = 1; i < tti_dur; ++i) { + if (srsran_prach_tti_opportunity_config_fdd(config_idx, current_tti - i, allowed_subframe)) { + return true; + } + } + return false; +} + uint32_t srsran_prach_nof_f_idx_tdd(uint32_t config_idx, uint32_t tdd_ul_dl_config) { if (config_idx < 64 && tdd_ul_dl_config < 7) { diff --git a/srsenb/src/stack/mac/sched_grid.cc b/srsenb/src/stack/mac/sched_grid.cc index 4b3813195..4f80f008f 100644 --- a/srsenb/src/stack/mac/sched_grid.cc +++ b/srsenb/src/stack/mac/sched_grid.cc @@ -99,7 +99,7 @@ void sf_grid_t::new_tti(tti_point tti_rx_) ul_mask |= pucch_mask; // Reserve PRBs for PRACH - if (srsran_prach_tti_opportunity_config_fdd(cc_cfg->cfg.prach_config, to_tx_ul(tti_rx).to_uint(), -1)) { + if (srsran_prach_in_window_config_fdd(cc_cfg->cfg.prach_config, to_tx_ul(tti_rx).to_uint(), -1)) { prbmask_t prach_mask{cc_cfg->nof_prb()}; prach_mask.fill(cc_cfg->cfg.prach_freq_offset, cc_cfg->cfg.prach_freq_offset + 6); reserve_ul_prbs(prach_mask, false); // TODO: set to true once test sib.conf files are updated From 592d9332ba8796c932621a5ac76d83fc00975da4 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 20 Jul 2021 21:26:00 +0100 Subject: [PATCH 27/34] sched,nr: add logic for allocation of RAR and Msg3 grants --- srsenb/hdr/stack/mac/nr/sched_nr_cell.h | 13 +-- srsenb/hdr/stack/mac/nr/sched_nr_cfg.h | 7 ++ srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h | 8 +- srsenb/hdr/stack/mac/nr/sched_nr_ue.h | 3 +- srsenb/src/stack/mac/nr/sched_nr_cell.cc | 20 ++-- srsenb/src/stack/mac/nr/sched_nr_cfg.cc | 18 ++- srsenb/src/stack/mac/nr/sched_nr_helpers.cc | 5 +- srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc | 115 ++++++++++++++----- srsenb/src/stack/mac/nr/sched_nr_worker.cc | 2 +- srsenb/test/mac/nr/sched_nr_cfg_generators.h | 1 + 10 files changed, 144 insertions(+), 48 deletions(-) diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_cell.h b/srsenb/hdr/stack/mac/nr/sched_nr_cell.h index f65323f12..fcf38564a 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_cell.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_cell.h @@ -35,12 +35,14 @@ public: explicit ra_sched(const bwp_params& bwp_cfg_); int dl_rach_info(const dl_sched_rar_info_t& rar_info); - void run_slot(bwp_slot_allocator& slot_grid); + void run_slot(bwp_slot_allocator& slot_grid, slot_ue_map_t& slot_ues); size_t empty() const { return pending_rars.empty(); } private: - alloc_result - allocate_pending_rar(bwp_slot_allocator& slot_grid, const pending_rar_t& rar, uint32_t& nof_grants_alloc); + alloc_result allocate_pending_rar(bwp_slot_allocator& slot_grid, + const pending_rar_t& rar, + slot_ue_map_t& slot_ues, + uint32_t& nof_grants_alloc); const bwp_params* bwp_cfg = nullptr; srslog::basic_logger& logger; @@ -69,14 +71,9 @@ public: explicit serv_cell_manager(const sched_cell_params& cell_cfg_); - void add_user(uint16_t rnti, ue_carrier* ue); - void rem_user(uint16_t rnti); - srsran::bounded_vector bwps; const sched_cell_params& cfg; - srsran::static_circular_map ues; - private: srslog::basic_logger& logger; }; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h b/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h index 8ec8bfe37..48608298b 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h @@ -47,6 +47,13 @@ struct bwp_params { uint32_t P; uint32_t N_rbg; + struct pusch_rach_time_cfg { + uint32_t msg3_delay; ///< Includes K2 and delta. See TS 36.214 6.1.2.1.1-2/4/5 + uint32_t S; + uint32_t L; + }; + std::vector pusch_rach_list; + bwp_params(const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_, uint32_t cc, uint32_t bwp_id); }; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h index a1425baf1..0b81d0dcd 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h @@ -83,7 +83,11 @@ public: void new_slot(tti_point pdcch_tti_) { pdcch_tti = pdcch_tti_; } - alloc_result alloc_rar(uint32_t aggr_idx, const pending_rar_t& rar, prb_interval interv, uint32_t max_nof_grants); + alloc_result alloc_rar_and_msg3(uint32_t aggr_idx, + const pending_rar_t& rar, + prb_interval interv, + slot_ue_map_t& ues, + uint32_t max_nof_grants); alloc_result alloc_pdsch(slot_ue& ue, const prb_grant& dl_grant); alloc_result alloc_pusch(slot_ue& ue, const rbgmask_t& dl_mask); @@ -93,6 +97,8 @@ public: const bwp_params& cfg; private: + alloc_result verify_pusch_space(bwp_slot_grid& pusch_grid, bwp_slot_grid* pdcch_grid = nullptr) const; + srslog::basic_logger& logger; bwp_res_grid& bwp_grid; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h index 041aa2566..974d69449 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h @@ -102,7 +102,8 @@ private: ue_cfg_t ue_cfg; }; -using ue_map_t = srsran::static_circular_map, SCHED_NR_MAX_USERS>; +using ue_map_t = srsran::static_circular_map, SCHED_NR_MAX_USERS>; +using slot_ue_map_t = srsran::static_circular_map; } // namespace sched_nr_impl diff --git a/srsenb/src/stack/mac/nr/sched_nr_cell.cc b/srsenb/src/stack/mac/nr/sched_nr_cell.cc index b30970237..b48ffebd3 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_cell.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_cell.cc @@ -19,8 +19,10 @@ namespace sched_nr_impl { ra_sched::ra_sched(const bwp_params& bwp_cfg_) : bwp_cfg(&bwp_cfg_), logger(srslog::fetch_basic_logger("MAC")) {} -alloc_result -ra_sched::allocate_pending_rar(bwp_slot_allocator& slot_grid, const pending_rar_t& rar, uint32_t& nof_grants_alloc) +alloc_result ra_sched::allocate_pending_rar(bwp_slot_allocator& slot_grid, + const pending_rar_t& rar, + slot_ue_map_t& slot_ues, + uint32_t& nof_grants_alloc) { const uint32_t rar_aggr_level = 2; const prb_bitmap& prbs = slot_grid.res_grid()[slot_grid.get_pdcch_tti()].dl_prbs.prbs(); @@ -29,11 +31,11 @@ ra_sched::allocate_pending_rar(bwp_slot_allocator& slot_grid, const pending_rar_ for (nof_grants_alloc = rar.msg3_grant.size(); nof_grants_alloc > 0; nof_grants_alloc--) { ret = alloc_result::invalid_coderate; uint32_t start_prb_idx = 0; - for (uint32_t nprb = 1; nprb < bwp_cfg->cfg.rb_width and ret == alloc_result::invalid_coderate; ++nprb) { + for (uint32_t nprb = 4; nprb < bwp_cfg->cfg.rb_width and ret == alloc_result::invalid_coderate; ++nprb) { prb_interval interv = find_empty_interval_of_length(prbs, nprb, start_prb_idx); start_prb_idx = interv.stop(); if (interv.length() == nprb) { - ret = slot_grid.alloc_rar(rar_aggr_level, rar, interv, nof_grants_alloc); + ret = slot_grid.alloc_rar_and_msg3(rar_aggr_level, rar, interv, slot_ues, nof_grants_alloc); } else { ret = alloc_result::no_sch_space; } @@ -50,10 +52,14 @@ ra_sched::allocate_pending_rar(bwp_slot_allocator& slot_grid, const pending_rar_ return ret; } -void ra_sched::run_slot(bwp_slot_allocator& slot_grid) +void ra_sched::run_slot(bwp_slot_allocator& slot_grid, slot_ue_map_t& slot_ues) { static const uint32_t PRACH_RAR_OFFSET = 3; tti_point pdcch_tti = slot_grid.get_pdcch_tti(); + tti_point msg3_tti = pdcch_tti + bwp_cfg->pusch_rach_list[0].msg3_delay; + if (not slot_grid.res_grid()[msg3_tti].is_ul) { + return; + } for (auto it = pending_rars.begin(); it != pending_rars.end();) { pending_rar_t& rar = *it; @@ -79,9 +85,9 @@ void ra_sched::run_slot(bwp_slot_allocator& slot_grid) return; } - // Try to schedule DCI + RBGs for RAR Grant + // Try to schedule DCIs + RBGs for RAR Grants uint32_t nof_rar_allocs = 0; - alloc_result ret = allocate_pending_rar(slot_grid, rar, nof_rar_allocs); + alloc_result ret = allocate_pending_rar(slot_grid, rar, slot_ues, nof_rar_allocs); if (ret == alloc_result::success) { // If RAR allocation was successful: diff --git a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc index da954d094..c9542c430 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc @@ -12,6 +12,9 @@ #include "srsenb/hdr/stack/mac/nr/sched_nr_cfg.h" #include "srsenb/hdr/stack/mac/nr/sched_nr_helpers.h" +extern "C" { +#include "srsran/phy/phch/ra_ul_nr.h" +} namespace srsenb { namespace sched_nr_impl { @@ -19,10 +22,23 @@ namespace sched_nr_impl { bwp_params::bwp_params(const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_, uint32_t cc_, uint32_t bwp_id_) : cell_cfg(cell), sched_cfg(sched_cfg_), cc(cc_), bwp_id(bwp_id_), cfg(cell.bwps[bwp_id_]) { + srsran_assert(bwp_id != 0 or cfg.pdcch.coreset_present[0], "CORESET#0 has to be active for initial BWP"); + P = get_P(cfg.rb_width, cfg.pdsch.rbg_size_cfg_1); N_rbg = get_nof_rbgs(cfg.rb_width, cfg.start_rb, cfg.pdsch.rbg_size_cfg_1); - srsran_assert(bwp_id != 0 or cfg.pdcch.coreset_present[0], "CORESET#0 has to be active for initial BWP"); + pusch_rach_list.resize(cfg.pusch.nof_common_time_ra); + const uint32_t coreset_id = 0; + srsran_sch_grant_nr_t grant; + for (uint32_t m = 0; m < cfg.pusch.nof_common_time_ra; ++m) { + int ret = + srsran_ra_ul_nr_time(&cfg.pusch, srsran_rnti_type_ra, srsran_search_space_type_rar, coreset_id, m, &grant); + srsran_assert(ret == SRSRAN_SUCCESS, "Failed to obtain RA config"); + pusch_rach_list[m].msg3_delay = grant.k; + pusch_rach_list[m].S = grant.S; + pusch_rach_list[m].L = grant.L; + } + srsran_assert(not pusch_rach_list.empty(), "Time-Domain Resource Allocation not valid"); } sched_cell_params::sched_cell_params(uint32_t cc_, const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_) : diff --git a/srsenb/src/stack/mac/nr/sched_nr_helpers.cc b/srsenb/src/stack/mac/nr/sched_nr_helpers.cc index 32a901272..8e54fdfb4 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_helpers.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_helpers.cc @@ -21,7 +21,10 @@ namespace sched_nr_impl { bool fill_dci_rar(prb_interval interv, const bwp_params& cell, srsran_dci_dl_nr_t& dci) { - dci.mcs = 5; + dci.mcs = 5; + dci.ctx.format = srsran_dci_format_nr_1_0; + // TODO: Fill + return true; } diff --git a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc index 49affafa3..aee8c6c55 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc @@ -11,6 +11,7 @@ */ #include "srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr_cell.h" #include "srsenb/hdr/stack/mac/nr/sched_nr_helpers.h" namespace srsenb { @@ -63,15 +64,21 @@ bwp_slot_allocator::bwp_slot_allocator(bwp_res_grid& bwp_grid_) : logger(srslog::fetch_basic_logger("MAC")), cfg(*bwp_grid_.cfg), bwp_grid(bwp_grid_) {} -alloc_result bwp_slot_allocator::alloc_rar(uint32_t aggr_idx, - const srsenb::sched_nr_impl::pending_rar_t& rar, - prb_interval interv, - uint32_t nof_grants) +alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint32_t aggr_idx, + const srsenb::sched_nr_impl::pending_rar_t& rar, + prb_interval interv, + slot_ue_map_t& ues, + uint32_t max_nof_grants) { - static const uint32_t msg3_nof_prbs = 3; + static const uint32_t msg3_nof_prbs = 3, m = 0; bwp_slot_grid& bwp_pdcch_slot = bwp_grid[pdcch_tti]; - bwp_slot_grid& bwp_msg3_slot = bwp_grid[pdcch_tti + 4]; + tti_point msg3_tti = pdcch_tti + cfg.pusch_rach_list[m].msg3_delay; + bwp_slot_grid& bwp_msg3_slot = bwp_grid[msg3_tti]; + alloc_result ret = verify_pusch_space(bwp_msg3_slot, nullptr); + if (ret != alloc_result::success) { + return ret; + } if (bwp_pdcch_slot.dl_pdcchs.full()) { logger.warning("SCHED: Maximum number of DL allocations reached"); @@ -88,10 +95,10 @@ alloc_result bwp_slot_allocator::alloc_rar(uint32_t } // Check Msg3 RB collision - uint32_t total_ul_nof_prbs = msg3_nof_prbs * nof_grants; + uint32_t total_ul_nof_prbs = msg3_nof_prbs * max_nof_grants; uint32_t total_ul_nof_rbgs = srsran::ceil_div(total_ul_nof_prbs, get_P(bwp_grid.nof_prbs(), false)); - prb_interval msg3_rbgs = find_empty_interval_of_length(bwp_msg3_slot.ul_prbs.prbs(), total_ul_nof_rbgs); - if (msg3_rbgs.length() < total_ul_nof_rbgs) { + prb_interval msg3_rbs = find_empty_interval_of_length(bwp_msg3_slot.ul_prbs.prbs(), total_ul_nof_rbgs); + if (msg3_rbs.length() < total_ul_nof_rbgs) { logger.debug("SCHED: No space in PUSCH for Msg3."); return alloc_result::sch_collision; } @@ -105,6 +112,8 @@ alloc_result bwp_slot_allocator::alloc_rar(uint32_t return alloc_result::no_cch_space; } + // RAR allocation successful. + // Generate DCI for RAR pdcch_dl_t& pdcch = bwp_pdcch_slot.dl_pdcchs.back(); if (not fill_dci_rar(interv, *bwp_grid.cfg, pdcch.dci)) { @@ -112,10 +121,39 @@ alloc_result bwp_slot_allocator::alloc_rar(uint32_t bwp_pdcch_slot.coresets[coreset_id]->rem_last_dci(); return alloc_result::invalid_coderate; } - - // RAR allocation successful. + // Generate RAR PDSCH bwp_pdcch_slot.dl_prbs.add(interv); + // Generate Msg3 grants in PUSCH + uint32_t last_msg3 = msg3_rbs.start(); + const int mcs = 0, max_harq_msg3_retx = 4; + int dai = 0; + srsran_slot_cfg_t slot_cfg; + slot_cfg.idx = msg3_tti.sf_idx(); + for (const auto& grant : rar.msg3_grant) { + slot_ue& ue = ues[grant.temp_crnti]; + bool success = ue.h_ul->new_tx( + msg3_tti, msg3_tti, prb_interval{last_msg3, last_msg3 + msg3_nof_prbs}, mcs, 100, max_harq_msg3_retx); + srsran_assert(success, "Failed to allocate Msg3"); + last_msg3 += msg3_nof_prbs; + srsran_dci_ul_nr_t msg3_dci; // Create dummy Msg3 DCI + msg3_dci.ctx.coreset_id = 1; + msg3_dci.ctx.rnti_type = srsran_rnti_type_ra; + msg3_dci.ctx.ss_type = srsran_search_space_type_rar; + msg3_dci.ctx.format = srsran_dci_format_nr_0_0; + msg3_dci.cc_id = cfg.cc; + msg3_dci.bwp_id = cfg.bwp_id; + msg3_dci.rv = 0; + msg3_dci.mcs = 0; + msg3_dci.time_domain_assigment = dai++; + bwp_msg3_slot.puschs.emplace_back(); + pusch_t& pusch = bwp_msg3_slot.puschs.back(); + success = ue.cfg->phy().get_pusch_cfg(slot_cfg, msg3_dci, pusch.sch); + srsran_assert(success, "Error converting DCI to PUSCH grant"); + pusch.sch.grant.tb[0].softbuffer.rx = ue.h_ul->get_softbuffer().get(); + } + bwp_msg3_slot.ul_prbs.add(msg3_rbs); + return alloc_result::success; } @@ -207,21 +245,18 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, const prb_grant& dl_gr alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, const rbg_bitmap& ul_mask) { + auto& bwp_pdcch_slot = bwp_grid[ue.pdcch_tti]; + auto& bwp_pusch_slot = bwp_grid[ue.pusch_tti]; + alloc_result ret = verify_pusch_space(bwp_pusch_slot, &bwp_pdcch_slot); + if (ret != alloc_result::success) { + return ret; + } + if (ue.h_ul == nullptr) { logger.warning("SCHED: Trying to allocate PUSCH for rnti=0x%x with no available HARQs", ue.rnti); return alloc_result::no_rnti_opportunity; } - auto& bwp_pdcch_slot = bwp_grid[ue.pdcch_tti]; - auto& bwp_pusch_slot = bwp_grid[ue.pusch_tti]; - if (not bwp_pusch_slot.is_ul) { - logger.warning("SCHED: Trying to allocate PUSCH in TDD non-UL slot index=%d", bwp_pusch_slot.slot_idx); - return alloc_result::no_sch_space; - } - pdcch_ul_list_t& pdcchs = bwp_pdcch_slot.ul_pdcchs; - if (pdcchs.full()) { - logger.warning("SCHED: Maximum number of UL allocations reached"); - return alloc_result::no_grant_space; - } + pdcch_ul_list_t& pdcchs = bwp_pdcch_slot.ul_pdcchs; const rbg_bitmap& pusch_mask = bwp_pusch_slot.ul_prbs.rbgs(); if ((pusch_mask & ul_mask).any()) { return alloc_result::sch_collision; @@ -235,10 +270,10 @@ alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, const rbg_bitmap& ul_m if (ue.h_ul->empty()) { srsran_assert(ue.cfg->ue_cfg()->fixed_ul_mcs >= 0, "Dynamic MCS not yet supported"); - int mcs = ue.cfg->ue_cfg()->fixed_ul_mcs; - int tbs = 100; - bool ret = ue.h_ul->new_tx(ue.pusch_tti, ue.pusch_tti, ul_mask, mcs, tbs, ue.cfg->ue_cfg()->maxharq_tx); - srsran_assert(ret, "Failed to allocate UL HARQ"); + int mcs = ue.cfg->ue_cfg()->fixed_ul_mcs; + int tbs = 100; + bool success = ue.h_ul->new_tx(ue.pusch_tti, ue.pusch_tti, ul_mask, mcs, tbs, ue.cfg->ue_cfg()->maxharq_tx); + srsran_assert(success, "Failed to allocate UL HARQ"); } else { srsran_assert(ue.h_ul->new_retx(ue.pusch_tti, ue.pusch_tti, ul_mask), "Failed to allocate UL HARQ retx"); } @@ -254,12 +289,36 @@ alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, const rbg_bitmap& ul_m pusch_t& pusch = bwp_pusch_slot.puschs.back(); srsran_slot_cfg_t slot_cfg; slot_cfg.idx = ue.pusch_tti.sf_idx(); - bool ret = ue.cfg->phy().get_pusch_cfg(slot_cfg, pdcch.dci, pusch.sch); - srsran_assert(ret, "Error converting DCI to PUSCH grant"); + bool success = ue.cfg->phy().get_pusch_cfg(slot_cfg, pdcch.dci, pusch.sch); + srsran_assert(success, "Error converting DCI to PUSCH grant"); pusch.sch.grant.tb[0].softbuffer.rx = ue.h_ul->get_softbuffer().get(); return alloc_result::success; } +alloc_result bwp_slot_allocator::verify_pusch_space(bwp_slot_grid& pusch_grid, bwp_slot_grid* pdcch_grid) const +{ + if (not pusch_grid.is_ul) { + logger.warning("SCHED: Trying to allocate PUSCH in TDD non-UL slot index=%d", pusch_grid.slot_idx); + return alloc_result::no_sch_space; + } + if (pdcch_grid != nullptr) { + // DCI needed + if (not pdcch_grid->is_dl) { + logger.warning("SCHED: Trying to allocate PDCCH in TDD non-DL slot index=%d", pdcch_grid->slot_idx); + return alloc_result::no_sch_space; + } + if (pdcch_grid->ul_pdcchs.full()) { + logger.warning("SCHED: Maximum number of PUSCH allocations reached"); + return alloc_result::no_grant_space; + } + } + if (pusch_grid.puschs.full()) { + logger.warning("SCHED: Maximum number of PUSCH allocations reached"); + return alloc_result::no_grant_space; + } + return alloc_result::success; +} + } // namespace sched_nr_impl } // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index af7191a47..98bc3bb50 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -81,7 +81,7 @@ void slot_cc_worker::run() bwp_alloc.new_slot(tti_rx + TX_ENB_DELAY); // Allocate pending RARs - cell.bwps[0].ra.run_slot(bwp_alloc); + cell.bwps[0].ra.run_slot(bwp_alloc, slot_ues); // TODO: Prioritize PDCCH scheduling for DL and UL data in a Round-Robin fashion alloc_dl_ues(); diff --git a/srsenb/test/mac/nr/sched_nr_cfg_generators.h b/srsenb/test/mac/nr/sched_nr_cfg_generators.h index 2587b8c24..1c6c84edc 100644 --- a/srsenb/test/mac/nr/sched_nr_cfg_generators.h +++ b/srsenb/test/mac/nr/sched_nr_cfg_generators.h @@ -40,6 +40,7 @@ sched_nr_interface::cell_cfg_t get_default_cell_cfg(const srsran::phy_cfg_nr_t& cell_cfg.bwps.resize(1); cell_cfg.bwps[0].pdcch = phy_cfg.pdcch; cell_cfg.bwps[0].pdsch = phy_cfg.pdsch; + cell_cfg.bwps[0].pusch = phy_cfg.pusch; cell_cfg.bwps[0].rb_width = phy_cfg.carrier.nof_prb; cell_cfg.bwps[0].pdcch.coreset_present[0] = true; From b589c0d184a8fdb548a1732699f225d256c0450a Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 21 Jul 2021 12:36:04 +0100 Subject: [PATCH 28/34] sched,nr: ack/crc info included in nr_phy_test --- srsenb/hdr/stack/gnb_stack_nr.h | 10 +++---- srsenb/hdr/stack/mac/nr/sched_nr.h | 1 + srsenb/hdr/stack/mac/nr/sched_nr_harq.h | 1 + srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 1 + srsenb/src/stack/mac/nr/sched_nr.cc | 5 ++++ test/phy/dummy_gnb_stack.h | 29 ++++++++++++++++++-- 6 files changed, 39 insertions(+), 8 deletions(-) diff --git a/srsenb/hdr/stack/gnb_stack_nr.h b/srsenb/hdr/stack/gnb_stack_nr.h index c0dc96a69..8394ef374 100644 --- a/srsenb/hdr/stack/gnb_stack_nr.h +++ b/srsenb/hdr/stack/gnb_stack_nr.h @@ -72,11 +72,11 @@ public: void toggle_padding() override { srsran::console("padding not available for NR\n"); } - int slot_indication(const srsran_slot_cfg_t& slot_cfg) override; - int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) override; - int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) override; - int pucch_info(const srsran_slot_cfg_t& slot_cfg, const pucch_info_t& pucch_info) override; - int pusch_info(const srsran_slot_cfg_t& slot_cfg, const pusch_info_t& pusch_info) override; + int slot_indication(const srsran_slot_cfg_t& slot_cfg) override; + int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) override; + int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) override; + int pucch_info(const srsran_slot_cfg_t& slot_cfg, const pucch_info_t& pucch_info) override; + int pusch_info(const srsran_slot_cfg_t& slot_cfg, const pusch_info_t& pusch_info) override; void rach_detected(const rach_info_t& rach_info) override; private: diff --git a/srsenb/hdr/stack/mac/nr/sched_nr.h b/srsenb/hdr/stack/mac/nr/sched_nr.h index cccd50e5c..9e82c82eb 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr.h @@ -42,6 +42,7 @@ public: void ue_cfg(uint16_t rnti, const ue_cfg_t& cfg) override; void dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) override; + void ul_crc_info(uint16_t rnti, uint32_t cc, uint32_t pid, bool crc) override; void ul_sr_info(tti_point tti_rx, uint16_t rnti) override; int get_dl_sched(tti_point pdsch_tti, uint32_t cc, dl_sched_t& result) override; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_harq.h b/srsenb/hdr/stack/mac/nr/sched_nr_harq.h index 15dee8aaf..326a50f5a 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_harq.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_harq.h @@ -116,6 +116,7 @@ public: void new_tti(tti_point tti_rx_); void dl_ack_info(uint32_t pid, uint32_t tb_idx, bool ack) { dl_harqs[pid].ack_info(tb_idx, ack); } + void ul_crc_info(uint32_t pid, bool ack) { ul_harqs[pid].ack_info(0, ack); } dl_harq_proc* find_pending_dl_retx() { diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index 2c99fa06d..ad3b9efcf 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -100,6 +100,7 @@ public: virtual int get_ul_sched(tti_point tti_rx, uint32_t cc, ul_sched_t& result) = 0; virtual void dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) = 0; + virtual void ul_crc_info(uint16_t rnti, uint32_t cc, uint32_t pid, bool crc) = 0; virtual void ul_sr_info(tti_point, uint16_t rnti) = 0; }; diff --git a/srsenb/src/stack/mac/nr/sched_nr.cc b/srsenb/src/stack/mac/nr/sched_nr.cc index b97523623..702210928 100644 --- a/srsenb/src/stack/mac/nr/sched_nr.cc +++ b/srsenb/src/stack/mac/nr/sched_nr.cc @@ -164,6 +164,11 @@ void sched_nr::dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb rnti, cc, [pid, tb_idx, ack](ue_carrier& ue_cc) { ue_cc.harq_ent.dl_ack_info(pid, tb_idx, ack); }); } +void sched_nr::ul_crc_info(uint16_t rnti, uint32_t cc, uint32_t pid, bool crc) +{ + sched_workers->enqueue_cc_feedback(rnti, cc, [pid, crc](ue_carrier& ue_cc) { ue_cc.harq_ent.ul_crc_info(pid, crc); }); +} + void sched_nr::ul_sr_info(tti_point tti_rx, uint16_t rnti) { sched_workers->enqueue_event(rnti, [this, rnti, tti_rx]() { ue_db[rnti]->ul_sr_info(tti_rx); }); diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index d2ce46c4b..649419d15 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -71,8 +71,9 @@ private: srsran::phy_cfg_nr_t phy_cfg = {}; bool valid = false; - srsenb::sched_nr sched; - srsran::tti_point pdsch_tti, pusch_tti; + srsenb::sched_nr sched; + srsran::tti_point pdsch_tti, pusch_tti; + srslog::basic_logger& sched_logger; std::mutex metrics_mutex; metrics_t metrics = {}; @@ -287,6 +288,8 @@ 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 @@ -320,9 +323,11 @@ public: phy_cfg(args.phy_cfg), ss_id(args.ss_id), sched(srsenb::sched_nr_interface::sched_cfg_t{}), - use_dummy_sched(args.use_dummy_sched) + use_dummy_sched(args.use_dummy_sched), + sched_logger(srslog::fetch_basic_logger("MAC")) { logger.set_level(srslog::str_to_basic_level(args.log_level)); + sched_logger.set_level(srslog::basic_levels::debug); // create sched object std::vector cells_cfg = srsenb::get_default_cells_cfg(1, phy_cfg); @@ -400,6 +405,7 @@ public: int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) override { logger.set_context(slot_cfg.idx); + sched_logger.set_context(slot_cfg.idx); if (not pdsch_tti.is_valid()) { pdsch_tti = srsran::tti_point{slot_cfg.idx}; } else { @@ -445,6 +451,7 @@ public: int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) override { logger.set_context(slot_cfg.idx); + sched_logger.set_context(slot_cfg.idx); if (not pusch_tti.is_valid()) { pusch_tti = srsran::tti_point{slot_cfg.idx}; } else { @@ -537,6 +544,20 @@ public: return SRSRAN_SUCCESS; } + void dl_ack_info(uint16_t rnti_, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) + { + if (not use_dummy_sched) { + sched.dl_ack_info(rnti_, cc, pid, tb_idx, ack); + } + } + + 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 @@ -579,6 +600,8 @@ 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; } From 61a73d51870ee0dca5ee9b4775cca14a3d2f5180 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 21 Jul 2021 12:59:34 +0100 Subject: [PATCH 29/34] sched: add missing checks for prachs with tti duration above 1msec --- srsenb/src/stack/mac/sched_carrier.cc | 2 +- srsenb/src/stack/mac/sched_grid.cc | 2 +- srsenb/test/mac/sched_common_test_suite.cc | 5 ++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/srsenb/src/stack/mac/sched_carrier.cc b/srsenb/src/stack/mac/sched_carrier.cc index ab13122e7..57be98686 100644 --- a/srsenb/src/stack/mac/sched_carrier.cc +++ b/srsenb/src/stack/mac/sched_carrier.cc @@ -439,7 +439,7 @@ void sched::carrier_sched::alloc_dl_users(sf_sched* tti_result) // NOTE: In case of 6 PRBs, do not transmit if there is going to be a PRACH in the UL to avoid collisions if (cc_cfg->nof_prb() == 6) { tti_point tti_rx_ack = to_tx_dl_ack(tti_result->get_tti_rx()); - if (srsran_prach_tti_opportunity_config_fdd(cc_cfg->cfg.prach_config, tti_rx_ack.to_uint(), -1)) { + if (srsran_prach_in_window_config_fdd(cc_cfg->cfg.prach_config, tti_rx_ack.to_uint(), -1)) { tti_result->reserve_dl_rbgs(0, cc_cfg->nof_rbgs); } } diff --git a/srsenb/src/stack/mac/sched_grid.cc b/srsenb/src/stack/mac/sched_grid.cc index 4f80f008f..1e5653846 100644 --- a/srsenb/src/stack/mac/sched_grid.cc +++ b/srsenb/src/stack/mac/sched_grid.cc @@ -319,7 +319,7 @@ void sf_sched::new_tti(tti_point tti_rx_, sf_sched_result* cc_results_) // setup first prb to be used for msg3 alloc. Account for potential PRACH alloc last_msg3_prb = tti_alloc.get_pucch_width(); tti_point tti_msg3_alloc = to_tx_ul(tti_rx) + MSG3_DELAY_MS; - if (srsran_prach_tti_opportunity_config_fdd(cc_cfg->cfg.prach_config, tti_msg3_alloc.to_uint(), -1)) { + if (srsran_prach_in_window_config_fdd(cc_cfg->cfg.prach_config, tti_msg3_alloc.to_uint(), -1)) { last_msg3_prb = std::max(last_msg3_prb, cc_cfg->cfg.prach_freq_offset + 6); } } diff --git a/srsenb/test/mac/sched_common_test_suite.cc b/srsenb/test/mac/sched_common_test_suite.cc index 71cc82213..bf4bcdc5f 100644 --- a/srsenb/test/mac/sched_common_test_suite.cc +++ b/srsenb/test/mac/sched_common_test_suite.cc @@ -39,7 +39,7 @@ int test_pusch_collisions(const sf_output_res_t& sf_out, uint32_t enb_cc_idx, co /* TEST: Check if there is space for PRACH */ bool is_prach_tti_tx_ul = - srsran_prach_tti_opportunity_config_fdd(cell_params.cfg.prach_config, to_tx_ul(sf_out.tti_rx).to_uint(), -1); + srsran_prach_in_window_config_fdd(cell_params.cfg.prach_config, to_tx_ul(sf_out.tti_rx).to_uint(), -1); if (is_prach_tti_tx_ul) { try_ul_fill({cell_params.cfg.prach_freq_offset, cell_params.cfg.prach_freq_offset + 6}, "PRACH"); } @@ -122,8 +122,7 @@ int test_pdsch_collisions(const sf_output_res_t& sf_out, uint32_t enb_cc_idx, co // forbid Data in DL if its ACKs conflict with PRACH for PRB==6 if (cell_params.nof_prb() == 6) { - if (srsran_prach_tti_opportunity_config_fdd( - cell_params.cfg.prach_config, to_tx_dl_ack(sf_out.tti_rx).to_uint(), -1)) { + if (srsran_prach_in_window_config_fdd(cell_params.cfg.prach_config, to_tx_dl_ack(sf_out.tti_rx).to_uint(), -1)) { dl_allocs.fill(0, dl_allocs.size()); } } From 4a2b51bc0d6cdf653c890dd0ae6865abeb91f17c Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 21 Jul 2021 16:47:48 +0100 Subject: [PATCH 30/34] sched,nr: fix sched nr pusch K2 timing --- srsenb/hdr/stack/mac/nr/sched_nr_cfg.h | 5 +++-- srsenb/src/stack/mac/nr/sched_nr_cell.cc | 2 +- srsenb/src/stack/mac/nr/sched_nr_cfg.cc | 13 ++++++++----- srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc | 2 +- srsenb/src/stack/mac/nr/sched_nr_ue.cc | 2 +- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h b/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h index 48608298b..ba8de9946 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h @@ -47,12 +47,13 @@ struct bwp_params { uint32_t P; uint32_t N_rbg; - struct pusch_rach_time_cfg { + struct pusch_ra_time_cfg { uint32_t msg3_delay; ///< Includes K2 and delta. See TS 36.214 6.1.2.1.1-2/4/5 + uint32_t K; uint32_t S; uint32_t L; }; - std::vector pusch_rach_list; + std::vector pusch_ra_list; bwp_params(const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_, uint32_t cc, uint32_t bwp_id); }; diff --git a/srsenb/src/stack/mac/nr/sched_nr_cell.cc b/srsenb/src/stack/mac/nr/sched_nr_cell.cc index b48ffebd3..8c5e1a26e 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_cell.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_cell.cc @@ -56,7 +56,7 @@ void ra_sched::run_slot(bwp_slot_allocator& slot_grid, slot_ue_map_t& slot_ues) { static const uint32_t PRACH_RAR_OFFSET = 3; tti_point pdcch_tti = slot_grid.get_pdcch_tti(); - tti_point msg3_tti = pdcch_tti + bwp_cfg->pusch_rach_list[0].msg3_delay; + tti_point msg3_tti = pdcch_tti + bwp_cfg->pusch_ra_list[0].msg3_delay; if (not slot_grid.res_grid()[msg3_tti].is_ul) { return; } diff --git a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc index c9542c430..ddf2e2869 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc @@ -27,18 +27,21 @@ bwp_params::bwp_params(const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_, ui P = get_P(cfg.rb_width, cfg.pdsch.rbg_size_cfg_1); N_rbg = get_nof_rbgs(cfg.rb_width, cfg.start_rb, cfg.pdsch.rbg_size_cfg_1); - pusch_rach_list.resize(cfg.pusch.nof_common_time_ra); + pusch_ra_list.resize(cfg.pusch.nof_common_time_ra); const uint32_t coreset_id = 0; srsran_sch_grant_nr_t grant; for (uint32_t m = 0; m < cfg.pusch.nof_common_time_ra; ++m) { int ret = srsran_ra_ul_nr_time(&cfg.pusch, srsran_rnti_type_ra, srsran_search_space_type_rar, coreset_id, m, &grant); srsran_assert(ret == SRSRAN_SUCCESS, "Failed to obtain RA config"); - pusch_rach_list[m].msg3_delay = grant.k; - pusch_rach_list[m].S = grant.S; - pusch_rach_list[m].L = grant.L; + pusch_ra_list[m].msg3_delay = grant.k; + ret = srsran_ra_ul_nr_time(&cfg.pusch, srsran_rnti_type_c, srsran_search_space_type_ue, coreset_id, m, &grant); + pusch_ra_list[m].K = grant.k; + pusch_ra_list[m].S = grant.S; + pusch_ra_list[m].L = grant.L; + srsran_assert(ret == SRSRAN_SUCCESS, "Failed to obtain RA config"); } - srsran_assert(not pusch_rach_list.empty(), "Time-Domain Resource Allocation not valid"); + srsran_assert(not pusch_ra_list.empty(), "Time-Domain Resource Allocation not valid"); } sched_cell_params::sched_cell_params(uint32_t cc_, const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_) : diff --git a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc index aee8c6c55..cdcf4f630 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc @@ -73,7 +73,7 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint32_t static const uint32_t msg3_nof_prbs = 3, m = 0; bwp_slot_grid& bwp_pdcch_slot = bwp_grid[pdcch_tti]; - tti_point msg3_tti = pdcch_tti + cfg.pusch_rach_list[m].msg3_delay; + tti_point msg3_tti = pdcch_tti + cfg.pusch_ra_list[m].msg3_delay; bwp_slot_grid& bwp_msg3_slot = bwp_grid[msg3_tti]; alloc_result ret = verify_pusch_space(bwp_msg3_slot, nullptr); if (ret != alloc_result::success) { diff --git a/srsenb/src/stack/mac/nr/sched_nr_ue.cc b/srsenb/src/stack/mac/nr/sched_nr_ue.cc index bf408ec00..45785eb94 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_ue.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_ue.cc @@ -49,7 +49,7 @@ slot_ue ue_carrier::try_reserve(tti_point pdcch_tti) uint32_t k1 = sfu.cfg->phy().harq_ack.dl_data_to_ul_ack[sfu.pdsch_tti.sf_idx() % sfu.cfg->phy().harq_ack.nof_dl_data_to_ul_ack]; sfu.uci_tti = sfu.pdsch_tti + k1; - uint32_t k2 = k1; + uint32_t k2 = bwp_cfg.active_bwp().pusch_ra_list[0].K; sfu.pusch_tti = sfu.pdcch_tti + k2; sfu.dl_cqi = dl_cqi; sfu.ul_cqi = ul_cqi; From 1a15a65483788144bf3ba9270b6194a2517d13dd Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 21 Jul 2021 18:35:43 +0200 Subject: [PATCH 31/34] Add missing parameters to enb.conf.example --- srsenb/enb.conf.example | 13 ++++++++++--- srsenb/src/main.cc | 12 ++++++------ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/srsenb/enb.conf.example b/srsenb/enb.conf.example index d3c36dc18..eeb99daf9 100644 --- a/srsenb/enb.conf.example +++ b/srsenb/enb.conf.example @@ -323,6 +323,10 @@ enable = false # metrics_period_secs: Sets the period at which metrics are requested from the eNB. # metrics_csv_enable: Write eNB metrics to CSV file. # metrics_csv_filename: File path to use for CSV metrics. +# report_json_enable: Write eNB report to JSON file (default disabled) +# report_json_filename: Report JSON filename (default /tmp/enb_report.json) +# alarms_log_enable: Enable Alarms logging (default diabled) +# alarms_filename: Alarms logging filename (default /tmp/alarms.log) # tracing_enable: Write source code tracing information to a file. # tracing_filename: File path to use for tracing information. # tracing_buffcapacity: Maximum capacity in bytes the tracing framework can store. @@ -330,14 +334,16 @@ enable = false # pregenerate_signals: Pregenerate uplink signals after attach. Improves CPU performance. # tx_amplitude: Transmit amplitude factor (set 0-1 to reduce PAPR) # rrc_inactivity_timer Inactivity timeout used to remove UE context from RRC (in milliseconds). +# max_mac_dl_kos: Maximum number of consecutive KOs in DL before triggering the UE's release (default 100) +# max_mac_ul_kos: Maximum number of consecutive KOs in UL before triggering the UE's release (default 100) # max_prach_offset_us: Maximum allowed RACH offset (in us) # nof_prealloc_ues: Number of UE memory resources to preallocate during eNB initialization for faster UE creation (Default 8) # rlf_release_timer_ms: Time taken by eNB to release UE context after it detects an RLF # eea_pref_list: Ordered preference list for the selection of encryption algorithm (EEA) (default: EEA0, EEA2, EEA1). # eia_pref_list: Ordered preference list for the selection of integrity algorithm (EIA) (default: EIA2, EIA1, EIA0). # gtpu_tunnel_timeout: Time that GTPU takes to release indirect forwarding tunnel since the last received GTPU PDU (0 for no timer). -#ts1_reloc_prep_timeout: S1AP TS 36.413 TS1RelocPrep Expiry Timeout value in milliseconds -#ts1_reloc_overall_timeout: S1AP TS 36.413 TS1RelocOverall Expiry Timeout value in milliseconds +# ts1_reloc_prep_timeout: S1AP TS 36.413 TS1RelocPrep Expiry Timeout value in milliseconds +# ts1_reloc_overall_timeout: S1AP TS 36.413 TS1RelocOverall Expiry Timeout value in milliseconds # rlf_release_timer_ms: Time taken by eNB to release UE context after it detects an RLF # rlf_min_ul_snr_estim: SNR threshold in dB below which the enb is notified with rlf ko # @@ -360,7 +366,8 @@ enable = false #pregenerate_signals = false #tx_amplitude = 0.6 #rrc_inactivity_timer = 30000 -#max_nof_kos = 100 +#max_mac_dl_kos = 100 +#max_mac_ul_kos = 100 #max_prach_offset_us = 30 #nof_prealloc_ues = 8 #rlf_release_timer_ms = 4000 diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 2fb380ff0..a3f548623 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -220,10 +220,10 @@ void parse_args(all_args_t* args, int argc, char* argv[]) ("expert.equalizer_mode", bpo::value(&args->phy.equalizer_mode)->default_value("mmse"), "Equalizer mode") ("expert.estimator_fil_w", bpo::value(&args->phy.estimator_fil_w)->default_value(0.1), "Chooses the coefficients for the 3-tap channel estimator centered filter.") ("expert.lte_sample_rates", bpo::value(&use_standard_lte_rates)->default_value(false), "Whether to use default LTE sample rates instead of shorter variants.") - ("expert.report_json_enable", bpo::value(&args->general.report_json_enable)->default_value(false), "Write eNB report to JSON file") - ("expert.report_json_filename", bpo::value(&args->general.report_json_filename)->default_value("/tmp/enb_report.json"), "Report JSON filename") - ("expert.alarms_log_enable", bpo::value(&args->general.alarms_log_enable)->default_value(false), "Log alarms") - ("expert.alarms_filename", bpo::value(&args->general.alarms_filename)->default_value("/tmp/enb_alarms.log"), "Alarms filename") + ("expert.report_json_enable", bpo::value(&args->general.report_json_enable)->default_value(false), "Write eNB report to JSON file (default disabled)") + ("expert.report_json_filename", bpo::value(&args->general.report_json_filename)->default_value("/tmp/enb_report.json"), "Report JSON filename (default /tmp/enb_report.json)") + ("expert.alarms_log_enable", bpo::value(&args->general.alarms_log_enable)->default_value(false), "Enable Alarms logging (default diabled)") + ("expert.alarms_filename", bpo::value(&args->general.alarms_filename)->default_value("/tmp/enb_alarms.log"), "Alarms logging filename (default /tmp/alarms.log)") ("expert.tracing_enable", bpo::value(&args->general.tracing_enable)->default_value(false), "Events tracing") ("expert.tracing_filename", bpo::value(&args->general.tracing_filename)->default_value("/tmp/enb_tracing.log"), "Tracing events filename") ("expert.tracing_buffcapacity", bpo::value(&args->general.tracing_buffcapacity)->default_value(1000000), "Tracing buffer capcity") @@ -234,8 +234,8 @@ void parse_args(all_args_t* args, int argc, char* argv[]) ("expert.eia_pref_list", bpo::value(&args->general.eia_pref_list)->default_value("EIA2, EIA1, EIA0"), "Ordered preference list for the selection of integrity algorithm (EIA) (default: EIA2, EIA1, EIA0).") ("expert.nof_prealloc_ues", bpo::value(&args->stack.mac.nof_prealloc_ues)->default_value(8), "Number of UE resources to preallocate during eNB initialization") ("expert.lcid_padding", bpo::value(&args->stack.mac.lcid_padding)->default_value(3), "LCID on which to put MAC padding") - ("expert.max_mac_dl_kos", bpo::value(&args->general.max_mac_dl_kos)->default_value(100), "Maximum number of consecutive KOs in DL before triggering the UE's release") - ("expert.max_mac_ul_kos", bpo::value(&args->general.max_mac_ul_kos)->default_value(100), "Maximum number of consecutive KOs in UL before triggering the UE's release") + ("expert.max_mac_dl_kos", bpo::value(&args->general.max_mac_dl_kos)->default_value(100), "Maximum number of consecutive KOs in DL before triggering the UE's release (default 100)") + ("expert.max_mac_ul_kos", bpo::value(&args->general.max_mac_ul_kos)->default_value(100), "Maximum number of consecutive KOs in UL before triggering the UE's release (default 100)") ("expert.gtpu_tunnel_timeout", bpo::value(&args->stack.gtpu_indirect_tunnel_timeout_msec)->default_value(0), "Maximum time that GTPU takes to release indirect forwarding tunnel since the last received GTPU PDU. (0 for infinity)") ("expert.rlf_release_timer_ms", bpo::value(&args->general.rlf_release_timer_ms)->default_value(4000), "Time taken by eNB to release UE context after it detects an RLF") ("expert.extended_cp", bpo::value(&args->phy.extended_cp)->default_value(false), "Use extended cyclic prefix") From 24e52d62911d1443aed4b2b47a2e783427e60a21 Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Wed, 21 Jul 2021 15:07:54 +0200 Subject: [PATCH 32/34] soapy: fix array parameter mismatch for some functions With soapy 0.8.0, GCC 11.1.0 warns of mismatched array bounds in some functions. This commit aligns the bound and adds proper wrappers to fix subsequent warnings. --- lib/src/phy/rf/rf_soapy_imp.c | 16 +++++++++++----- lib/src/phy/rf/rf_soapy_imp.h | 9 +++++++-- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/lib/src/phy/rf/rf_soapy_imp.c b/lib/src/phy/rf/rf_soapy_imp.c index ffa282bab..adbc9f559 100644 --- a/lib/src/phy/rf/rf_soapy_imp.c +++ b/lib/src/phy/rf/rf_soapy_imp.c @@ -256,11 +256,15 @@ int rf_soapy_stop_tx_stream(void* h) void rf_soapy_flush_buffer(void* h) { int n; - cf_t tmp1[1024]; - cf_t tmp2[1024]; - void* data[2] = {tmp1, tmp2}; + cf_t dummy[1024]; + void* data[SRSRAN_MAX_CHANNELS] = {}; + + for (int i = 0; i < SRSRAN_MAX_CHANNELS; i++) { + data[i] = dummy; + } + do { - n = rf_soapy_recv_with_time_multi(h, data, 1024, 0, NULL, NULL); + n = rf_soapy_recv_with_time_multi(h, data, sizeof(dummy), 0, NULL, NULL); } while (n > 0); } @@ -848,7 +852,9 @@ int rf_soapy_recv_with_time_multi(void* h, int rf_soapy_recv_with_time(void* h, void* data, uint32_t nsamples, bool blocking, time_t* secs, double* frac_secs) { - return rf_soapy_recv_with_time_multi(h, &data, nsamples, blocking, secs, frac_secs); + void* data_multi[SRSRAN_MAX_PORTS] = {NULL}; + data_multi[0] = data; + return rf_soapy_recv_with_time_multi(h, data_multi, nsamples, blocking, secs, frac_secs); } int rf_soapy_send_timed(void* h, diff --git a/lib/src/phy/rf/rf_soapy_imp.h b/lib/src/phy/rf/rf_soapy_imp.h index 2f31230e1..ff7facf34 100644 --- a/lib/src/phy/rf/rf_soapy_imp.h +++ b/lib/src/phy/rf/rf_soapy_imp.h @@ -14,6 +14,7 @@ #define SRSRAN_RF_SOAPY_IMP_H_ #include "srsran/config.h" +#include "srsran/phy/common/phy_common.h" #include "srsran/phy/rf/rf.h" #include #include @@ -66,8 +67,12 @@ SRSRAN_API double rf_soapy_set_rx_freq(void* h, uint32_t ch, double freq); SRSRAN_API int rf_soapy_recv_with_time(void* h, void* data, uint32_t nsamples, bool blocking, time_t* secs, double* frac_secs); -SRSRAN_API int -rf_soapy_recv_with_time_multi(void* h, void** data, uint32_t nsamples, bool blocking, time_t* secs, double* frac_secs); +SRSRAN_API int rf_soapy_recv_with_time_multi(void* h, + void* data[SRSRAN_MAX_PORTS], + uint32_t nsamples, + bool blocking, + time_t* secs, + double* frac_secs); SRSRAN_API double rf_soapy_set_tx_srate(void* h, double freq); From 91720590782332c79a2e872603896511dfc06ed5 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Tue, 20 Jul 2021 09:38:08 +0200 Subject: [PATCH 33/34] Supply ctor with logger instead of fetching --- srsenb/src/stack/gnb_stack_nr.cc | 2 +- srsue/hdr/stack/upper/gw.h | 2 +- srsue/hdr/stack/upper/nas.h | 2 +- srsue/hdr/stack/upper/nas_5g.h | 2 +- srsue/hdr/stack/upper/nas_base.h | 2 +- srsue/src/stack/rrc/test/rrc_meas_test.cc | 2 +- srsue/src/stack/ue_stack_lte.cc | 2 +- srsue/src/stack/upper/gw.cc | 2 +- srsue/src/stack/upper/nas.cc | 4 ++-- srsue/src/stack/upper/nas_5g.cc | 4 ++-- srsue/src/stack/upper/nas_base.cc | 2 +- srsue/src/stack/upper/test/gw_test.cc | 2 +- srsue/src/stack/upper/test/nas_5g_test.cc | 4 ++-- srsue/src/stack/upper/test/nas_test.cc | 10 +++++----- srsue/src/ue.cc | 4 ++-- 15 files changed, 23 insertions(+), 23 deletions(-) diff --git a/srsenb/src/stack/gnb_stack_nr.cc b/srsenb/src/stack/gnb_stack_nr.cc index d287d2888..abf148c08 100644 --- a/srsenb/src/stack/gnb_stack_nr.cc +++ b/srsenb/src/stack/gnb_stack_nr.cc @@ -23,7 +23,7 @@ gnb_stack_nr::gnb_stack_nr() : task_sched{512, 128}, thread("gNB"), rlc_logger(s m_pdcp.reset(new pdcp_nr(&task_sched, "PDCP-NR")); m_rrc.reset(new rrc_nr(&task_sched)); m_sdap.reset(new sdap()); - m_gw.reset(new srsue::gw()); + m_gw.reset(new srsue::gw(srslog::fetch_basic_logger("GW"))); // m_gtpu.reset(new srsenb::gtpu()); ue_task_queue = task_sched.make_task_queue(); diff --git a/srsue/hdr/stack/upper/gw.h b/srsue/hdr/stack/upper/gw.h index dc36f38ea..8ea0a345b 100644 --- a/srsue/hdr/stack/upper/gw.h +++ b/srsue/hdr/stack/upper/gw.h @@ -43,7 +43,7 @@ struct gw_args_t { class gw : public gw_interface_stack, public srsran::thread { public: - gw(); + gw(srslog::basic_logger& logger_); int init(const gw_args_t& args_, stack_interface_gw* stack); void stop(); diff --git a/srsue/hdr/stack/upper/nas.h b/srsue/hdr/stack/upper/nas.h index 2294096f4..bfb4d2a6a 100644 --- a/srsue/hdr/stack/upper/nas.h +++ b/srsue/hdr/stack/upper/nas.h @@ -38,7 +38,7 @@ class rrc_interface_nas; class nas : public nas_interface_rrc, public srsran::timer_callback, public nas_base { public: - explicit nas(srsran::task_sched_handle task_sched_); + explicit nas(srslog::basic_logger& logger_, srsran::task_sched_handle task_sched_); virtual ~nas(); int init(usim_interface_nas* usim_, rrc_interface_nas* rrc_, gw_interface_nas* gw_, const nas_args_t& args_); void stop(); diff --git a/srsue/hdr/stack/upper/nas_5g.h b/srsue/hdr/stack/upper/nas_5g.h index 34171d605..484e55875 100644 --- a/srsue/hdr/stack/upper/nas_5g.h +++ b/srsue/hdr/stack/upper/nas_5g.h @@ -35,7 +35,7 @@ namespace srsue { class nas_5g : public nas_base, public nas_5g_interface_rrc_nr, public nas_5g_interface_procedures { public: - explicit nas_5g(srsran::task_sched_handle task_sched_); + explicit nas_5g(srslog::basic_logger& logger_, srsran::task_sched_handle task_sched_); virtual ~nas_5g(); int init(usim_interface_nas* usim_, rrc_nr_interface_nas_5g* rrc_nr_, gw_interface_nas* gw_, const nas_args_t& cfg_); void stop(); diff --git a/srsue/hdr/stack/upper/nas_base.h b/srsue/hdr/stack/upper/nas_base.h index 225278146..68d4ec151 100644 --- a/srsue/hdr/stack/upper/nas_base.h +++ b/srsue/hdr/stack/upper/nas_base.h @@ -28,7 +28,7 @@ namespace srsue { class nas_base { public: - nas_base(const std::string& type_); + nas_base(srslog::basic_logger& logger_); // PCAP void start_pcap(srsran::nas_pcap* pcap_) { pcap = pcap_; } diff --git a/srsue/src/stack/rrc/test/rrc_meas_test.cc b/srsue/src/stack/rrc/test/rrc_meas_test.cc index 1c438ebf0..530d4f2f5 100644 --- a/srsue/src/stack/rrc/test/rrc_meas_test.cc +++ b/srsue/src/stack/rrc/test/rrc_meas_test.cc @@ -187,7 +187,7 @@ public: class nas_test : public srsue::nas { public: - nas_test(srsran::task_sched_handle t) : srsue::nas(t) {} + nas_test(srsran::task_sched_handle t) : srsue::nas(srslog::fetch_basic_logger("NAS"), t) {} bool is_registered() override { return false; } }; diff --git a/srsue/src/stack/ue_stack_lte.cc b/srsue/src/stack/ue_stack_lte.cc index 4bef269a1..3d84ea6ab 100644 --- a/srsue/src/stack/ue_stack_lte.cc +++ b/srsue/src/stack/ue_stack_lte.cc @@ -50,7 +50,7 @@ ue_stack_lte::ue_stack_lte() : rrc_nr(&task_sched), pdcp(&task_sched, "PDCP"), pdcp_nr(&task_sched, "PDCP-NR"), - nas(&task_sched), + nas(srslog::fetch_basic_logger("NAS", false), &task_sched), thread("STACK"), task_sched(512, 64), tti_tprof("tti_tprof", "STCK", TTI_STAT_PERIOD) diff --git a/srsue/src/stack/upper/gw.cc b/srsue/src/stack/upper/gw.cc index 4ae579421..af75a7438 100644 --- a/srsue/src/stack/upper/gw.cc +++ b/srsue/src/stack/upper/gw.cc @@ -29,7 +29,7 @@ namespace srsue { -gw::gw() : thread("GW"), logger(srslog::fetch_basic_logger("GW", false)), tft_matcher(logger) {} +gw::gw(srslog::basic_logger& logger_) : thread("GW"), logger(logger_), tft_matcher(logger) {} int gw::init(const gw_args_t& args_, stack_interface_gw* stack_) { diff --git a/srsue/src/stack/upper/nas.cc b/srsue/src/stack/upper/nas.cc index 7a228a209..489026d04 100644 --- a/srsue/src/stack/upper/nas.cc +++ b/srsue/src/stack/upper/nas.cc @@ -34,8 +34,8 @@ namespace srsue { * NAS ********************************************************************/ -nas::nas(srsran::task_sched_handle task_sched_) : - nas_base("NAS"), +nas::nas(srslog::basic_logger& logger_, srsran::task_sched_handle task_sched_) : + nas_base(logger_), plmn_searcher(this), task_sched(task_sched_), t3402(task_sched_.get_unique_timer()), diff --git a/srsue/src/stack/upper/nas_5g.cc b/srsue/src/stack/upper/nas_5g.cc index 97718fc75..a210af22f 100644 --- a/srsue/src/stack/upper/nas_5g.cc +++ b/srsue/src/stack/upper/nas_5g.cc @@ -36,8 +36,8 @@ namespace srsue { * NAS 5G (NR) ********************************************************************/ -nas_5g::nas_5g(srsran::task_sched_handle task_sched_) : - nas_base("NAS-5G"), +nas_5g::nas_5g(srslog::basic_logger& logger_, srsran::task_sched_handle task_sched_) : + nas_base(logger_), task_sched(task_sched_), t3502(task_sched_.get_unique_timer()), t3510(task_sched_.get_unique_timer()), diff --git a/srsue/src/stack/upper/nas_base.cc b/srsue/src/stack/upper/nas_base.cc index b4a01f76a..635213d58 100644 --- a/srsue/src/stack/upper/nas_base.cc +++ b/srsue/src/stack/upper/nas_base.cc @@ -14,7 +14,7 @@ using namespace srsran; namespace srsue { -nas_base::nas_base(const std::string& type_) : logger(srslog::fetch_basic_logger(type_)) {} +nas_base::nas_base(srslog::basic_logger& logger_) : logger(logger_) {} int nas_base::parse_security_algorithm_list(std::string algorithm_string, bool* algorithm_caps) { diff --git a/srsue/src/stack/upper/test/gw_test.cc b/srsue/src/stack/upper/test/gw_test.cc index 9aa26226a..0198e2e8a 100644 --- a/srsue/src/stack/upper/test/gw_test.cc +++ b/srsue/src/stack/upper/test/gw_test.cc @@ -33,7 +33,7 @@ int gw_test() gw_args.log.gw_level = "debug"; gw_args.log.gw_hex_limit = 100000; test_stack_dummy stack; - srsue::gw gw; + srsue::gw gw(srslog::fetch_basic_logger("GW")); gw.init(gw_args, &stack); uint32_t eps_bearer_id = 5; diff --git a/srsue/src/stack/upper/test/nas_5g_test.cc b/srsue/src/stack/upper/test/nas_5g_test.cc index 8556e326a..5a48ead48 100644 --- a/srsue/src/stack/upper/test/nas_5g_test.cc +++ b/srsue/src/stack/upper/test/nas_5g_test.cc @@ -49,8 +49,8 @@ int amf_attach_request_test(srsran::nas_pcap* pcap) nas_cfg.ea5g = "0,1,2,3"; test_stack_dummy stack(&pdcp_dummy); - srsue::nas_5g nas_5g(&stack.task_sched); - srsue::gw gw; + srsue::nas_5g nas_5g(srslog::fetch_basic_logger("NAS-5G"), &stack.task_sched); + srsue::gw gw(srslog::fetch_basic_logger("GW")); if (pcap != nullptr) { nas_5g.start_pcap(pcap); diff --git a/srsue/src/stack/upper/test/nas_test.cc b/srsue/src/stack/upper/test/nas_test.cc index 825d29ee4..edbc5e72a 100644 --- a/srsue/src/stack/upper/test/nas_test.cc +++ b/srsue/src/stack/upper/test/nas_test.cc @@ -59,8 +59,8 @@ int mme_attach_request_test() nas_cfg.apn_name = "test123"; test_stack_dummy stack(&pdcp_dummy); - srsue::nas nas(&stack.task_sched); - srsue::gw gw; + srsue::nas nas(srslog::fetch_basic_logger("NAS"), &stack.task_sched); + srsue::gw gw(srslog::fetch_basic_logger("GW")); nas.init(&usim, &rrc_dummy, &gw, nas_cfg); rrc_dummy.init(&nas); @@ -124,7 +124,7 @@ int security_command_test() usim.init(&args); { - srsue::nas nas(&stack.task_sched); + srsue::nas nas(srslog::fetch_basic_logger("NAS"), &stack.task_sched); nas_args_t cfg; cfg.eia = "1,2,3"; cfg.eea = "0,1,2,3"; @@ -179,7 +179,7 @@ int esm_info_request_test() usim.init(&args); { - srsue::nas nas(&stack.task_sched); + srsue::nas nas(srslog::fetch_basic_logger("NAS-5G"), &stack.task_sched); nas_args_t cfg; cfg.apn_name = "srsran"; cfg.apn_user = "srsuser"; @@ -223,7 +223,7 @@ int dedicated_eps_bearer_test() srsue::usim usim(srslog::fetch_basic_logger("USIM")); usim.init(&args); - srsue::nas nas(&stack.task_sched); + srsue::nas nas(srslog::fetch_basic_logger("NAS"), &stack.task_sched); nas_args_t cfg = {}; cfg.force_imsi_attach = true; // make sure we get a fresh security context cfg.eia = "1,2,3"; diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index e5413776f..484ec23bb 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -61,7 +61,7 @@ int ue::init(const all_args_t& args_) return SRSRAN_ERROR; } - std::unique_ptr gw_ptr(new gw()); + std::unique_ptr gw_ptr(new gw(srslog::fetch_basic_logger("GW"))); if (!gw_ptr) { srsran::console("Error creating a GW instance.\n"); return SRSRAN_ERROR; @@ -123,7 +123,7 @@ int ue::init(const all_args_t& args_) std::unique_ptr nr_stack(new srsue::ue_stack_nr()); std::unique_ptr nr_radio(new srsran::radio_null); std::unique_ptr nr_phy; - std::unique_ptr gw_ptr(new gw()); + std::unique_ptr gw_ptr(new gw(srslog::fetch_basic_logger("GW"))); // Init layers if (nr_radio->init(args.rf, nullptr)) { From 2563a78f34003535b024e0e3c27a8e6454cea138 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Wed, 21 Jul 2021 18:32:50 +0200 Subject: [PATCH 34/34] Added basic 5G NAS metrics --- srsue/hdr/stack/upper/nas_5g.h | 1 + srsue/hdr/stack/upper/nas_5g_metrics.h | 27 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 srsue/hdr/stack/upper/nas_5g_metrics.h diff --git a/srsue/hdr/stack/upper/nas_5g.h b/srsue/hdr/stack/upper/nas_5g.h index 484e55875..fc13ede48 100644 --- a/srsue/hdr/stack/upper/nas_5g.h +++ b/srsue/hdr/stack/upper/nas_5g.h @@ -25,6 +25,7 @@ #include "srsran/interfaces/ue_rrc_interfaces.h" #include "srsran/interfaces/ue_usim_interfaces.h" #include "srsran/srslog/srslog.h" +#include "srsue/hdr/stack/upper/nas_5g_metrics.h" #include "srsue/hdr/stack/upper/nas_5gmm_state.h" #include "srsue/hdr/stack/upper/nas_config.h" diff --git a/srsue/hdr/stack/upper/nas_5g_metrics.h b/srsue/hdr/stack/upper/nas_5g_metrics.h new file mode 100644 index 000000000..3dc7b425b --- /dev/null +++ b/srsue/hdr/stack/upper/nas_5g_metrics.h @@ -0,0 +1,27 @@ +/** + * + * \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 SRSUE_NAS_5G_METRICS_H +#define SRSUE_NAS_5G_METRICS_H + +#include "nas_5gmm_state.h" + +namespace srsue { + +struct nas_5g_metrics_t { + uint32_t nof_active_5g_bearers; + mm5g_state_t::state_t state; +}; + +} // namespace srsue + +#endif // SRSUE_NAS_5G_METRICS_H