diff --git a/lib/include/srsran/asn1/rrc_nr_utils.h b/lib/include/srsran/asn1/rrc_nr_utils.h index 52e60d2f4..3fd1d0e95 100644 --- a/lib/include/srsran/asn1/rrc_nr_utils.h +++ b/lib/include/srsran/asn1/rrc_nr_utils.h @@ -82,7 +82,7 @@ void to_asn1(asn1::rrc_nr::plmn_id_s* asn1_type, const plmn_id_t& cfg); bool make_phy_rach_cfg(const asn1::rrc_nr::rach_cfg_common_s& asn1_type, srsran_prach_cfg_t* prach_cfg); bool make_phy_tdd_cfg(const asn1::rrc_nr::tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common, - srsran_tdd_config_nr_t* srsran_tdd_config_nr); + srsran_duplex_config_nr_t* srsran_duplex_config_nr); bool make_phy_harq_ack_cfg(const asn1::rrc_nr::phys_cell_group_cfg_s& phys_cell_group_cfg, srsran_harq_ack_cfg_hl_t* srsran_ue_dl_nr_harq_ack_cfg); bool make_phy_coreset_cfg(const asn1::rrc_nr::ctrl_res_set_s& ctrl_res_set, srsran_coreset_t* srsran_coreset); diff --git a/lib/include/srsran/common/bearer_manager.h b/lib/include/srsran/common/bearer_manager.h index 41ca29c65..1aba22f28 100644 --- a/lib/include/srsran/common/bearer_manager.h +++ b/lib/include/srsran/common/bearer_manager.h @@ -113,11 +113,23 @@ public: /// All registered bearer are removed (e.g. after connection release) void reset(); - bool has_active_radio_bearer(uint32_t eps_bearer_id) { return impl.has_active_radio_bearer(eps_bearer_id); } - - radio_bearer_t get_radio_bearer(uint32_t eps_bearer_id) { return impl.get_radio_bearer(eps_bearer_id); } - - radio_bearer_t get_lcid_bearer(uint32_t lcid) { return impl.get_lcid_bearer(lcid); } + bool has_active_radio_bearer(uint32_t eps_bearer_id) + { + srsran::rwlock_read_guard rw_lock(rwlock); + return impl.has_active_radio_bearer(eps_bearer_id); + } + + radio_bearer_t get_radio_bearer(uint32_t eps_bearer_id) + { + srsran::rwlock_read_guard rw_lock(rwlock); + return impl.get_radio_bearer(eps_bearer_id); + } + + radio_bearer_t get_lcid_bearer(uint32_t lcid) + { + srsran::rwlock_read_guard rw_lock(rwlock); + return impl.get_lcid_bearer(lcid); + } private: pthread_rwlock_t rwlock = {}; /// RW lock to protect access from RRC/GW threads diff --git a/lib/include/srsran/common/phy_cfg_nr.h b/lib/include/srsran/common/phy_cfg_nr.h index 80abe33f4..aed5ed988 100644 --- a/lib/include/srsran/common/phy_cfg_nr.h +++ b/lib/include/srsran/common/phy_cfg_nr.h @@ -44,16 +44,16 @@ struct phy_cfg_nr_t { srsran_subcarrier_spacing_t scs = srsran_subcarrier_spacing_30kHz; }; - srsran_tdd_config_nr_t tdd = {}; - srsran_sch_hl_cfg_nr_t pdsch = {}; - srsran_sch_hl_cfg_nr_t pusch = {}; - srsran_pucch_nr_hl_cfg_t pucch = {}; - srsran_prach_cfg_t prach = {}; - srsran_pdcch_cfg_nr_t pdcch = {}; - srsran_harq_ack_cfg_hl_t harq_ack = {}; - srsran_csi_hl_cfg_t csi = {}; - srsran_carrier_nr_t carrier = {}; - ssb_cfg_t ssb; + srsran_duplex_config_nr_t duplex = {}; + srsran_sch_hl_cfg_nr_t pdsch = {}; + srsran_sch_hl_cfg_nr_t pusch = {}; + srsran_pucch_nr_hl_cfg_t pucch = {}; + srsran_prach_cfg_t prach = {}; + srsran_pdcch_cfg_nr_t pdcch = {}; + srsran_harq_ack_cfg_hl_t harq_ack = {}; + srsran_csi_hl_cfg_t csi = {}; + srsran_carrier_nr_t carrier = {}; + ssb_cfg_t ssb; phy_cfg_nr_t() {} diff --git a/lib/include/srsran/common/phy_cfg_nr_default.h b/lib/include/srsran/common/phy_cfg_nr_default.h index e3e494438..5d071b139 100644 --- a/lib/include/srsran/common/phy_cfg_nr_default.h +++ b/lib/include/srsran/common/phy_cfg_nr_default.h @@ -52,18 +52,23 @@ public: const std::array R_CARRIER_STRING = {{"10MHz", "20MHz"}}; enum { + /** + * @brief FDD, all slots for DL and UL + */ + R_DUPLEX_FDD = 0, + /** * @brief TDD custom reference 5 slot DL and 5 slot UL */ - R_TDD_CUSTOM_6_4 = 0, + R_DUPLEX_TDD_CUSTOM_6_4, /** * @brief TDD pattern FR1.15-1 defined in TS38.101-4 Table A.1.2-1 */ - R_TDD_FR1_15_1, - R_TDD_COUNT, - } tdd = R_TDD_CUSTOM_6_4; - const std::array R_TDD_STRING = {{"6D+4U", "FR1.15-1"}}; + R_DUPLEX_TDD_FR1_15_1, + R_DUPLEX_COUNT, + } duplex = R_DUPLEX_TDD_CUSTOM_6_4; + const std::array R_DUPLEX_STRING = {{"FDD", "6D+4U", "FR1.15-1"}}; enum { /** @@ -153,8 +158,8 @@ private: /** * TDD make helper methods */ - static void make_tdd_custom_6_4(srsran_tdd_config_nr_t& tdd); - static void make_tdd_fr1_15_1(srsran_tdd_config_nr_t& tdd); + static void make_tdd_custom_6_4(srsran_duplex_config_nr_t& duplex); + static void make_tdd_fr1_15_1(srsran_duplex_config_nr_t& duplex); /** * PDCCH make helper methods @@ -180,9 +185,9 @@ private: /** * HARQ make helper methods */ - static void make_harq_auto(srsran_harq_ack_cfg_hl_t& harq, - const srsran_carrier_nr_t& carrier, - const srsran_tdd_config_nr_t& tdd_cfg); + static void make_harq_auto(srsran_harq_ack_cfg_hl_t& harq, + const srsran_carrier_nr_t& carrier, + const srsran_duplex_config_nr_t& duplex_cfg); /** * PRACH make helper methods diff --git a/lib/include/srsran/interfaces/enb_interfaces.h b/lib/include/srsran/interfaces/enb_interfaces.h index 671b80b0d..990e05aff 100644 --- a/lib/include/srsran/interfaces/enb_interfaces.h +++ b/lib/include/srsran/interfaces/enb_interfaces.h @@ -23,6 +23,8 @@ #include "srsran/common/interfaces_common.h" #include "srsran/srsran.h" +#include "srsran/interfaces/enb_rrc_interfaces.h" + #ifndef SRSRAN_ENB_INTERFACES_H #define SRSRAN_ENB_INTERFACES_H @@ -36,8 +38,6 @@ public: virtual void remove_eps_bearers(uint16_t rnti) = 0; }; -class stack_interface_phy_lte; - } // namespace srsenb #endif // SRSRAN_ENB_INTERFACES_H diff --git a/lib/include/srsran/interfaces/enb_mac_interfaces.h b/lib/include/srsran/interfaces/enb_mac_interfaces.h index 990e429bc..b85c9144a 100644 --- a/lib/include/srsran/interfaces/enb_mac_interfaces.h +++ b/lib/include/srsran/interfaces/enb_mac_interfaces.h @@ -267,8 +267,6 @@ public: // Combined interface for PHY to access stack (MAC and RRC) class stack_interface_phy_lte : public mac_interface_phy_lte { -public: - virtual void tti_clock() = 0; }; } // namespace srsenb diff --git a/lib/include/srsran/interfaces/enb_rrc_interfaces.h b/lib/include/srsran/interfaces/enb_rrc_interfaces.h index 05f966b89..dc58cda30 100644 --- a/lib/include/srsran/interfaces/enb_rrc_interfaces.h +++ b/lib/include/srsran/interfaces/enb_rrc_interfaces.h @@ -129,67 +129,6 @@ public: virtual void notify_pdcp_integrity_error(uint16_t rnti, uint32_t lcid) = 0; }; -// RRC interfaces for NSA operation - -/// X2AP inspired interface to allow EUTRA RRC to call NR RRC -class rrc_nr_interface_rrc -{ -public: - struct sgnb_addition_req_params_t { - uint32_t eps_bearer_id; - // add configuration check - // E-RAB Parameters, Tunnel address (IP address, TEID) - // QCI, security, etc - }; - - /// Request addition of NR carrier for UE - virtual int sgnb_addition_request(uint16_t eutra_rnti, const sgnb_addition_req_params_t& params) = 0; - - /// Provide information whether the requested configuration was applied successfully by the UE - 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: - /** - * @brief List of parameters included in the SgNB addition Ack message - * @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 - * @param eps_bearer_id ID of the transfered bearer - */ - struct sgnb_addition_ack_params_t { - uint16_t nr_rnti = SRSRAN_INVALID_RNTI; // RNTI that was assigned to the UE - asn1::dyn_octstring nr_secondary_cell_group_cfg_r15; - asn1::dyn_octstring nr_radio_bearer_cfg1_r15; - uint32_t eps_bearer_id = 0; // (list of) successfully transfered EPS bearers - }; - - /** - * @brief Signal successful addition of UE - * - * @param eutra_rnti The RNTI that the EUTRA RRC used to request the SgNB addition - * @param params Parameter list - */ - virtual void sgnb_addition_ack(uint16_t eutra_rnti, sgnb_addition_ack_params_t params) = 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 eutra_rnti The RNTI that the EUTRA RRC used to request the SgNB addition - * @param nr_rnti The RNTI that has been assigned to the UE on the SgNB - */ - virtual void sgnb_addition_complete(uint16_t eutra_rnti, uint16_t nr_rnti) = 0; -}; - } // namespace srsenb #endif // SRSRAN_ENB_RRC_INTERFACES_H diff --git a/lib/include/srsran/interfaces/enb_time_interface.h b/lib/include/srsran/interfaces/enb_time_interface.h new file mode 100644 index 000000000..e1ef79d90 --- /dev/null +++ b/lib/include/srsran/interfaces/enb_time_interface.h @@ -0,0 +1,31 @@ +/** + * + * \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_ENB_TIME_INTERFACE_H +#define SRSRAN_ENB_TIME_INTERFACE_H + +namespace srsenb { + +// RAT-agnostic interface to provide timing information to upper layers +class enb_time_interface +{ +public: + /** + * @brief Called for every tick (currently every ms) + * + */ + virtual void tti_clock() = 0; +}; + +} // namespace srsenb + +#endif // SRSRAN_ENB_TIME_INTERFACE_H diff --git a/lib/include/srsran/interfaces/enb_x2_interfaces.h b/lib/include/srsran/interfaces/enb_x2_interfaces.h new file mode 100644 index 000000000..a5b503ee3 --- /dev/null +++ b/lib/include/srsran/interfaces/enb_x2_interfaces.h @@ -0,0 +1,101 @@ +/** + * + * \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 "srsran/interfaces/enb_pdcp_interfaces.h" +#include "srsran/interfaces/enb_rrc_interface_types.h" + +#ifndef SRSRAN_ENB_X2_INTERFACES_H +#define SRSRAN_ENB_X2_INTERFACES_H + +namespace srsenb { + +/** + * @brief Set of X2AP inspired interfaces to support 5G NSA + * + */ + +/// X2AP inspired interface to allow EUTRA RRC to call NR RRC +class rrc_nr_interface_rrc +{ +public: + struct sgnb_addition_req_params_t { + uint32_t eps_bearer_id; + // add configuration check + // E-RAB Parameters, Tunnel address (IP address, TEID) + // QCI, security, etc + }; + + /// Request addition of NR carrier for UE + virtual int sgnb_addition_request(uint16_t eutra_rnti, const sgnb_addition_req_params_t& params) = 0; + + /// Provide information whether the requested configuration was applied successfully by the UE + 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: + /** + * @brief List of parameters included in the SgNB addition Ack message + * @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 + * @param eps_bearer_id ID of the transfered bearer + */ + struct sgnb_addition_ack_params_t { + uint16_t nr_rnti = SRSRAN_INVALID_RNTI; // RNTI that was assigned to the UE + asn1::dyn_octstring nr_secondary_cell_group_cfg_r15; + asn1::dyn_octstring nr_radio_bearer_cfg1_r15; + uint32_t eps_bearer_id = 0; // (list of) successfully transfered EPS bearers + }; + + /** + * @brief Signal successful addition of UE + * + * @param eutra_rnti The RNTI that the EUTRA RRC used to request the SgNB addition + * @param params Parameter list + */ + virtual void sgnb_addition_ack(uint16_t eutra_rnti, sgnb_addition_ack_params_t params) = 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 eutra_rnti The RNTI that the EUTRA RRC used to request the SgNB addition + * @param nr_rnti The RNTI that has been assigned to the UE on the SgNB + */ + virtual void sgnb_addition_complete(uint16_t eutra_rnti, uint16_t nr_rnti) = 0; +}; + +class stack_nr_interface_stack_eutra +{ +public: + /// Helper method to provide time signal to NR-RRC (PHY only sends TTI ticks to EUTRA stack) + virtual void tti_clock() = 0; +}; + +// combined interface used by X2 adapter +class x2_interface : public rrc_nr_interface_rrc, + public rrc_eutra_interface_rrc_nr, + public stack_nr_interface_stack_eutra, + public pdcp_interface_gtpu +{}; + +} // namespace srsenb + +#endif // SRSRAN_ENB_X2_INTERFACES_H diff --git a/lib/include/srsran/interfaces/ue_nr_interfaces.h b/lib/include/srsran/interfaces/ue_nr_interfaces.h index 18d1953f0..b7eba05ec 100644 --- a/lib/include/srsran/interfaces/ue_nr_interfaces.h +++ b/lib/include/srsran/interfaces/ue_nr_interfaces.h @@ -189,6 +189,7 @@ struct phy_args_nr_t { bool store_pdsch_ko = false; float trs_epre_ema_alpha = 0.1f; ///< EPRE measurement exponential average alpha float trs_rsrp_ema_alpha = 0.1f; ///< RSRP measurement exponential average alpha + float trs_sinr_ema_alpha = 0.1f; ///< SINR measurement exponential average alpha float trs_cfo_ema_alpha = 0.1f; ///< RSRP measurement exponential average alpha bool enable_worker_cfo = true; ///< Enable/Disable open loop CFO correction at the workers diff --git a/lib/include/srsran/phy/ch_estimation/csi_rs_cfg.h b/lib/include/srsran/phy/ch_estimation/csi_rs_cfg.h index b3d4fc3f6..8ed96f82f 100644 --- a/lib/include/srsran/phy/ch_estimation/csi_rs_cfg.h +++ b/lib/include/srsran/phy/ch_estimation/csi_rs_cfg.h @@ -137,4 +137,6 @@ typedef struct SRSRAN_API { uint32_t count; ///< Number of resources in the set } srsran_csi_rs_zp_set_t; +SRSRAN_API bool srsran_csi_rs_resource_mapping_is_valid(const srsran_csi_rs_resource_mapping_t *res); + #endif // SRSRAN_CSI_RS_CFG_H diff --git a/lib/include/srsran/phy/common/phy_common_nr.h b/lib/include/srsran/phy/common/phy_common_nr.h index b9e70d394..f96aa232b 100644 --- a/lib/include/srsran/phy/common/phy_common_nr.h +++ b/lib/include/srsran/phy/common/phy_common_nr.h @@ -467,6 +467,17 @@ typedef struct SRSRAN_API { srsran_tdd_pattern_t pattern2; } srsran_tdd_config_nr_t; +/** + * @brief Describes duplex configuration + */ +typedef struct SRSRAN_API { + srsran_duplex_mode_t mode; + union { + srsran_tdd_config_nr_t tdd; ///< TDD configuration + // ... add here other mode parameters + }; +} srsran_duplex_config_nr_t; + /** * @brief Describes a measurement based on NZP-CSI-RS or SSB-CSI * @note Used for tracking RSRP, SNR, CFO, SFO, and so on @@ -501,6 +512,13 @@ SRSRAN_API const char* srsran_rnti_type_str(srsran_rnti_type_t rnti_type); */ SRSRAN_API const char* srsran_rnti_type_str_short(srsran_rnti_type_t rnti_type); +/** + * @brief Get the Search Space Type string for a given type + * @param ss_type The given Search Space Type + * @return The string describing the SS Type + */ +SRSRAN_API const char* srsran_ss_type_str(srsran_search_space_type_t ss_type); + /** * @brief Get the RNTI type name for NR * @param rnti_type RNTI type name @@ -595,21 +613,21 @@ SRSRAN_API float srsran_symbol_distance_s(uint32_t l0, uint32_t l1, srsran_subca /** * @brief Decides whether a given slot is configured as Downlink - * @param cfg Provides TDD configuration + * @param cfg Provides the carrier duplex configuration * @param numerology Provides BWP numerology * @param slot_idx Slot index in the frame for the given numerology * @return true if the provided slot index is configured for Downlink */ -SRSRAN_API bool srsran_tdd_nr_is_dl(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx); +SRSRAN_API bool srsran_duplex_nr_is_dl(const srsran_duplex_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx); /** * @brief Decides whether a given slot is configured as Uplink - * @param cfg Provides TDD configuration + * @param cfg Provides the carrier duplex configuration * @param numerology Provides BWP numerology * @param slot_idx Slot index in the frame for the given numerology * @return true if the provided slot index is configured for Uplink */ -SRSRAN_API bool srsran_tdd_nr_is_ul(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx); +SRSRAN_API bool srsran_duplex_nr_is_ul(const srsran_duplex_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx); SRSRAN_API int srsran_carrier_to_cell(const srsran_carrier_nr_t* carrier, srsran_cell_t* cell); diff --git a/lib/include/srsran/phy/gnb/gnb_dl.h b/lib/include/srsran/phy/gnb/gnb_dl.h index 12d01c5eb..50e3afa89 100644 --- a/lib/include/srsran/phy/gnb/gnb_dl.h +++ b/lib/include/srsran/phy/gnb/gnb_dl.h @@ -76,6 +76,8 @@ SRSRAN_API int srsran_gnb_dl_pdsch_put(srsran_gnb_dl_t* q, const srsran_sch_cfg_nr_t* cfg, uint8_t* data[SRSRAN_MAX_TB]); +SRSRAN_API float srsran_gnb_dl_get_maximum_signal_power_dBfs(uint32_t nof_prb); + SRSRAN_API int srsran_gnb_dl_pdsch_info(const srsran_gnb_dl_t* q, const srsran_sch_cfg_nr_t* cfg, char* str, uint32_t str_len); diff --git a/lib/include/srsran/rlc/rlc_am_lte.h b/lib/include/srsran/rlc/rlc_am_lte.h index 3f5743702..681bb3f4b 100644 --- a/lib/include/srsran/rlc/rlc_am_lte.h +++ b/lib/include/srsran/rlc/rlc_am_lte.h @@ -337,6 +337,7 @@ public: srsue::pdcp_interface_rlc* pdcp_, srsue::rrc_interface_rlc* rrc_, srsran::timer_handler* timers_); + bool configure(const rlc_config_t& cfg_); void reestablish(); void stop(); @@ -564,6 +565,7 @@ private: rlc_am_lte_tx tx; rlc_am_lte_rx rx; + std::mutex metrics_mutex; rlc_bearer_metrics_t metrics = {}; }; diff --git a/lib/src/asn1/rrc_nr_utils.cc b/lib/src/asn1/rrc_nr_utils.cc index 700cdb76b..dcb0b4928 100644 --- a/lib/src/asn1/rrc_nr_utils.cc +++ b/lib/src/asn1/rrc_nr_utils.cc @@ -280,21 +280,21 @@ bool make_phy_rach_cfg(const rach_cfg_common_s& asn1_type, srsran_prach_cfg_t* p }; bool make_phy_tdd_cfg(const tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common, - srsran_tdd_config_nr_t* in_srsran_tdd_config_nr) + srsran_duplex_config_nr_t* in_srsran_duplex_config_nr) { - srsran_tdd_config_nr_t srsran_tdd_config_nr = {}; + srsran_duplex_config_nr_t srsran_duplex_config_nr = {}; switch (tdd_ul_dl_cfg_common.pattern1.dl_ul_tx_periodicity) { case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms1: - srsran_tdd_config_nr.pattern1.period_ms = 1; + srsran_duplex_config_nr.tdd.pattern1.period_ms = 1; break; case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms2: - srsran_tdd_config_nr.pattern1.period_ms = 2; + srsran_duplex_config_nr.tdd.pattern1.period_ms = 2; break; case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms5: - srsran_tdd_config_nr.pattern1.period_ms = 5; + srsran_duplex_config_nr.tdd.pattern1.period_ms = 5; break; case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms10: - srsran_tdd_config_nr.pattern1.period_ms = 10; + srsran_duplex_config_nr.tdd.pattern1.period_ms = 10; break; case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms1p25: @@ -306,12 +306,12 @@ bool make_phy_tdd_cfg(const tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common, tdd_ul_dl_cfg_common.pattern1.dl_ul_tx_periodicity.to_string()); return false; } - srsran_tdd_config_nr.pattern1.nof_dl_slots = tdd_ul_dl_cfg_common.pattern1.nrof_dl_slots; - srsran_tdd_config_nr.pattern1.nof_dl_symbols = tdd_ul_dl_cfg_common.pattern1.nrof_dl_symbols; - srsran_tdd_config_nr.pattern1.nof_ul_slots = tdd_ul_dl_cfg_common.pattern1.nrof_ul_slots; - srsran_tdd_config_nr.pattern1.nof_ul_symbols = tdd_ul_dl_cfg_common.pattern1.nrof_ul_symbols; + srsran_duplex_config_nr.tdd.pattern1.nof_dl_slots = tdd_ul_dl_cfg_common.pattern1.nrof_dl_slots; + srsran_duplex_config_nr.tdd.pattern1.nof_dl_symbols = tdd_ul_dl_cfg_common.pattern1.nrof_dl_symbols; + srsran_duplex_config_nr.tdd.pattern1.nof_ul_slots = tdd_ul_dl_cfg_common.pattern1.nrof_ul_slots; + srsran_duplex_config_nr.tdd.pattern1.nof_ul_symbols = tdd_ul_dl_cfg_common.pattern1.nrof_ul_symbols; // Copy and return struct - *in_srsran_tdd_config_nr = srsran_tdd_config_nr; + *in_srsran_duplex_config_nr = srsran_duplex_config_nr; if (not tdd_ul_dl_cfg_common.pattern2_present) { return true; @@ -319,16 +319,16 @@ bool make_phy_tdd_cfg(const tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common, switch (tdd_ul_dl_cfg_common.pattern2.dl_ul_tx_periodicity) { case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms1: - srsran_tdd_config_nr.pattern2.period_ms = 1; + srsran_duplex_config_nr.tdd.pattern2.period_ms = 1; break; case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms2: - srsran_tdd_config_nr.pattern2.period_ms = 2; + srsran_duplex_config_nr.tdd.pattern2.period_ms = 2; break; case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms5: - srsran_tdd_config_nr.pattern2.period_ms = 5; + srsran_duplex_config_nr.tdd.pattern2.period_ms = 5; break; case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms10: - srsran_tdd_config_nr.pattern2.period_ms = 10; + srsran_duplex_config_nr.tdd.pattern2.period_ms = 10; break; case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms1p25: @@ -341,12 +341,12 @@ bool make_phy_tdd_cfg(const tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common, return false; } - srsran_tdd_config_nr.pattern2.nof_dl_slots = tdd_ul_dl_cfg_common.pattern2.nrof_dl_slots; - srsran_tdd_config_nr.pattern2.nof_dl_symbols = tdd_ul_dl_cfg_common.pattern2.nrof_dl_symbols; - srsran_tdd_config_nr.pattern2.nof_ul_slots = tdd_ul_dl_cfg_common.pattern2.nrof_ul_slots; - srsran_tdd_config_nr.pattern2.nof_ul_symbols = tdd_ul_dl_cfg_common.pattern2.nrof_ul_symbols; + srsran_duplex_config_nr.tdd.pattern2.nof_dl_slots = tdd_ul_dl_cfg_common.pattern2.nrof_dl_slots; + srsran_duplex_config_nr.tdd.pattern2.nof_dl_symbols = tdd_ul_dl_cfg_common.pattern2.nrof_dl_symbols; + srsran_duplex_config_nr.tdd.pattern2.nof_ul_slots = tdd_ul_dl_cfg_common.pattern2.nrof_ul_slots; + srsran_duplex_config_nr.tdd.pattern2.nof_ul_symbols = tdd_ul_dl_cfg_common.pattern2.nrof_ul_symbols; // Copy and return struct - *in_srsran_tdd_config_nr = srsran_tdd_config_nr; + *in_srsran_duplex_config_nr = srsran_duplex_config_nr; return true; } @@ -1079,6 +1079,15 @@ bool make_phy_zp_csi_rs_resource(const asn1::rrc_nr::zp_csi_rs_res_s& zp_csi_rs_ } zp_csi_rs_resource.resource_mapping.freq_band.nof_rb = zp_csi_rs_res.res_map.freq_band.nrof_rbs; zp_csi_rs_resource.resource_mapping.freq_band.start_rb = zp_csi_rs_res.res_map.freq_band.start_rb; + + // Validate CSI-RS resource mapping + if (not srsran_csi_rs_resource_mapping_is_valid(&zp_csi_rs_resource.resource_mapping)) { + asn1::json_writer json_writer; + zp_csi_rs_res.res_map.to_json(json_writer); + asn1::log_error("Resource mapping is invalid or not implemented: %s", json_writer.to_string()); + return false; + } + if (zp_csi_rs_res.periodicity_and_offset_present) { switch (zp_csi_rs_res.periodicity_and_offset.type()) { case csi_res_periodicity_and_offset_c::types_opts::options::slots4: @@ -1237,6 +1246,14 @@ bool make_phy_nzp_csi_rs_resource(const asn1::rrc_nr::nzp_csi_rs_res_s& asn1_nzp csi_rs_nzp_resource.resource_mapping.freq_band.nof_rb = asn1_nzp_csi_rs_res.res_map.freq_band.nrof_rbs; csi_rs_nzp_resource.resource_mapping.freq_band.start_rb = asn1_nzp_csi_rs_res.res_map.freq_band.start_rb; + // Validate CSI-RS resource mapping + if (not srsran_csi_rs_resource_mapping_is_valid(&csi_rs_nzp_resource.resource_mapping)) { + asn1::json_writer json_writer; + asn1_nzp_csi_rs_res.res_map.to_json(json_writer); + asn1::log_error("Resource mapping is invalid or not implemented: %s", json_writer.to_string()); + return false; + } + csi_rs_nzp_resource.power_control_offset = asn1_nzp_csi_rs_res.pwr_ctrl_offset; if (asn1_nzp_csi_rs_res.pwr_ctrl_offset_ss_present) { csi_rs_nzp_resource.power_control_offset_ss = asn1_nzp_csi_rs_res.pwr_ctrl_offset_ss.to_number(); diff --git a/lib/src/common/bearer_manager.cc b/lib/src/common/bearer_manager.cc index 7eae569a1..268845bfc 100644 --- a/lib/src/common/bearer_manager.cc +++ b/lib/src/common/bearer_manager.cc @@ -111,6 +111,7 @@ void ue_bearer_manager::remove_eps_bearer(uint8_t eps_bearer_id) void ue_bearer_manager::reset() { + srsran::rwlock_write_guard rw_lock(rwlock); impl.reset(); logger.info("Bearers: Reset EPS bearer manager"); } diff --git a/lib/src/common/mac_pcap_net.cc b/lib/src/common/mac_pcap_net.cc index 2a3d085a2..88d6b6a30 100644 --- a/lib/src/common/mac_pcap_net.cc +++ b/lib/src/common/mac_pcap_net.cc @@ -58,9 +58,11 @@ uint32_t mac_pcap_net::open(std::string client_ip_addr_, client_udp_port_, bind_addr_str.c_str(), bind_udp_port_); - client_addr.sin_family = AF_INET; - client_addr.sin_addr.s_addr = inet_addr(client_ip_addr_.c_str()); - client_addr.sin_port = htons(client_udp_port_); + + if (not net_utils::set_sockaddr(&client_addr, client_ip_addr_.c_str(), client_udp_port_)) { + logger.error("Invalid client_ip_addr: %s", client_ip_addr_.c_str()); + return SRSRAN_ERROR; + } running = true; ue_id = ue_id_; // start writer thread diff --git a/lib/src/common/phy_cfg_nr_default.cc b/lib/src/common/phy_cfg_nr_default.cc index 8dfe70a68..89ae602cc 100644 --- a/lib/src/common/phy_cfg_nr_default.cc +++ b/lib/src/common/phy_cfg_nr_default.cc @@ -53,13 +53,13 @@ phy_cfg_nr_default_t::reference_cfg_t::reference_cfg_t(const std::string& args) } } srsran_assert(carrier != R_CARRIER_COUNT, "Invalid carrier reference configuration '%s'", param.back().c_str()); - } else if (param.front() == "tdd") { - for (tdd = R_TDD_CUSTOM_6_4; tdd < R_TDD_COUNT; tdd = inc(tdd)) { - if (R_TDD_STRING[tdd] == param.back()) { + } else if (param.front() == "duplex") { + for (duplex = R_DUPLEX_FDD; duplex < R_DUPLEX_COUNT; duplex = inc(duplex)) { + if (R_DUPLEX_STRING[duplex] == param.back()) { break; } } - srsran_assert(tdd != R_TDD_COUNT, "Invalid TDD reference configuration '%s'", param.back().c_str()); + srsran_assert(duplex != R_DUPLEX_COUNT, "Invalid duplex reference configuration '%s'", param.back().c_str()); } else if (param.front() == "pdsch") { for (pdsch = R_PDSCH_DEFAULT; pdsch < R_PDSCH_COUNT; pdsch = inc(pdsch)) { if (R_PDSCH_STRING[pdsch] == param.back()) { @@ -95,8 +95,18 @@ void phy_cfg_nr_default_t::make_carrier_custom_20MHz(srsran_carrier_nr_t& carrie carrier.scs = srsran_subcarrier_spacing_15kHz; } -void phy_cfg_nr_default_t::make_tdd_custom_6_4(srsran_tdd_config_nr_t& tdd) +void phy_cfg_nr_default_t::make_tdd_custom_6_4(srsran_duplex_config_nr_t& conf) { + // Set the duplex mode to TDD + conf.mode = SRSRAN_DUPLEX_MODE_TDD; + + // Select TDD config + srsran_tdd_config_nr_t& tdd = conf.tdd; + + // Initialise pattern + tdd = {}; + + // Enable pattern 1 tdd.pattern1.period_ms = 10; tdd.pattern1.nof_dl_slots = 6; tdd.pattern1.nof_dl_symbols = 0; @@ -107,8 +117,17 @@ void phy_cfg_nr_default_t::make_tdd_custom_6_4(srsran_tdd_config_nr_t& tdd) tdd.pattern2.period_ms = 0; } -void phy_cfg_nr_default_t::make_tdd_fr1_15_1(srsran_tdd_config_nr_t& tdd) -{ +void phy_cfg_nr_default_t::make_tdd_fr1_15_1(srsran_duplex_config_nr_t& conf) +{ // Set the duplex mode to TDD + conf.mode = SRSRAN_DUPLEX_MODE_TDD; + + // Select TDD config + srsran_tdd_config_nr_t& tdd = conf.tdd; + + // Initialise pattern + tdd = {}; + + // Enable pattern 1 tdd.pattern1.period_ms = 5; tdd.pattern1.nof_dl_slots = 3; tdd.pattern1.nof_dl_symbols = 10; @@ -328,32 +347,39 @@ void phy_cfg_nr_default_t::make_pucch_custom_one(srsran_pucch_nr_hl_cfg_t& pucch pucch.sr_resources[1].resource = resource_sr; } -void phy_cfg_nr_default_t::make_harq_auto(srsran_harq_ack_cfg_hl_t& harq, - const srsran_carrier_nr_t& carrier, - const srsran_tdd_config_nr_t& tdd_cfg) +void phy_cfg_nr_default_t::make_harq_auto(srsran_harq_ack_cfg_hl_t& harq, + const srsran_carrier_nr_t& carrier, + const srsran_duplex_config_nr_t& duplex_cfg) { - // Generate as many entries as DL slots - harq.nof_dl_data_to_ul_ack = SRSRAN_MIN(tdd_cfg.pattern1.nof_dl_slots, SRSRAN_MAX_NOF_DL_DATA_TO_UL); - if (tdd_cfg.pattern1.nof_dl_symbols > 0) { - harq.nof_dl_data_to_ul_ack++; - } + if (duplex_cfg.mode == SRSRAN_DUPLEX_MODE_TDD) { + const srsran_tdd_config_nr_t& tdd_cfg = duplex_cfg.tdd; - // Set PDSCH to ACK timing delay to 4 or more - for (uint32_t n = 0; n < harq.nof_dl_data_to_ul_ack; n++) { - // Set the first slots into the first UL slot - if (harq.nof_dl_data_to_ul_ack >= 4 and n < (harq.nof_dl_data_to_ul_ack - 4)) { - harq.dl_data_to_ul_ack[n] = harq.nof_dl_data_to_ul_ack - n; - continue; + // Generate as many entries as DL slots + harq.nof_dl_data_to_ul_ack = SRSRAN_MIN(tdd_cfg.pattern1.nof_dl_slots, SRSRAN_MAX_NOF_DL_DATA_TO_UL); + if (tdd_cfg.pattern1.nof_dl_symbols > 0) { + harq.nof_dl_data_to_ul_ack++; } - // After that try if n+4 is UL slot - if (srsran_tdd_nr_is_ul(&tdd_cfg, carrier.scs, n + 4)) { - harq.dl_data_to_ul_ack[n] = 4; - continue; - } + // Set PDSCH to ACK timing delay to 4 or more + for (uint32_t n = 0; n < harq.nof_dl_data_to_ul_ack; n++) { + // Set the first slots into the first UL slot + if (harq.nof_dl_data_to_ul_ack >= 4 and n < (harq.nof_dl_data_to_ul_ack - 4)) { + harq.dl_data_to_ul_ack[n] = harq.nof_dl_data_to_ul_ack - n; + continue; + } + + // After that try if n+4 is UL slot + if (srsran_duplex_nr_is_ul(&duplex_cfg, carrier.scs, n + 4)) { + harq.dl_data_to_ul_ack[n] = 4; + continue; + } - // Otherwise set delay to the first UL slot of the next TDD period - harq.dl_data_to_ul_ack[n] = (tdd_cfg.pattern1.period_ms + tdd_cfg.pattern1.nof_dl_slots) - n; + // Otherwise set delay to the first UL slot of the next TDD period + harq.dl_data_to_ul_ack[n] = (tdd_cfg.pattern1.period_ms + tdd_cfg.pattern1.nof_dl_slots) - n; + } + } else { + harq.dl_data_to_ul_ack[0] = 4; + harq.nof_dl_data_to_ul_ack = 1; } // Zero the rest @@ -386,14 +412,17 @@ phy_cfg_nr_default_t::phy_cfg_nr_default_t(const reference_cfg_t& reference_cfg) srsran_assertion_failure("Invalid carrier reference"); } - switch (reference_cfg.tdd) { - case reference_cfg_t::R_TDD_CUSTOM_6_4: - make_tdd_custom_6_4(tdd); + switch (reference_cfg.duplex) { + case reference_cfg_t::R_DUPLEX_FDD: + duplex.mode = SRSRAN_DUPLEX_MODE_FDD; + break; + case reference_cfg_t::R_DUPLEX_TDD_CUSTOM_6_4: + make_tdd_custom_6_4(duplex); break; - case reference_cfg_t::R_TDD_FR1_15_1: - make_tdd_fr1_15_1(tdd); + case reference_cfg_t::R_DUPLEX_TDD_FR1_15_1: + make_tdd_fr1_15_1(duplex); break; - case reference_cfg_t::R_TDD_COUNT: + case reference_cfg_t::R_DUPLEX_COUNT: srsran_assertion_failure("Invalid TDD reference"); } @@ -428,7 +457,7 @@ phy_cfg_nr_default_t::phy_cfg_nr_default_t(const reference_cfg_t& reference_cfg) switch (reference_cfg.harq) { case reference_cfg_t::R_HARQ_AUTO: - make_harq_auto(harq_ack, carrier, tdd); + make_harq_auto(harq_ack, carrier, duplex); break; } diff --git a/lib/src/pdcp/pdcp_entity_lte.cc b/lib/src/pdcp/pdcp_entity_lte.cc index 503bc1cc1..9e9362aee 100644 --- a/lib/src/pdcp/pdcp_entity_lte.cc +++ b/lib/src/pdcp/pdcp_entity_lte.cc @@ -63,7 +63,7 @@ bool pdcp_entity_lte::configure(const pdcp_config_t& cnfg_) if (active) { // Already configured if (cnfg_ != cfg) { - logger.error("Bearer reconfiguration not supported. LCID=%d.", rrc->get_rb_name(lcid)); + logger.error("Bearer reconfiguration not supported. LCID=%s.", rrc->get_rb_name(lcid)); return false; } return true; diff --git a/lib/src/pdcp/pdcp_entity_nr.cc b/lib/src/pdcp/pdcp_entity_nr.cc index 477f4c05d..17e26fb98 100644 --- a/lib/src/pdcp/pdcp_entity_nr.cc +++ b/lib/src/pdcp/pdcp_entity_nr.cc @@ -55,7 +55,7 @@ bool pdcp_entity_nr::configure(const pdcp_config_t& cnfg_) if (active) { // Already configured if (cnfg_ != cfg) { - logger.error("Bearer reconfiguration not supported. LCID=%d.", rrc->get_rb_name(lcid)); + logger.error("Bearer reconfiguration not supported. LCID=%s.", rrc->get_rb_name(lcid)); return false; } return true; diff --git a/lib/src/phy/ch_estimation/csi_rs.c b/lib/src/phy/ch_estimation/csi_rs.c index 4f5a751d1..7d5b20eda 100644 --- a/lib/src/phy/ch_estimation/csi_rs.c +++ b/lib/src/phy/ch_estimation/csi_rs.c @@ -98,8 +98,7 @@ static int csi_rs_location_get_k_list(const srsran_csi_rs_resource_mapping_t* re } // Row 2 - if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->nof_ports == 1 && - resource->cdm == srsran_csi_rs_cdm_nocdm) { + if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->cdm == srsran_csi_rs_cdm_nocdm) { if (resource->density == srsran_csi_rs_resource_mapping_density_one || resource->density == srsran_csi_rs_resource_mapping_density_dot5_even || resource->density == srsran_csi_rs_resource_mapping_density_dot5_odd) { @@ -151,8 +150,7 @@ static int csi_rs_location_get_l_list(const srsran_csi_rs_resource_mapping_t* re } // Row 2 - if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->nof_ports == 1 && - resource->cdm == srsran_csi_rs_cdm_nocdm) { + if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->cdm == srsran_csi_rs_cdm_nocdm) { if (resource->density == srsran_csi_rs_resource_mapping_density_one || resource->density == srsran_csi_rs_resource_mapping_density_dot5_even || resource->density == srsran_csi_rs_resource_mapping_density_dot5_odd) { @@ -206,24 +204,14 @@ bool srsran_csi_rs_send(const srsran_csi_rs_period_and_offset_t* periodicity, co static int csi_rs_nof_cdm_groups(const srsran_csi_rs_resource_mapping_t* resource) { + // Row 1 if (resource->row == srsran_csi_rs_resource_mapping_row_1 && resource->nof_ports == 1 && resource->density == srsran_csi_rs_resource_mapping_density_three && resource->cdm == srsran_csi_rs_cdm_nocdm) { return 1; } - // Row 1 - if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->nof_ports == 1 && - resource->cdm == srsran_csi_rs_cdm_nocdm) { - if (resource->density == srsran_csi_rs_resource_mapping_density_one || - resource->density == srsran_csi_rs_resource_mapping_density_dot5_even || - resource->density == srsran_csi_rs_resource_mapping_density_dot5_odd) { - return 1; - } - } - // Row 2 - if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->nof_ports == 1 && - resource->cdm == srsran_csi_rs_cdm_nocdm) { + if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->cdm == srsran_csi_rs_cdm_nocdm) { if (resource->density == srsran_csi_rs_resource_mapping_density_one || resource->density == srsran_csi_rs_resource_mapping_density_dot5_even || resource->density == srsran_csi_rs_resource_mapping_density_dot5_odd) { @@ -241,6 +229,29 @@ static int csi_rs_nof_cdm_groups(const srsran_csi_rs_resource_mapping_t* resourc return SRSRAN_ERROR; } +bool srsran_csi_rs_resource_mapping_is_valid(const srsran_csi_rs_resource_mapping_t* res) +{ + if (res == NULL) { + return false; + } + + if (csi_rs_nof_cdm_groups(res) < 1) { + return false; + } + + uint32_t l_list[CSI_RS_MAX_SYMBOLS_SLOT] = {}; + if (csi_rs_location_get_l_list(res, 0, l_list) < SRSRAN_SUCCESS) { + return false; + } + + uint32_t k_list[CSI_RS_MAX_SUBC_PRB] = {}; + if (csi_rs_location_get_k_list(res, 0, k_list) < SRSRAN_SUCCESS) { + return false; + } + + return true; +} + uint32_t csi_rs_count(srsran_csi_rs_density_t density, uint32_t nprb) { switch (density) { @@ -705,7 +716,7 @@ int srsran_csi_rs_nzp_measure_trs(const srsran_carrier_nr_t* carrier, float cfo_max = 0.0f; for (uint32_t i = 1; i < count; i++) { float time_diff = srsran_symbol_distance_s(measurements[i - 1].l0, measurements[i].l0, carrier->scs); - float phase_diff = cargf(measurements[i - 1].corr * conjf(measurements[i].corr)); + float phase_diff = cargf(measurements[i].corr * conjf(measurements[i - 1].corr)); float cfo_max_temp = 0.0f; // Avoid zero division diff --git a/lib/src/phy/common/phy_common_nr.c b/lib/src/phy/common/phy_common_nr.c index 66b660166..e4c71df47 100644 --- a/lib/src/phy/common/phy_common_nr.c +++ b/lib/src/phy/common/phy_common_nr.c @@ -72,6 +72,31 @@ const char* srsran_rnti_type_str_short(srsran_rnti_type_t rnti_type) return "unknown"; } +const char* srsran_ss_type_str(srsran_search_space_type_t ss_type) +{ + switch (ss_type) { + case srsran_search_space_type_common_0: + return "common0"; + case srsran_search_space_type_common_0A: + return "common0A"; + case srsran_search_space_type_common_1: + return "common1"; + case srsran_search_space_type_common_2: + return "common2"; + case srsran_search_space_type_common_3: + return "common3"; + case srsran_search_space_type_ue: + return "ue"; + case srsran_search_space_type_rar: + return "rar"; + case srsran_search_space_type_cg: + return "cg"; + default:; // Do nothing + break; + } + return "unknown"; +} + const char* srsran_dci_format_nr_string(srsran_dci_format_nr_t format) { switch (format) { @@ -267,13 +292,8 @@ float srsran_symbol_distance_s(uint32_t l0, uint32_t l1, srsran_subcarrier_spaci return srsran_symbol_offset_s(l1, scs) - srsran_symbol_offset_s(l0, scs); } -bool srsran_tdd_nr_is_dl(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx) +static bool tdd_nr_is_dl(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx) { - // Protect NULL pointer access - if (cfg == NULL) { - return false; - } - // Prevent zero division if (cfg->pattern1.period_ms == 0 && cfg->pattern2.period_ms == 0) { return false; @@ -296,13 +316,24 @@ bool srsran_tdd_nr_is_dl(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, (slot_idx_period == pattern->nof_dl_slots && pattern->nof_dl_symbols != 0)); } -bool srsran_tdd_nr_is_ul(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx) +bool srsran_duplex_nr_is_dl(const srsran_duplex_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx) + { // Protect NULL pointer access if (cfg == NULL) { return false; } + // In case of TDD + if (cfg->mode == SRSRAN_DUPLEX_MODE_TDD) { + return tdd_nr_is_dl(&cfg->tdd, numerology, slot_idx); + } + + return true; +} + +static bool tdd_nr_is_ul(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx) +{ // Prevent zero division if (cfg->pattern1.period_ms == 0 && cfg->pattern2.period_ms == 0) { return false; @@ -327,6 +358,21 @@ bool srsran_tdd_nr_is_ul(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, return (slot_idx_period > start_ul || (slot_idx_period == start_ul && pattern->nof_ul_symbols != 0)); } +bool srsran_duplex_nr_is_ul(const srsran_duplex_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx) +{ + // Protect NULL pointer access + if (cfg == NULL) { + return false; + } + + // In case of TDD + if (cfg->mode == SRSRAN_DUPLEX_MODE_TDD) { + return tdd_nr_is_ul(&cfg->tdd, numerology, slot_idx); + } + + return true; +} + int srsran_carrier_to_cell(const srsran_carrier_nr_t* carrier, srsran_cell_t* cell) { // Protect memory access diff --git a/lib/src/phy/dft/dft_fftw.c b/lib/src/phy/dft/dft_fftw.c index 4f8b7d424..8f90092a7 100644 --- a/lib/src/phy/dft/dft_fftw.c +++ b/lib/src/phy/dft/dft_fftw.c @@ -59,7 +59,21 @@ __attribute__((constructor)) static void srsran_dft_load() #ifdef FFTW_WISDOM_FILE char full_path[256]; get_fftw_wisdom_file(full_path, sizeof(full_path)); - fftwf_import_wisdom_from_filename(full_path); + // lockf needs a file descriptor open for writing, so this must be r+ + FILE* fd = fopen(full_path, "r+"); + if (fd == NULL) { + return; + } + if (lockf(fileno(fd), F_LOCK, 0) == -1) { + perror("lockf()"); + return; + } + fftwf_import_wisdom_from_file(fd); + if (lockf(fileno(fd), F_ULOCK, 0) == -1) { + perror("u-lockf()"); + return; + } + fclose(fd); #else printf("Warning: FFTW Wisdom file not defined\n"); #endif @@ -71,7 +85,20 @@ __attribute__((destructor)) static void srsran_dft_exit() #ifdef FFTW_WISDOM_FILE char full_path[256]; get_fftw_wisdom_file(full_path, sizeof(full_path)); - fftwf_export_wisdom_to_filename(full_path); + FILE* fd = fopen(full_path, "w"); + if (fd == NULL) { + return; + } + if (lockf(fileno(fd), F_LOCK, 0) == -1) { + perror("lockf()"); + return; + } + fftwf_export_wisdom_to_file(fd); + if (lockf(fileno(fd), F_ULOCK, 0) == -1) { + perror("u-lockf()"); + return; + } + fclose(fd); #endif fftwf_cleanup(); } diff --git a/lib/src/phy/gnb/gnb_dl.c b/lib/src/phy/gnb/gnb_dl.c index 768863c7b..1741351a4 100644 --- a/lib/src/phy/gnb/gnb_dl.c +++ b/lib/src/phy/gnb/gnb_dl.c @@ -22,6 +22,11 @@ #include "srsran/phy/gnb/gnb_dl.h" #include +static float gnb_dl_get_norm_factor(uint32_t nof_prb) +{ + return 0.05f / sqrtf(nof_prb); +} + static int gnb_dl_alloc_prb(srsran_gnb_dl_t* q, uint32_t new_nof_prb) { if (q->max_prb < new_nof_prb) { @@ -171,11 +176,21 @@ void srsran_gnb_dl_gen_signal(srsran_gnb_dl_t* q) return; } + float norm_factor = gnb_dl_get_norm_factor(q->pdcch.carrier.nof_prb); + for (uint32_t i = 0; i < q->nof_tx_antennas; i++) { srsran_ofdm_tx_sf(&q->fft[i]); + + srsran_vec_sc_prod_cfc(q->fft[i].cfg.out_buffer, norm_factor, q->fft[i].cfg.out_buffer, (uint32_t)q->fft[i].sf_sz); } } +float srsran_gnb_dl_get_maximum_signal_power_dBfs(uint32_t nof_prb) +{ + return srsran_convert_amplitude_to_dB(gnb_dl_get_norm_factor(nof_prb)) + + srsran_convert_power_to_dB((float)nof_prb * SRSRAN_NRE) + 3.0f; +} + int srsran_gnb_dl_base_zero(srsran_gnb_dl_t* q) { if (q == NULL) { diff --git a/lib/src/phy/io/netsink.c b/lib/src/phy/io/netsink.c index a32731aa9..424f4aedb 100644 --- a/lib/src/phy/io/netsink.c +++ b/lib/src/phy/io/netsink.c @@ -39,7 +39,7 @@ int srsran_netsink_init(srsran_netsink_t* q, const char* address, uint16_t port, q->sockfd = socket(AF_INET, type == SRSRAN_NETSINK_TCP ? SOCK_STREAM : SOCK_DGRAM, 0); if (q->sockfd < 0) { perror("socket"); - return -1; + return SRSRAN_ERROR; } int enable = 1; @@ -53,12 +53,15 @@ int srsran_netsink_init(srsran_netsink_t* q, const char* address, uint16_t port, #endif q->servaddr.sin_family = AF_INET; - q->servaddr.sin_addr.s_addr = inet_addr(address); + if (inet_pton(q->servaddr.sin_family, address, &q->servaddr.sin_addr) != 1) { + perror("inet_pton"); + return SRSRAN_ERROR; + } q->servaddr.sin_port = htons(port); q->connected = false; q->type = type; - return 0; + return SRSRAN_SUCCESS; } void srsran_netsink_free(srsran_netsink_t* q) @@ -73,9 +76,9 @@ int srsran_netsink_set_nonblocking(srsran_netsink_t* q) { if (fcntl(q->sockfd, F_SETFL, O_NONBLOCK)) { perror("fcntl"); - return -1; + return SRSRAN_ERROR; } - return 0; + return SRSRAN_SUCCESS; } int srsran_netsink_write(srsran_netsink_t* q, void* buffer, int nof_bytes) @@ -83,11 +86,11 @@ int srsran_netsink_write(srsran_netsink_t* q, void* buffer, int nof_bytes) if (!q->connected) { if (connect(q->sockfd, &q->servaddr, sizeof(q->servaddr)) < 0) { if (errno == ECONNREFUSED || errno == EINPROGRESS) { - return 0; + return SRSRAN_SUCCESS; } else { perror("connect"); exit(-1); - return -1; + return SRSRAN_ERROR; } } else { q->connected = true; @@ -102,10 +105,10 @@ int srsran_netsink_write(srsran_netsink_t* q, void* buffer, int nof_bytes) q->sockfd = socket(AF_INET, q->type == SRSRAN_NETSINK_TCP ? SOCK_STREAM : SOCK_DGRAM, 0); if (q->sockfd < 0) { perror("socket"); - return -1; + return SRSRAN_ERROR; } q->connected = false; - return 0; + return SRSRAN_SUCCESS; } } } diff --git a/lib/src/phy/io/netsource.c b/lib/src/phy/io/netsource.c index 7dbd5fd97..b8914062a 100644 --- a/lib/src/phy/io/netsource.c +++ b/lib/src/phy/io/netsource.c @@ -39,7 +39,7 @@ int srsran_netsource_init(srsran_netsource_t* q, const char* address, uint16_t p if (q->sockfd < 0) { perror("socket"); - return -1; + return SRSRAN_ERROR; } // Make sockets reusable @@ -55,16 +55,19 @@ int srsran_netsource_init(srsran_netsource_t* q, const char* address, uint16_t p q->type = type; q->servaddr.sin_family = AF_INET; - q->servaddr.sin_addr.s_addr = inet_addr(address); + if (inet_pton(q->servaddr.sin_family, address, &q->servaddr.sin_addr) != 1) { + perror("inet_pton"); + return SRSRAN_ERROR; + } q->servaddr.sin_port = htons(port); if (bind(q->sockfd, (struct sockaddr*)&q->servaddr, sizeof(struct sockaddr_in))) { perror("bind"); - return -1; + return SRSRAN_ERROR; } q->connfd = 0; - return 0; + return SRSRAN_SUCCESS; } void srsran_netsource_free(srsran_netsource_t* q) @@ -82,9 +85,9 @@ int srsran_netsource_read(srsran_netsource_t* q, void* buffer, int nbytes) if (n == -1) { if (errno == EAGAIN) { - return 0; + return SRSRAN_SUCCESS; } else { - return -1; + return SRSRAN_ERROR; } } else { return n; @@ -97,7 +100,7 @@ int srsran_netsource_read(srsran_netsource_t* q, void* buffer, int nbytes) q->connfd = accept(q->sockfd, (struct sockaddr*)&q->cliaddr, &clilen); if (q->connfd < 0) { perror("accept"); - return -1; + return SRSRAN_ERROR; } } int n = read(q->connfd, buffer, nbytes); @@ -105,7 +108,7 @@ int srsran_netsource_read(srsran_netsource_t* q, void* buffer, int nbytes) printf("Connection closed\n"); close(q->connfd); q->connfd = 0; - return 0; + return SRSRAN_SUCCESS; } if (n == -1) { perror("read"); @@ -136,7 +139,7 @@ int srsran_netsource_set_nonblocking(srsran_netsource_t* q) perror("fcntl"); return -1; } - return 0; + return SRSRAN_SUCCESS; } int srsran_netsource_set_timeout(srsran_netsource_t* q, uint32_t microseconds) @@ -146,7 +149,7 @@ int srsran_netsource_set_timeout(srsran_netsource_t* q, uint32_t microseconds) t.tv_usec = microseconds; if (setsockopt(q->sockfd, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(struct timeval))) { perror("setsockopt"); - return -1; + return SRSRAN_ERROR; } - return 0; + return SRSRAN_SUCCESS; } diff --git a/lib/src/phy/phch/ra_dl_nr.c b/lib/src/phy/phch/ra_dl_nr.c index 6e86cb55e..2f8bcd1d8 100644 --- a/lib/src/phy/phch/ra_dl_nr.c +++ b/lib/src/phy/phch/ra_dl_nr.c @@ -186,7 +186,7 @@ int srsran_ra_dl_nr_time(const srsran_sch_hl_cfg_nr_t* cfg, srsran_ra_dl_nr_time_default_A(m, cfg->typeA_pos, grant); } } else { - ERROR("Unhandled case %s, ss_type=%d", srsran_rnti_type_str(rnti_type), ss_type); + ERROR("Unhandled case %s, ss_type=%s", srsran_rnti_type_str(rnti_type), srsran_ss_type_str(ss_type)); } // Validate S and L parameters @@ -349,4 +349,3 @@ uint32_t srsran_ra_nr_type1_riv(uint32_t N_prb, uint32_t start_rb, uint32_t leng { return srsran_sliv_from_s_and_l(N_prb, start_rb, length_rb); } - diff --git a/lib/src/phy/sync/ssb.c b/lib/src/phy/sync/ssb.c index 242dc1dba..1f1122cc3 100644 --- a/lib/src/phy/sync/ssb.c +++ b/lib/src/phy/sync/ssb.c @@ -706,7 +706,7 @@ ssb_measure(srsran_ssb_t* q, const cf_t ssb_grid[SRSRAN_SSB_NOF_RE], uint32_t N_ // Compute CFO in Hz float distance_s = srsran_symbol_distance_s(SRSRAN_PSS_NR_SYMBOL_IDX, SRSRAN_SSS_NR_SYMBOL_IDX, q->cfg.scs); float cfo_hz_max = 1.0f / distance_s; - float cfo_hz = cargf(corr_pss * conjf(corr_sss)) / (2.0f * M_PI) * cfo_hz_max; + float cfo_hz = cargf(corr_sss * conjf(corr_pss)) / (2.0f * M_PI) * cfo_hz_max; // Compute average RSRP float rsrp_pss = SRSRAN_CSQABS(corr_pss); diff --git a/lib/src/phy/sync/test/ssb_measure_test.c b/lib/src/phy/sync/test/ssb_measure_test.c index e8a681341..98343b6c9 100644 --- a/lib/src/phy/sync/test/ssb_measure_test.c +++ b/lib/src/phy/sync/test/ssb_measure_test.c @@ -80,7 +80,7 @@ static void run_channel() } // CFO - srsran_vec_apply_cfo(buffer, -cfo_hz / srate_hz, buffer, sf_len); + srsran_vec_apply_cfo(buffer, cfo_hz / srate_hz, buffer, sf_len); // AWGN srsran_channel_awgn_run_c(&awgn, buffer, buffer, sf_len); diff --git a/lib/src/phy/ue/test/ue_dl_nr_file_test.c b/lib/src/phy/ue/test/ue_dl_nr_file_test.c index 7cf0e226f..3b838682c 100644 --- a/lib/src/phy/ue/test/ue_dl_nr_file_test.c +++ b/lib/src/phy/ue/test/ue_dl_nr_file_test.c @@ -123,11 +123,12 @@ static int work_ue_dl(srsran_ue_dl_nr_t* ue_dl, srsran_slot_cfg_t* slot) // Print PDCCH blind search candidates for (uint32_t i = 0; i < ue_dl->pdcch_info_count; i++) { const srsran_ue_dl_nr_pdcch_info_t* info = &ue_dl->pdcch_info[i]; - INFO("PDCCH: rnti=0x%x, crst_id=%d, ss_type=%d, ncce=%d, al=%d, EPRE=%+.2f, RSRP=%+.2f, corr=%.3f; " + INFO("PDCCH: %s-rnti=0x%x, crst_id=%d, ss_type=%s, ncce=%d, al=%d, EPRE=%+.2f, RSRP=%+.2f, corr=%.3f; " "nof_bits=%d; crc=%s;", + srsran_rnti_type_str_short(info->dci_ctx.rnti_type), info->dci_ctx.rnti, info->dci_ctx.coreset_id, - info->dci_ctx.ss_type, + srsran_ss_type_str(info->dci_ctx.ss_type), info->dci_ctx.location.ncce, info->dci_ctx.location.L, info->measure.epre_dBfs, diff --git a/lib/src/phy/ue/ue_sync.c b/lib/src/phy/ue/ue_sync.c index ccbac4a45..e37fdb8d9 100644 --- a/lib/src/phy/ue/ue_sync.c +++ b/lib/src/phy/ue/ue_sync.c @@ -937,31 +937,44 @@ int srsran_ue_sync_run_find_gnss_mode(srsran_ue_sync_t* q, INFO("Calibration samples received start at %ld + %f", q->last_timestamp.full_secs, q->last_timestamp.frac_secs); // round to nearest second - srsran_timestamp_t ts_next_rx; + srsran_timestamp_t ts_next_rx, ts_next_rx_tmp, ts_tmp; srsran_timestamp_copy(&ts_next_rx, &q->last_timestamp); ts_next_rx.full_secs++; ts_next_rx.frac_secs = 0.0; - INFO("Next desired recv at %ld + %f", ts_next_rx.full_secs, ts_next_rx.frac_secs); + srsran_timestamp_copy(&ts_next_rx_tmp, &ts_next_rx); + INFO("Next desired recv at %ld + %f\n", ts_next_rx_tmp.full_secs, ts_next_rx_tmp.frac_secs); // get difference in time between second rx and now - srsran_timestamp_sub(&ts_next_rx, q->last_timestamp.full_secs, q->last_timestamp.frac_secs); - srsran_timestamp_sub(&ts_next_rx, 0, 0.001); ///< account for samples that have already been rx'ed + srsran_timestamp_sub(&ts_next_rx_tmp, q->last_timestamp.full_secs, q->last_timestamp.frac_secs); + srsran_timestamp_sub(&ts_next_rx_tmp, 0, 0.001); ///< account for samples that have already been rx'ed - uint64_t align_len = srsran_timestamp_uint64(&ts_next_rx, q->sf_len * 1000); + uint64_t align_len = srsran_timestamp_uint64(&ts_next_rx_tmp, q->sf_len * 1000); - DEBUG("Difference between first recv is %ld + %f, realigning %" PRIu64 " samples", - ts_next_rx.full_secs, - ts_next_rx.frac_secs, + DEBUG("Difference between first recv is %ld + %f, realigning %" PRIu64 " samples\n", + ts_next_rx_tmp.full_secs, + ts_next_rx_tmp.frac_secs, align_len); // receive align_len samples into dummy_buffer, make sure to not exceed buffer len uint32_t sample_count = 0; - while (sample_count < align_len) { - uint32_t actual_rx_len = SRSRAN_MIN(align_len, DUMMY_BUFFER_NUM_SAMPLES); - actual_rx_len = SRSRAN_MIN(align_len - sample_count, actual_rx_len); + while (align_len > q->sf_len) { + uint32_t actual_rx_len = SRSRAN_MIN(align_len, q->sf_len); q->recv_callback(q->stream, dummy_offset_buffer, actual_rx_len, &q->last_timestamp); - sample_count += actual_rx_len; + + srsran_timestamp_copy(&ts_tmp, &ts_next_rx); + srsran_timestamp_sub(&ts_tmp, q->last_timestamp.full_secs, q->last_timestamp.frac_secs); + srsran_timestamp_sub(&ts_tmp, 0, 0.001); ///< account for samples that have already been rx'ed + align_len = srsran_timestamp_uint64(&ts_tmp, q->sf_len * 1000); + + if (align_len > q->sf_len * 1000) { + ts_next_rx.full_secs++; + ts_next_rx.frac_secs = 0.0; + srsran_timestamp_copy(&ts_tmp, &ts_next_rx); + srsran_timestamp_sub(&ts_tmp, q->last_timestamp.full_secs, q->last_timestamp.frac_secs); + srsran_timestamp_sub(&ts_tmp, 0, 0.001); ///< account for samples that have already been rx'ed + align_len = srsran_timestamp_uint64(&ts_tmp, q->sf_len * 1000); + } } DEBUG("Received %d samples during alignment", sample_count); @@ -1026,39 +1039,22 @@ int srsran_ue_sync_set_tti_from_timestamp(srsran_ue_sync_t* q, srsran_timestamp_ time_t t_cur = rx_timestamp->full_secs; DEBUG("t_cur=%ld", t_cur); - // time_t of reference UTC time on 1. Jan 1900 at 0:00 - // If we put this date in https://www.epochconverter.com it returns a negative number - time_t t_ref = {0}; -#if 0 - struct tm t = {0}; - t.tm_year = 1900; // year-1900 - t.tm_mday = 1; // first of January - // t.tm_isdst = 0; // Is DST on? 1 = yes, 0 = no, -1 = unknown - t_ref = mktime(&t); -#endif - - DEBUG("t_ref=%ld", t_ref); + // 3GPP Reference UTC time is 1. Jan 1900 at 0:00 + // If we put this date in https://www.epochconverter.com it returns a negative number (-2208988800) + // as epoch time starts at 1. Jan 1970 at 0:00 + uint64_t epoch_offset_3gpp = 2208988800; static const uint32_t MSECS_PER_SEC = 1000; - DEBUG("diff=%f", difftime(t_cur, t_ref)); - - double time_diff_secs = difftime(t_cur, t_ref); - - if (time_diff_secs < 0) { - fprintf(stderr, "Time diff between Rx timestamp and reference UTC is negative. Is the timestamp correct?\n"); - return SRSRAN_ERROR; - } - - DEBUG("time diff in s %f", time_diff_secs); + uint64_t time_3gpp_secs = t_cur + epoch_offset_3gpp; // convert to ms and add fractional part - double time_diff_msecs = time_diff_secs * MSECS_PER_SEC + rx_timestamp->frac_secs; - DEBUG("time diff in ms %f", time_diff_msecs); + uint64_t time_3gpp_msecs = (time_3gpp_secs + rx_timestamp->frac_secs) * MSECS_PER_SEC; + DEBUG("rx time with 3gpp base in ms %lu\n", time_3gpp_msecs); // calculate SFN and SF index according to TS 36.331 Sec. 5.10.14 - q->frame_number = ((uint32_t)floor(0.1 * (time_diff_msecs - q->sfn_offset))) % 1024; - q->sf_idx = ((uint32_t)floor(time_diff_msecs - q->sfn_offset)) % 10; + q->frame_number = (uint32_t)(((uint64_t)floor(0.1 * (time_3gpp_msecs - q->sfn_offset))) % 1024); + q->sf_idx = (uint32_t)(((uint64_t)floor(time_3gpp_msecs - q->sfn_offset)) % 10); return SRSRAN_SUCCESS; } diff --git a/lib/src/phy/ue/ue_ul_nr.c b/lib/src/phy/ue/ue_ul_nr.c index 23ac4e30c..3b14cc16e 100644 --- a/lib/src/phy/ue/ue_ul_nr.c +++ b/lib/src/phy/ue/ue_ul_nr.c @@ -110,7 +110,7 @@ void srsran_ue_ul_nr_set_freq_offset(srsran_ue_ul_nr_t* q, float freq_offset_hz) return; } - q->freq_offset_hz = freq_offset_hz; + q->freq_offset_hz = -freq_offset_hz; } int srsran_ue_ul_nr_encode_pusch(srsran_ue_ul_nr_t* q, diff --git a/lib/src/rlc/rlc_am_lte.cc b/lib/src/rlc/rlc_am_lte.cc index a5084af11..5354fba06 100644 --- a/lib/src/rlc/rlc_am_lte.cc +++ b/lib/src/rlc/rlc_am_lte.cc @@ -212,13 +212,19 @@ uint32_t rlc_am_lte::get_bearer() rlc_bearer_metrics_t rlc_am_lte::get_metrics() { // update values that aren't calculated on the fly - metrics.rx_latency_ms = rx.get_sdu_rx_latency_ms(); - metrics.rx_buffered_bytes = rx.get_rx_buffered_bytes(); + uint32_t latency = rx.get_sdu_rx_latency_ms(); + uint32_t buffered_bytes = rx.get_rx_buffered_bytes(); + + std::lock_guard lock(metrics_mutex); + metrics.rx_latency_ms = latency; + metrics.rx_buffered_bytes = buffered_bytes; + return metrics; } void rlc_am_lte::reset_metrics() { + std::lock_guard lock(metrics_mutex); metrics = {}; } @@ -229,6 +235,7 @@ void rlc_am_lte::reset_metrics() void rlc_am_lte::write_sdu(unique_byte_buffer_t sdu) { if (tx.write_sdu(std::move(sdu)) == SRSRAN_SUCCESS) { + std::lock_guard lock(metrics_mutex); metrics.num_tx_sdus++; } } @@ -236,6 +243,8 @@ void rlc_am_lte::write_sdu(unique_byte_buffer_t sdu) void rlc_am_lte::discard_sdu(uint32_t discard_sn) { tx.discard_sdu(discard_sn); + + std::lock_guard lock(metrics_mutex); metrics.num_lost_sdus++; } @@ -261,14 +270,19 @@ uint32_t rlc_am_lte::get_buffer_state() uint32_t rlc_am_lte::read_pdu(uint8_t* payload, uint32_t nof_bytes) { uint32_t read_bytes = tx.read_pdu(payload, nof_bytes); + + std::lock_guard lock(metrics_mutex); metrics.num_tx_pdus++; metrics.num_tx_pdu_bytes += read_bytes; + return read_bytes; } void rlc_am_lte::write_pdu(uint8_t* payload, uint32_t nof_bytes) { rx.write_pdu(payload, nof_bytes); + + std::lock_guard lock(metrics_mutex); metrics.num_rx_pdus++; metrics.num_rx_pdu_bytes += nof_bytes; } @@ -416,6 +430,8 @@ void rlc_am_lte::rlc_am_lte_tx::check_sn_reached_max_retx(uint32_t sn) pdcp_sns.push_back(segment.pdcp_sn()); } parent->pdcp->notify_failure(parent->lcid, pdcp_sns); + + std::lock_guard lock(parent->metrics_mutex); parent->metrics.num_lost_pdus++; } } @@ -1767,7 +1783,10 @@ void rlc_am_lte::rlc_am_lte_rx::reassemble_rx_sdus() std::chrono::high_resolution_clock::now() - rx_sdu->get_timestamp()) .count()); parent->pdcp->write_pdu(parent->lcid, std::move(rx_sdu)); - parent->metrics.num_rx_sdus++; + { + std::lock_guard lock(parent->metrics_mutex); + parent->metrics.num_rx_sdus++; + } rx_sdu = srsran::make_byte_buffer(); if (rx_sdu == nullptr) { @@ -1817,7 +1836,10 @@ void rlc_am_lte::rlc_am_lte_rx::reassemble_rx_sdus() std::chrono::high_resolution_clock::now() - rx_sdu->get_timestamp()) .count()); parent->pdcp->write_pdu(parent->lcid, std::move(rx_sdu)); - parent->metrics.num_rx_sdus++; + { + std::lock_guard lock(parent->metrics_mutex); + parent->metrics.num_rx_sdus++; + } rx_sdu = srsran::make_byte_buffer(); if (rx_sdu == NULL) { @@ -1994,9 +2016,9 @@ int rlc_am_lte::rlc_am_lte_rx::get_status_pdu_length() if (not lock.owns_lock()) { return 0; } - rlc_status_pdu_t status = {}; - status.ack_sn = vr_ms; - uint32_t i = vr_r; + rlc_status_pdu_t status = {}; + status.ack_sn = vr_ms; + uint32_t i = vr_r; while (RX_MOD_BASE(i) < RX_MOD_BASE(vr_ms) && status.N_nack < RLC_AM_WINDOW_SIZE) { if (not rx_window.has_sn(i)) { status.N_nack++; diff --git a/lib/test/asn1/rrc_nr_utils_test.cc b/lib/test/asn1/rrc_nr_utils_test.cc index ea41eb346..2b0ef0bb9 100644 --- a/lib/test/asn1/rrc_nr_utils_test.cc +++ b/lib/test/asn1/rrc_nr_utils_test.cc @@ -97,15 +97,15 @@ int make_phy_tdd_cfg_test() tdd_ul_dl_cfg_common.pattern1.nrof_ul_slots = 2; tdd_ul_dl_cfg_common.pattern1.nrof_ul_symbols = 4; - srsran_tdd_config_nr_t srsran_tdd_config_nr; - TESTASSERT(make_phy_tdd_cfg(tdd_ul_dl_cfg_common, &srsran_tdd_config_nr) == true); - - TESTASSERT(srsran_tdd_config_nr.pattern1.period_ms == 10); - TESTASSERT(srsran_tdd_config_nr.pattern1.nof_dl_slots == 7); - TESTASSERT(srsran_tdd_config_nr.pattern1.nof_dl_symbols == 6); - TESTASSERT(srsran_tdd_config_nr.pattern1.nof_ul_slots == 2); - TESTASSERT(srsran_tdd_config_nr.pattern1.nof_ul_symbols == 4); - TESTASSERT(srsran_tdd_config_nr.pattern2.period_ms == 0); + srsran_duplex_config_nr_t srsran_duplex_config_nr; + TESTASSERT(make_phy_tdd_cfg(tdd_ul_dl_cfg_common, &srsran_duplex_config_nr) == true); + + TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.period_ms == 10); + TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.nof_dl_slots == 7); + TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.nof_dl_symbols == 6); + TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.nof_ul_slots == 2); + TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.nof_ul_symbols == 4); + TESTASSERT(srsran_duplex_config_nr.tdd.pattern2.period_ms == 0); return SRSRAN_SUCCESS; } diff --git a/lib/test/asn1/srsran_asn1_rrc_nr_test.cc b/lib/test/asn1/srsran_asn1_rrc_nr_test.cc index 67438cf0b..c1c59a8a8 100644 --- a/lib/test/asn1/srsran_asn1_rrc_nr_test.cc +++ b/lib/test/asn1/srsran_asn1_rrc_nr_test.cc @@ -294,7 +294,7 @@ int test_radio_bearer_config() return SRSRAN_SUCCESS; } -int test_cell_group_config() +int test_cell_group_config_tdd() { uint8_t cell_group_config_raw[] = "\x5c\x40\xb1\xc0\x33\xc8\x53\xe0\x12\x0f\x05\x38\x0f\x80\x41\x15" "\x07\xad\x40\x00\xba\x14\xe6\x37\xd1\xa4\xd3\xa0\x01\x34\x9a\x5f" @@ -914,6 +914,615 @@ int test_cell_group_config() return SRSRAN_SUCCESS; } +int test_cell_group_config_fdd() +{ + uint8_t cell_group_config_raw[] = "\x5c\x40\xb1\xc0\x7d\x48\x3a\x04\xc0\x3e\x01\x04\x54\x1e\xb5\x80" + "\x02\xe8\x53\xb8\x9f\x46\x85\x60\xa4\x00\x40\xab\x41\x00\x00\x00" + "\xcd\x8d\xb2\x44\xa2\x01\xff\x00\x00\x00\x00\x01\x1b\x82\x21\x00" + "\x01\x24\x04\x00\xd0\x14\x6c\x00\x10\x28\x9d\xc0\x00\x00\x33\x71" + "\xb6\x48\x90\x04\x00\x08\x2e\x25\x18\xf0\x02\x4a\x31\x06\xe1\x8d" + "\xb8\x44\x70\x01\x08\x4c\x23\x06\xdd\x40\x01\x01\xc0\x24\xb8\x19" + "\x50\x00\x2f\xf0\x00\x00\x00\x00\x10\x6e\x11\x04\x00\x01\x10\x24" + "\xa0\x04\x19\x04\x00\x00\x40\xd3\x02\x02\x8a\x14\x00\x1c\x90\x30" + "\x00\x02\x66\xaa\xc9\x08\x38\x00\x20\x81\x84\x0a\x18\x39\x38\x81" + "\x22\x85\x8c\x1a\x38\x79\x10\x00\x00\x85\x00\x00\x80\x0a\x50\x00" + "\x10\x00\xc5\x00\x01\x80\x08\x50\x10\x20\x00\xa5\x01\x02\x80\x0c" + "\x50\x10\x30\x00\x85\x02\x03\x80\x0a\x50\x20\x40\xcd\x04\x01\x23" + "\x34\x12\x05\x0c\xd0\x50\x16\x33\x41\x60\x60\xcd\x06\x01\xa3\x34" + "\x1a\x07\x0c\xd0\x70\x1e\x01\x41\x00\x80\x00\xc5\x02\x08\x80\x50" + "\x4a\x04\x84\x30\x28\x42\x01\x22\x80\x14\x92\x1e\x2e\xe0\x0c\x10" + "\xe0\x00\x00\x01\xff\xd2\x94\x98\xc6\x37\x28\x16\x00\x00\x21\x97" + "\x00\x00\x00\x00\x00\x00\x06\x2f\x00\xfa\x08\x48\xad\x54\x50\x04" + "\x70\x01\x80\x00\x82\x00\x0e\x21\x7d\x24\x08\x07\x01\x01\x08\x40" + "\x00\xe2\x17\xd1\xcb\x00\xe0\x40\x22\x08\x00\x1c\x42\xfa\x39\x60" + "\x1c\x0c\x04\x21\x00\x03\x88\x5f\x47\x30\x03\x82\x00\x88\x20\x00" + "\x71\x0b\xe8\xe6\x00\x04\x00\x00\x00\x41\x0c\x04\x08\x0c\x10\x0e" + "\x0d\x00\x00\xe4\x81\x00\x00\x00\x20\x04\x00\x08\x06\x00\x08\x09" + "\x00\x22\x00\xa4\x00\x00\x23\x85\x01\x13\x1c"; + + asn1::SRSASN_CODE err; + + cbit_ref bref(&cell_group_config_raw[0], sizeof(cell_group_config_raw)); + cell_group_cfg_s cell_group_cfg; + + TESTASSERT(cell_group_cfg.unpack(bref) == SRSASN_SUCCESS); + + TESTASSERT(test_pack_unpack_consistency(cell_group_cfg) == SRSASN_SUCCESS); + + TESTASSERT(cell_group_cfg.sp_cell_cfg_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.serv_cell_idx_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded.first_active_dl_bwp_id_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded.pdcch_serving_cell_cfg_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded.pdsch_serving_cell_cfg_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.recfg_with_sync_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.pci_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.pci == 500); + TESTASSERT(cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp_present == true); + TESTASSERT( + cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common_present == + true); + + TESTASSERT( + cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common.type() == + asn1::rrc_nr::setup_release_c::types_opts::setup); + + asn1::rrc_nr::rach_cfg_common_s& rach_cfg_common = + cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common.setup(); + + TESTASSERT(rach_cfg_common.rach_cfg_generic.prach_cfg_idx == 16); + TESTASSERT(rach_cfg_common.rach_cfg_generic.msg1_fdm == asn1::rrc_nr::rach_cfg_generic_s::msg1_fdm_opts::one); + TESTASSERT(rach_cfg_common.rach_cfg_generic.zero_correlation_zone_cfg == 0); + TESTASSERT(rach_cfg_common.rach_cfg_generic.preamb_rx_target_pwr == -110); + TESTASSERT(rach_cfg_common.rach_cfg_generic.preamb_trans_max == + asn1::rrc_nr::rach_cfg_generic_s::preamb_trans_max_opts::n7); + TESTASSERT(rach_cfg_common.rach_cfg_generic.pwr_ramp_step == + asn1::rrc_nr::rach_cfg_generic_s::pwr_ramp_step_opts::db4); + TESTASSERT(rach_cfg_common.rach_cfg_generic.ra_resp_win == asn1::rrc_nr::rach_cfg_generic_s::ra_resp_win_opts::sl10); + TESTASSERT(rach_cfg_common.ssb_per_rach_occasion_and_cb_preambs_per_ssb_present == true); + +#if JSON_OUTPUT + asn1::json_writer json_writer; + cell_group_cfg.to_json(json_writer); + srslog::fetch_basic_logger("RRC").info("RRC Secondary Cell Group: Content: %s\n", json_writer.to_string().c_str()); +#endif + + // pack it again + cell_group_cfg_s cell_group_cfg_pack; + + // RLC for DRB1 + cell_group_cfg_pack.rlc_bearer_to_add_mod_list_present = true; + cell_group_cfg_pack.rlc_bearer_to_add_mod_list.resize(1); + auto& rlc = cell_group_cfg_pack.rlc_bearer_to_add_mod_list[0]; + rlc.lc_ch_id = 4; + rlc.served_radio_bearer_present = true; + rlc.served_radio_bearer.set_drb_id(); + rlc.served_radio_bearer.drb_id() = 1; + rlc.rlc_cfg_present = true; + rlc.rlc_cfg.set_um_bi_dir(); + rlc.rlc_cfg.um_bi_dir().ul_um_rlc.sn_field_len_present = true; + rlc.rlc_cfg.um_bi_dir().ul_um_rlc.sn_field_len = sn_field_len_um_opts::size12; + rlc.rlc_cfg.um_bi_dir().dl_um_rlc.sn_field_len_present = true; + rlc.rlc_cfg.um_bi_dir().dl_um_rlc.sn_field_len = sn_field_len_um_opts::size12; + rlc.rlc_cfg.um_bi_dir().dl_um_rlc.t_reassembly = t_reassembly_opts::ms50; + + // MAC logical channel config + rlc.mac_lc_ch_cfg_present = true; + rlc.mac_lc_ch_cfg.ul_specific_params_present = true; + rlc.mac_lc_ch_cfg.ul_specific_params.prio = 11; + rlc.mac_lc_ch_cfg.ul_specific_params.prioritised_bit_rate = + asn1::rrc_nr::lc_ch_cfg_s::ul_specific_params_s_::prioritised_bit_rate_opts::kbps0; + rlc.mac_lc_ch_cfg.ul_specific_params.bucket_size_dur = + asn1::rrc_nr::lc_ch_cfg_s::ul_specific_params_s_::bucket_size_dur_opts::ms100; + rlc.mac_lc_ch_cfg.ul_specific_params.lc_ch_group_present = true; + rlc.mac_lc_ch_cfg.ul_specific_params.lc_ch_group = 6; + rlc.mac_lc_ch_cfg.ul_specific_params.sched_request_id_present = true; + rlc.mac_lc_ch_cfg.ul_specific_params.sched_request_id = 0; + + // mac-CellGroup-Config + cell_group_cfg_pack.mac_cell_group_cfg_present = true; + auto& mac_cell_group = cell_group_cfg_pack.mac_cell_group_cfg; + mac_cell_group.sched_request_cfg_present = true; + mac_cell_group.sched_request_cfg.sched_request_to_add_mod_list_present = true; + mac_cell_group.sched_request_cfg.sched_request_to_add_mod_list.resize(1); + mac_cell_group.sched_request_cfg.sched_request_to_add_mod_list[0].sched_request_id = 0; + mac_cell_group.sched_request_cfg.sched_request_to_add_mod_list[0].sr_trans_max = + asn1::rrc_nr::sched_request_to_add_mod_s::sr_trans_max_opts::n64; + mac_cell_group.bsr_cfg_present = true; + mac_cell_group.bsr_cfg.periodic_bsr_timer = asn1::rrc_nr::bsr_cfg_s::periodic_bsr_timer_opts::sf20; + mac_cell_group.bsr_cfg.retx_bsr_timer = asn1::rrc_nr::bsr_cfg_s::retx_bsr_timer_opts::sf320; + // Skip TAG and PHR config + + 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(0b100); + 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 = 0; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg_present = true; + + // UL config dedicated + // PUCCH + auto& ul_config = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg; + ul_config.init_ul_bwp_present = true; + ul_config.init_ul_bwp.pucch_cfg_present = true; + ul_config.init_ul_bwp.pucch_cfg.set_setup(); + ul_config.init_ul_bwp.pucch_cfg.setup().format2_present = true; + ul_config.init_ul_bwp.pucch_cfg.setup().format2.set_setup(); + ul_config.init_ul_bwp.pucch_cfg.setup().format2.setup().max_code_rate_present = true; + ul_config.init_ul_bwp.pucch_cfg.setup().format2.setup().max_code_rate = pucch_max_code_rate_opts::zero_dot25; + + // SR resources + ul_config.init_ul_bwp.pucch_cfg.setup().sched_request_res_to_add_mod_list_present = true; + ul_config.init_ul_bwp.pucch_cfg.setup().sched_request_res_to_add_mod_list.resize(1); + auto& sr_res1 = ul_config.init_ul_bwp.pucch_cfg.setup().sched_request_res_to_add_mod_list[0]; + sr_res1.sched_request_res_id = 1; + sr_res1.sched_request_id = 0; + sr_res1.periodicity_and_offset_present = true; + sr_res1.periodicity_and_offset.set_sl40(); + sr_res1.periodicity_and_offset.sl40() = 4; + sr_res1.res_present = true; + sr_res1.res = 16; + + // DL data + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack_present = true; + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack.resize(1); + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[0] = 4; + + + //TODO? + // PUCCH resources (only one format1 for the moment) + ul_config.init_ul_bwp.pucch_cfg.setup().res_to_add_mod_list_present = true; + ul_config.init_ul_bwp.pucch_cfg.setup().res_to_add_mod_list.resize(1); + auto& pucch_res1 = ul_config.init_ul_bwp.pucch_cfg.setup().res_to_add_mod_list[0]; + pucch_res1.pucch_res_id = 0; + pucch_res1.start_prb = 0; + pucch_res1.format.set_format1(); + pucch_res1.format.format1().init_cyclic_shift = 0; + pucch_res1.format.format1().nrof_symbols = 14; + pucch_res1.format.format1().start_symbol_idx = 0; + pucch_res1.format.format1().time_domain_occ = 0; + + // PUSCH config + ul_config.init_ul_bwp.pusch_cfg_present = true; + ul_config.init_ul_bwp.pusch_cfg.set_setup(); + auto& pusch_cfg_ded = ul_config.init_ul_bwp.pusch_cfg.setup(); + pusch_cfg_ded.dmrs_ul_for_pusch_map_type_a_present = true; + pusch_cfg_ded.dmrs_ul_for_pusch_map_type_a.set_setup(); + pusch_cfg_ded.dmrs_ul_for_pusch_map_type_a.setup().dmrs_add_position_present = true; + pusch_cfg_ded.dmrs_ul_for_pusch_map_type_a.setup().dmrs_add_position = dmrs_ul_cfg_s::dmrs_add_position_opts::pos1; + // PUSH power control skipped + pusch_cfg_ded.res_alloc = pusch_cfg_s::res_alloc_opts::res_alloc_type1; + + // UCI + pusch_cfg_ded.uci_on_pusch_present = true; + pusch_cfg_ded.uci_on_pusch.set_setup(); + pusch_cfg_ded.uci_on_pusch.setup().beta_offsets_present = true; + pusch_cfg_ded.uci_on_pusch.setup().beta_offsets.set_semi_static(); + auto& beta_offset_semi_static = pusch_cfg_ded.uci_on_pusch.setup().beta_offsets.semi_static(); + beta_offset_semi_static.beta_offset_ack_idx1_present = true; + beta_offset_semi_static.beta_offset_ack_idx1 = 9; + beta_offset_semi_static.beta_offset_ack_idx2_present = true; + beta_offset_semi_static.beta_offset_ack_idx2 = 9; + beta_offset_semi_static.beta_offset_ack_idx3_present = true; + beta_offset_semi_static.beta_offset_ack_idx3 = 9; + beta_offset_semi_static.beta_offset_csi_part1_idx1_present = true; + beta_offset_semi_static.beta_offset_csi_part1_idx1 = 6; + beta_offset_semi_static.beta_offset_csi_part1_idx2_present = true; + beta_offset_semi_static.beta_offset_csi_part1_idx2 = 6; + beta_offset_semi_static.beta_offset_csi_part2_idx1_present = true; + beta_offset_semi_static.beta_offset_csi_part2_idx1 = 6; + beta_offset_semi_static.beta_offset_csi_part2_idx2_present = true; + beta_offset_semi_static.beta_offset_csi_part2_idx2 = 6; + pusch_cfg_ded.uci_on_pusch.setup().scaling = uci_on_pusch_s::scaling_opts::f1; + + ul_config.first_active_ul_bwp_id_present = true; + ul_config.first_active_ul_bwp_id = 0; + + // Serving cell config (only to setup) + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.pdcch_serving_cell_cfg_present = true; + 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; + 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.pdsch_serving_cell_cfg.setup().nrof_harq_processes_for_pdsch_present = + true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.pdsch_serving_cell_cfg.setup().nrof_harq_processes_for_pdsch = + pdsch_serving_cell_cfg_s::nrof_harq_processes_for_pdsch_opts::n16; + + 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(); + + //TODO? + // nzp-CSI-RS Resource + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list_present = true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list.resize(1); + auto& nzp_csi_res = + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list[0]; + nzp_csi_res.nzp_csi_rs_res_id = 0; + nzp_csi_res.res_map.freq_domain_alloc.set_row2(); + nzp_csi_res.res_map.freq_domain_alloc.row2().from_number(0b100000000000); + nzp_csi_res.res_map.nrof_ports = asn1::rrc_nr::csi_rs_res_map_s::nrof_ports_opts::p1; + nzp_csi_res.res_map.first_ofdm_symbol_in_time_domain = 4; + nzp_csi_res.res_map.cdm_type = asn1::rrc_nr::csi_rs_res_map_s::cdm_type_opts::no_cdm; + nzp_csi_res.res_map.density.set_one(); + nzp_csi_res.res_map.freq_band.start_rb = 0; + nzp_csi_res.res_map.freq_band.nrof_rbs = 52; + nzp_csi_res.pwr_ctrl_offset = 0; + // Skip pwr_ctrl_offset_ss_present + nzp_csi_res.scrambling_id = 500; + nzp_csi_res.periodicity_and_offset_present = true; + nzp_csi_res.periodicity_and_offset.set_slots80(); + nzp_csi_res.periodicity_and_offset.slots80() = 1; + // optional + nzp_csi_res.qcl_info_periodic_csi_rs_present = true; + nzp_csi_res.qcl_info_periodic_csi_rs = 0; + + //TODO? + // nzp-CSI-RS ResourceSet + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list_present = + true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list.resize(1); + auto& nzp_csi_res_set = + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list[0]; + nzp_csi_res_set.nzp_csi_res_set_id = 1; + nzp_csi_res_set.nzp_csi_rs_res.resize(1); + nzp_csi_res_set.nzp_csi_rs_res[0] = 1; + // Skip TRS info + + // CSI report config + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().csi_report_cfg_to_add_mod_list_present = true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().csi_report_cfg_to_add_mod_list.resize(1); + auto& csi_report = + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().csi_report_cfg_to_add_mod_list[0]; + csi_report.report_cfg_id = 0; + csi_report.res_for_ch_meas = 0; + csi_report.csi_im_res_for_interference_present = true; + csi_report.csi_im_res_for_interference = 1; + csi_report.report_cfg_type.set_periodic(); + csi_report.report_cfg_type.periodic().report_slot_cfg.set_slots80(); + csi_report.report_cfg_type.periodic().report_slot_cfg.slots80() = 5; + csi_report.report_cfg_type.periodic().pucch_csi_res_list.resize(1); + csi_report.report_cfg_type.periodic().pucch_csi_res_list[0].ul_bw_part_id = 0; + csi_report.report_cfg_type.periodic().pucch_csi_res_list[0].pucch_res = 17; + csi_report.report_quant.set_cri_ri_pmi_cqi(); + csi_report.report_freq_cfg_present = true; + csi_report.report_freq_cfg.cqi_format_ind_present = true; + csi_report.report_freq_cfg.cqi_format_ind = + asn1::rrc_nr::csi_report_cfg_s::report_freq_cfg_s_::cqi_format_ind_opts::wideband_cqi; + csi_report.time_restrict_for_ch_meass = asn1::rrc_nr::csi_report_cfg_s::time_restrict_for_ch_meass_opts::not_cfgured; + csi_report.time_restrict_for_interference_meass = + asn1::rrc_nr::csi_report_cfg_s::time_restrict_for_interference_meass_opts::not_cfgured; + csi_report.group_based_beam_report.set_disabled(); + csi_report.cqi_table = asn1::rrc_nr::csi_report_cfg_s::cqi_table_opts::table2; + csi_report.subband_size = asn1::rrc_nr::csi_report_cfg_s::subband_size_opts::value1; + + // Reconfig with Sync + 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 = 17933; + 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 = -36; + 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; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.n_timing_advance_offset = + asn1::rrc_nr::serving_cell_cfg_common_s::n_timing_advance_offset_opts::n0; + + // 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 = + 176210; + + 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(5); + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.absolute_freq_point_a = + 175364; + 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().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 = 16; + 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_short_bitmap().from_number(0b1000); + 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; + + // 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 + asn1::json_writer json_writer2; + cell_group_cfg_pack.to_json(json_writer2); + 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_pdcp_sdu_nr(1, packed_dcch.data(), packed_dcch.size()); +#endif + + return SRSRAN_SUCCESS; +} + + int main() { auto& asn1_logger = srslog::fetch_basic_logger("ASN1", false); @@ -935,7 +1544,8 @@ int main() TESTASSERT(test_ue_mrdc_capabilities() == SRSRAN_SUCCESS); TESTASSERT(test_ue_rrc_reconfiguration() == SRSRAN_SUCCESS); TESTASSERT(test_radio_bearer_config() == SRSRAN_SUCCESS); - TESTASSERT(test_cell_group_config() == SRSRAN_SUCCESS); + TESTASSERT(test_cell_group_config_tdd() == SRSRAN_SUCCESS); + TESTASSERT(test_cell_group_config_fdd() == SRSRAN_SUCCESS); srslog::flush(); diff --git a/srsenb/enb.conf.example b/srsenb/enb.conf.example index 45aaaff21..a76b90874 100644 --- a/srsenb/enb.conf.example +++ b/srsenb/enb.conf.example @@ -170,7 +170,11 @@ enable = false # pusch_mcs: Optional fixed PUSCH MCS (ignores reported CQIs if specified) # pusch_max_mcs: Optional PUSCH MCS limit # min_nof_ctrl_symbols: Minimum number of control symbols -# max_nof_ctrl_symbols: Maximum number of control symbols +# max_nof_ctrl_symbols: Maximum number of control symbols +# pucch_multiplex_enable: Allow PUCCH HARQ to collide with PUSCH and other PUCCH +# pucch_harq_max_rb: Maximum number of RB to be used for PUCCH on the edges of the grid. +# If defined and greater than 0, the scheduler will avoid DL PDCCH allocations if +# PUCCH HARQ falls outside this region # target_bler: Target BLER (in decimal) to achieve via adaptive link # max_delta_dl_cqi: Maximum shift in CQI for adaptive DL link # max_delta_ul_snr: Maximum shift in UL SNR for adaptive UL link @@ -196,6 +200,7 @@ enable = false #min_nof_ctrl_symbols = 1 #max_nof_ctrl_symbols = 3 #pucch_multiplex_enable = false +#pucch_harq_max_rb = 0 #target_bler = 0.05 #max_delta_dl_cqi = 5 #max_delta_ul_snr = 5 diff --git a/srsenb/hdr/enb.h b/srsenb/hdr/enb.h index 69c4075d1..a2084eaba 100644 --- a/srsenb/hdr/enb.h +++ b/srsenb/hdr/enb.h @@ -33,12 +33,14 @@ #include #include "phy/phy.h" +#include "x2_adapter.h" #include "srsran/radio/radio.h" #include "srsenb/hdr/phy/enb_phy_base.h" #include "srsenb/hdr/stack/enb_stack_base.h" #include "srsenb/hdr/stack/rrc/rrc_config.h" +#include "srsenb/hdr/stack/rrc/rrc_config_nr.h" #include "srsenb/hdr/stack/mac/sched_interface.h" #include "srsran/common/bcd_helpers.h" @@ -48,6 +50,7 @@ #include "srsran/common/security.h" #include "srsran/interfaces/enb_command_interface.h" #include "srsran/interfaces/enb_metrics_interface.h" +#include "srsran/interfaces/enb_time_interface.h" #include "srsran/interfaces/ue_interfaces.h" #include "srsran/srslog/srslog.h" #include "srsran/system/sys_metrics_processor.h" @@ -126,7 +129,7 @@ struct rrc_cfg_t; Main eNB class *******************************************************************************/ -class enb : public enb_metrics_interface, enb_command_interface +class enb : public enb_metrics_interface, enb_command_interface, enb_time_interface { public: enb(srslog::sink& log_sink); @@ -149,6 +152,8 @@ public: void toggle_padding() override; + void tti_clock() override; + private: const static int ENB_POOL_SIZE = 1024 * 10; @@ -160,11 +165,14 @@ private: all_args_t args = {}; bool started = false; - phy_cfg_t phy_cfg = {}; - rrc_cfg_t rrc_cfg = {}; + phy_cfg_t phy_cfg = {}; + rrc_cfg_t rrc_cfg = {}; + rrc_nr_cfg_t rrc_nr_cfg = {}; // eNB components - std::unique_ptr stack = nullptr; + x2_adapter x2; + std::unique_ptr eutra_stack = nullptr; + std::unique_ptr nr_stack = nullptr; std::unique_ptr radio = nullptr; std::unique_ptr phy = nullptr; diff --git a/srsenb/hdr/phy/nr/worker_pool.h b/srsenb/hdr/phy/nr/worker_pool.h index 2f3ec3f4b..0c462c823 100644 --- a/srsenb/hdr/phy/nr/worker_pool.h +++ b/srsenb/hdr/phy/nr/worker_pool.h @@ -80,7 +80,6 @@ private: int get_mch_sched(uint32_t tti, bool is_mcch, dl_sched_list_t& dl_sched_res) override { return 0; } int get_ul_sched(uint32_t tti, ul_sched_list_t& ul_sched_res) override { return 0; } void set_sched_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs) override {} - void tti_clock() override {} }; srsran::phy_common_interface& common; diff --git a/srsenb/hdr/phy/phy.h b/srsenb/hdr/phy/phy.h index a1d84dea9..444d83a31 100644 --- a/srsenb/hdr/phy/phy.h +++ b/srsenb/hdr/phy/phy.h @@ -27,6 +27,7 @@ #include "srsenb/hdr/phy/enb_phy_base.h" #include "srsran/common/trace.h" #include "srsran/interfaces/enb_metrics_interface.h" +#include "srsran/interfaces/enb_time_interface.h" #include "srsran/interfaces/radio_interfaces.h" #include "srsran/radio/radio.h" #include "srsran/srslog/srslog.h" @@ -46,12 +47,14 @@ public: int init(const phy_args_t& args, const phy_cfg_t& cfg, srsran::radio_interface_phy* radio_, - stack_interface_phy_lte* stack_); + stack_interface_phy_lte* stack_, + enb_time_interface* enb_); int init(const phy_args_t& args, const phy_cfg_t& cfg, srsran::radio_interface_phy* radio_, stack_interface_phy_lte* stack_lte_, - stack_interface_phy_nr& stack_nr_); + stack_interface_phy_nr& stack_nr_, + enb_time_interface* enb_); void stop() override; std::string get_type() override { return "lte"; }; diff --git a/srsenb/hdr/phy/txrx.h b/srsenb/hdr/phy/txrx.h index 8fd1ebab2..4d53cb058 100644 --- a/srsenb/hdr/phy/txrx.h +++ b/srsenb/hdr/phy/txrx.h @@ -27,6 +27,7 @@ #include "srsenb/hdr/phy/lte/worker_pool.h" #include "srsenb/hdr/phy/nr/worker_pool.h" #include "srsran/config.h" +#include "srsran/interfaces/enb_time_interface.h" #include "srsran/phy/channel/channel.h" #include "srsran/radio/radio.h" #include @@ -37,7 +38,7 @@ class txrx final : public srsran::thread { public: txrx(srslog::basic_logger& logger); - bool init(stack_interface_phy_lte* stack_, + bool init(enb_time_interface* enb_, srsran::radio_interface_phy* radio_handler, lte::worker_pool* lte_workers_, phy_common* worker_com, @@ -49,7 +50,7 @@ public: private: void run_thread() override; - stack_interface_phy_lte* stack = nullptr; + enb_time_interface* enb = nullptr; srsran::radio_interface_phy* radio_h = nullptr; srslog::basic_logger& logger; lte::worker_pool* lte_workers = nullptr; diff --git a/srsenb/hdr/stack/enb_stack_base.h b/srsenb/hdr/stack/enb_stack_base.h index 6d44b420d..9b9ae95c6 100644 --- a/srsenb/hdr/stack/enb_stack_base.h +++ b/srsenb/hdr/stack/enb_stack_base.h @@ -69,7 +69,6 @@ typedef struct { } stack_log_args_t; typedef struct { - std::string type; uint32_t sync_queue_size; // Max allowed difference between PHY and Stack clocks (in TTI) uint32_t gtpu_indirect_tunnel_timeout_msec; mac_args_t mac; @@ -95,6 +94,8 @@ public: virtual void toggle_padding() = 0; // eNB metrics interface virtual bool get_metrics(stack_metrics_t* metrics) = 0; + + virtual void tti_clock() = 0; }; } // namespace srsenb diff --git a/srsenb/hdr/stack/enb_stack_lte.h b/srsenb/hdr/stack/enb_stack_lte.h index 5603b142f..3b98d54db 100644 --- a/srsenb/hdr/stack/enb_stack_lte.h +++ b/srsenb/hdr/stack/enb_stack_lte.h @@ -28,9 +28,7 @@ #define SRSRAN_ENB_STACK_LTE_H #include "mac/mac.h" -#include "mac/nr/mac_nr.h" #include "rrc/rrc.h" -#include "rrc/rrc_nr.h" #include "s1ap/s1ap.h" #include "srsran/common/task_scheduler.h" #include "upper/gtpu.h" @@ -49,7 +47,7 @@ class gtpu_pdcp_adapter; class enb_stack_lte final : public enb_stack_base, public stack_interface_phy_lte, - public stack_interface_phy_nr, + public rrc_eutra_interface_rrc_nr, public srsran::thread { public: @@ -57,12 +55,7 @@ public: ~enb_stack_lte() final; // eNB stack base interface - int init(const stack_args_t& args_, - const rrc_cfg_t& rrc_cfg_, - phy_interface_stack_lte* phy_, - phy_interface_stack_nr* phy_nr_); - int init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_, phy_interface_stack_lte* phy_); - int init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_); + int init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_, phy_interface_stack_lte* phy_, x2_interface* x2_); void stop() final; std::string get_type() final; bool get_metrics(stack_metrics_t* metrics) final; @@ -124,25 +117,16 @@ public: void toggle_padding() override { mac.toggle_padding(); } void tti_clock() override; - // mac_interface_phy_nr - int slot_indication(const srsran_slot_cfg_t& slot_cfg) override { return mac_nr.slot_indication(slot_cfg); } - int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, srsenb::mac_interface_phy_nr::dl_sched_t& dl_sched) override + // rrc_eutra_interface_rrc_nr + void sgnb_addition_ack(uint16_t eutra_rnti, sgnb_addition_ack_params_t params) final { - return mac_nr.get_dl_sched(slot_cfg, dl_sched); + rrc.sgnb_addition_ack(eutra_rnti, params); } - int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, srsenb::mac_interface_phy_nr::ul_sched_t& ul_sched) override + void sgnb_addition_reject(uint16_t eutra_rnti) final { rrc.sgnb_addition_reject(eutra_rnti); } + void sgnb_addition_complete(uint16_t eutra_rnti, uint16_t nr_rnti) final { - return mac_nr.get_ul_sched(slot_cfg, ul_sched); + rrc.sgnb_addition_complete(eutra_rnti, nr_rnti); } - int pucch_info(const srsran_slot_cfg_t& slot_cfg, const pucch_info_t& pucch_info) override - { - return mac_nr.pucch_info(slot_cfg, pucch_info); - } - int pusch_info(const srsran_slot_cfg_t& slot_cfg, pusch_info_t& pusch_info) override - { - return mac_nr.pusch_info(slot_cfg, pusch_info); - } - void rach_detected(const rach_info_t& rach_info) override { mac_nr.rach_detected(rach_info); } private: static const int STACK_MAIN_THREAD_PRIO = 4; @@ -164,10 +148,6 @@ private: srslog::basic_logger& s1ap_logger; srslog::basic_logger& gtpu_logger; srslog::basic_logger& stack_logger; - srslog::basic_logger& rrc_nr_logger; - srslog::basic_logger& mac_nr_logger; - srslog::basic_logger& rlc_nr_logger; - srslog::basic_logger& pdcp_nr_logger; // PCAP and trace option srsran::mac_pcap mac_pcap; @@ -189,15 +169,8 @@ private: srsenb::gtpu gtpu; srsenb::s1ap s1ap; - // NR components for NSA mode - srsenb::mac_nr mac_nr; - srsenb::rlc rlc_nr; - srsenb::pdcp pdcp_nr; - srsenb::rrc_nr rrc_nr; - // RAT-specific interfaces phy_interface_stack_lte* phy = nullptr; - phy_interface_stack_nr* phy_nr = nullptr; // state std::atomic started{false}; diff --git a/srsenb/hdr/stack/gnb_stack_nr.h b/srsenb/hdr/stack/gnb_stack_nr.h index 972415ff9..2195c7396 100644 --- a/srsenb/hdr/stack/gnb_stack_nr.h +++ b/srsenb/hdr/stack/gnb_stack_nr.h @@ -27,16 +27,15 @@ #ifndef SRSRAN_GNB_STACK_NR_H #define SRSRAN_GNB_STACK_NR_H -#include "s1ap/s1ap.h" #include "srsenb/hdr/stack/mac/nr/mac_nr.h" #include "srsenb/hdr/stack/rrc/rrc_nr.h" #include "srsenb/hdr/stack/upper/pdcp_nr.h" #include "srsenb/hdr/stack/upper/rlc_nr.h" -#include "upper/gtpu.h" +#include "upper/pdcp.h" +#include "upper/rlc.h" #include "upper/sdap.h" #include "enb_stack_base.h" -#include "srsenb/hdr/enb.h" #include "srsran/interfaces/gnb_interfaces.h" // This is needed for GW @@ -49,14 +48,18 @@ class gnb_stack_nr final : public srsenb::enb_stack_base, public stack_interface_phy_nr, public stack_interface_mac, public srsue::stack_interface_gw, + public rrc_nr_interface_rrc, + public pdcp_interface_gtpu, // for user-plane over X2 public srsran::thread { public: - explicit gnb_stack_nr(); + explicit gnb_stack_nr(srslog::sink& log_sink); ~gnb_stack_nr() final; - int init(const srsenb::stack_args_t& args_, const rrc_nr_cfg_t& rrc_cfg_, phy_interface_stack_nr* phy_); - int init(const srsenb::stack_args_t& args_, const rrc_nr_cfg_t& rrc_cfg_); + int init(const srsenb::stack_args_t& args_, + const rrc_nr_cfg_t& rrc_cfg_, + phy_interface_stack_nr* phy_, + x2_interface* x2_); // eNB stack base interface void stop() final; @@ -71,12 +74,12 @@ public: void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) override; bool has_active_radio_bearer(uint32_t eps_bearer_id) override; bool switch_on(); - void run_tti(uint32_t tti); + void tti_clock() override; // MAC interface to trigger processing of received PDUs void process_pdus() final; - void toggle_padding() override { srsran::console("padding not available for NR\n"); } + void toggle_padding() 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; @@ -85,15 +88,40 @@ public: int pusch_info(const srsran_slot_cfg_t& slot_cfg, pusch_info_t& pusch_info) override; void rach_detected(const rach_info_t& rach_info) override; + // X2 interface + + // control plane, i.e. rrc_nr_interface_rrc + int sgnb_addition_request(uint16_t eutra_rnti, const sgnb_addition_req_params_t& params) final + { + return rrc.sgnb_addition_request(eutra_rnti, params); + }; + int sgnb_reconfiguration_complete(uint16_t eutra_rnti, asn1::dyn_octstring reconfig_response) final + { + return rrc.sgnb_reconfiguration_complete(eutra_rnti, reconfig_response); + }; + // X2 data interface + void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu, int pdcp_sn = -1) final + { + pdcp.write_sdu(rnti, lcid, std::move(sdu), pdcp_sn); + } + std::map get_buffered_pdus(uint16_t rnti, uint32_t lcid) final + { + return pdcp.get_buffered_pdus(rnti, lcid); + } + private: void run_thread() final; - void run_tti_impl(uint32_t tti); + void tti_clock_impl(); // args srsenb::stack_args_t args = {}; phy_interface_stack_nr* phy = nullptr; + srslog::basic_logger& rrc_logger; + srslog::basic_logger& mac_logger; srslog::basic_logger& rlc_logger; + srslog::basic_logger& pdcp_logger; + srslog::basic_logger& stack_logger; // task scheduling static const int STACK_MAIN_THREAD_PRIO = 4; @@ -101,18 +129,14 @@ private: srsran::task_multiqueue::queue_handle sync_task_queue, ue_task_queue, gw_task_queue, mac_task_queue; // derived - std::unique_ptr m_mac; - std::unique_ptr m_rlc; - std::unique_ptr m_pdcp; - std::unique_ptr m_sdap; - std::unique_ptr m_rrc; - std::unique_ptr m_gw; - // std::unique_ptr m_ngap; - // std::unique_ptr m_gtpu; + srsenb::mac_nr mac; + srsenb::rlc rlc; + srsenb::pdcp pdcp; + srsenb::rrc_nr rrc; + // std::unique_ptr m_sdap; // state - bool running = false; - uint32_t current_tti = 10240; + std::atomic running = {false}; }; } // namespace srsenb diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index eb5532b2b..1d0ad0203 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -69,7 +69,7 @@ public: struct cell_cfg_t { srsran_carrier_nr_t carrier = {}; - srsran_tdd_config_nr_t tdd = {}; + srsran_duplex_config_nr_t duplex = {}; srsran::phy_cfg_nr_t::ssb_cfg_t ssb = {}; srsran::bounded_vector bwps{1}; // idx0 for BWP-common }; diff --git a/srsenb/hdr/stack/mac/sched_interface.h b/srsenb/hdr/stack/mac/sched_interface.h index 3129740d3..608f38e07 100644 --- a/srsenb/hdr/stack/mac/sched_interface.h +++ b/srsenb/hdr/stack/mac/sched_interface.h @@ -67,6 +67,7 @@ public: int max_aggr_level = 3; bool adaptive_aggr_level = false; bool pucch_mux_enabled = false; + int pucch_harq_max_rb = 0; float target_bler = 0.05; float max_delta_dl_cqi = 5; float max_delta_ul_snr = 5; diff --git a/srsenb/hdr/stack/mac/ta.h b/srsenb/hdr/stack/mac/ta.h index e296dbf62..3de31a216 100644 --- a/srsenb/hdr/stack/mac/ta.h +++ b/srsenb/hdr/stack/mac/ta.h @@ -208,6 +208,7 @@ public: */ void start() { + std::lock_guard lock(mutex); // Transition to idle only if the current state is idle if (state == state_idle) { state = state_measure; diff --git a/srsenb/hdr/stack/mac/ue.h b/srsenb/hdr/stack/mac/ue.h index 19253fc21..f75cb76b1 100644 --- a/srsenb/hdr/stack/mac/ue.h +++ b/srsenb/hdr/stack/mac/ue.h @@ -169,20 +169,20 @@ public: srsran_softbuffer_tx_t* get_tx_softbuffer(uint32_t enb_cc_idx, uint32_t harq_process, uint32_t tb_idx); srsran_softbuffer_rx_t* get_rx_softbuffer(uint32_t enb_cc_idx, uint32_t tti); - uint8_t* request_buffer(uint32_t tti, uint32_t enb_cc_idx, uint32_t len); - void process_pdu(srsran::unique_byte_buffer_t pdu, uint32_t ue_cc_idx, uint32_t grant_nof_prbs); + uint8_t* request_buffer(uint32_t tti, uint32_t enb_cc_idx, uint32_t len); + void process_pdu(srsran::unique_byte_buffer_t pdu, uint32_t ue_cc_idx, uint32_t grant_nof_prbs); srsran::unique_byte_buffer_t release_pdu(uint32_t tti, uint32_t enb_cc_idx); void clear_old_buffers(uint32_t tti); 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(); + 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; @@ -197,11 +197,11 @@ private: srslog::basic_logger& logger; sched_interface* sched = nullptr; - srsran::mac_pcap* pcap = nullptr; - srsran::mac_pcap_net* pcap_net = nullptr; - uint64_t conres_id = 0; - uint16_t rnti = 0; - uint32_t last_tti = 0; + srsran::mac_pcap* pcap = nullptr; + srsran::mac_pcap_net* pcap_net = nullptr; + uint64_t conres_id = 0; + uint16_t rnti = 0; + std::atomic last_tti{0}; uint32_t nof_failures = 0; std::atomic active_state{true}; diff --git a/srsenb/hdr/stack/rrc/rrc.h b/srsenb/hdr/stack/rrc/rrc.h index 3159aeb01..e6506c710 100644 --- a/srsenb/hdr/stack/rrc/rrc.h +++ b/srsenb/hdr/stack/rrc/rrc.h @@ -35,6 +35,7 @@ #include "srsran/common/task_scheduler.h" #include "srsran/common/timeout.h" #include "srsran/interfaces/enb_rrc_interfaces.h" +#include "srsran/interfaces/enb_x2_interfaces.h" #include "srsran/srslog/srslog.h" #include diff --git a/srsenb/hdr/stack/rrc/rrc_nr.h b/srsenb/hdr/stack/rrc/rrc_nr.h index 528cb4845..011746433 100644 --- a/srsenb/hdr/stack/rrc/rrc_nr.h +++ b/srsenb/hdr/stack/rrc/rrc_nr.h @@ -36,6 +36,7 @@ #include "srsran/interfaces/enb_pdcp_interfaces.h" #include "srsran/interfaces/enb_rlc_interfaces.h" #include "srsran/interfaces/enb_rrc_interfaces.h" +#include "srsran/interfaces/enb_x2_interfaces.h" #include "srsran/interfaces/gnb_interfaces.h" #include "srsran/interfaces/gnb_mac_interfaces.h" #include "srsran/interfaces/gnb_ngap_interfaces.h" @@ -126,7 +127,9 @@ public: 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_secondary_cell_group_config_common(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); + int pack_secondary_cell_group_config_fdd(asn1::dyn_octstring& packed_secondary_cell_config); + int pack_secondary_cell_group_config_tdd(asn1::dyn_octstring& packed_secondary_cell_config); int pack_nr_radio_bearer_config(asn1::dyn_octstring& packed_nr_bearer_config); int add_drb(); diff --git a/srsenb/hdr/x2_adapter.h b/srsenb/hdr/x2_adapter.h new file mode 100644 index 000000000..047533af8 --- /dev/null +++ b/srsenb/hdr/x2_adapter.h @@ -0,0 +1,120 @@ +/** + * + * \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. + * + */ + +/** + * @brief Dummy X2AP implementation + * + * Dummy X2 adapter to facilitate communication between EUTRA RRC and NR RRC + * for EN-DC procedures. + * + * The class uses direct function calls instead of real X2AP ASN1 encoded + * messages. It mainly focuses on Sec 9.1.4 of TS 36.423 Rel. 15.11 + * for E-UTRAN-NR Dual Connectivity Procedures, i.e. SgNB-* + * + * It furthermore provide an interface for the GTPU adapter to + * write DL PDUs, which it then forwards to the NR PDCP. + * + * It also provides a method to allow the eNB to foward timing + * signal, i.e. TTI tics, to the NR stack. + */ + +#ifndef SRSENB_X2_ADAPTER_H +#define SRSENB_X2_ADAPTER_H + +#include "srsran/interfaces/enb_x2_interfaces.h" +#include "stack/enb_stack_lte.h" +#include "stack/gnb_stack_nr.h" + +namespace srsenb { + +class x2_adapter final : public x2_interface +{ +public: + x2_adapter() = default; + + // init functions to set handle to stacks + void set_eutra_stack(enb_stack_lte* eutra_stack_) { eutra_stack = eutra_stack_; } + + void set_nr_stack(gnb_stack_nr* nr_stack_) { nr_stack = nr_stack_; } + + /// rrc_nr_interface_rrc + int sgnb_addition_request(uint16_t eutra_rnti, const sgnb_addition_req_params_t& params) + { + if (nr_stack == nullptr) { + return SRSRAN_ERROR; + } + return nr_stack->sgnb_addition_request(eutra_rnti, params); + } + int sgnb_reconfiguration_complete(uint16_t eutra_rnti, asn1::dyn_octstring reconfig_response) + { + if (nr_stack == nullptr) { + return SRSRAN_ERROR; + } + return nr_stack->sgnb_reconfiguration_complete(eutra_rnti, reconfig_response); + } + + /// rrc_eutra_interface_rrc_nr + void sgnb_addition_ack(uint16_t eutra_rnti, sgnb_addition_ack_params_t params) + { + if (eutra_stack == nullptr) { + return; + } + eutra_stack->sgnb_addition_ack(eutra_rnti, params); + } + void sgnb_addition_reject(uint16_t eutra_rnti) + { + if (eutra_stack == nullptr) { + return; + } + eutra_stack->sgnb_addition_reject(eutra_rnti); + } + void sgnb_addition_complete(uint16_t eutra_rnti, uint16_t nr_rnti) + { + if (eutra_stack == nullptr) { + return; + } + eutra_stack->sgnb_addition_complete(eutra_rnti, nr_rnti); + } + + // stack_nr_interface_stack_eutra + void tti_clock() + { + if (nr_stack == nullptr) { + return; + } + nr_stack->tti_clock(); + } + + // pdcp_interface_gtpu + void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu, int pdcp_sn = -1) + { + if (nr_stack == nullptr) { + return; + } + nr_stack->write_sdu(rnti, lcid, std::move(sdu), pdcp_sn); + } + std::map get_buffered_pdus(uint16_t rnti, uint32_t lcid) + { + if (nr_stack == nullptr) { + return {}; + } + return nr_stack->get_buffered_pdus(rnti, lcid); + } + +private: + enb_stack_lte* eutra_stack = nullptr; + gnb_stack_nr* nr_stack = nullptr; +}; + +} // namespace srsenb + +#endif // SRSENB_X2_ADAPTER_H diff --git a/srsenb/rb.conf.example b/srsenb/rb.conf.example index 27d997fc3..de1cb8f33 100644 --- a/srsenb/rb.conf.example +++ b/srsenb/rb.conf.example @@ -12,9 +12,9 @@ // t_reordering = 35; // t_status_prohibit = 0; // }; -// }; -// enb_specific = { -// dl_max_retx_thresh = 32; +// enb_specific = { +// dl_max_retx_thresh = 32; +// }; // }; // } @@ -30,9 +30,9 @@ // t_reordering = 35; // t_status_prohibit = 0; // }; -// }; -// enb_specific = { -// dl_max_retx_thresh = 32; +// enb_specific = { +// dl_max_retx_thresh = 32; +// }; // }; // } diff --git a/srsenb/src/enb.cc b/srsenb/src/enb.cc index 78fa24951..cbab78e61 100644 --- a/srsenb/src/enb.cc +++ b/srsenb/src/enb.cc @@ -39,7 +39,8 @@ enb::enb(srslog::sink& log_sink) : enb::~enb() { - stack.reset(); + eutra_stack.reset(); + nr_stack.reset(); } int enb::init(const all_args_t& args_) @@ -59,55 +60,79 @@ int enb::init(const all_args_t& args_) srsran::byte_buffer_pool::get_instance()->enable_logger(true); // Create layers - if (args.stack.type == "lte") { - std::unique_ptr lte_stack(new enb_stack_lte(log_sink)); - if (!lte_stack) { - srsran::console("Error creating eNB stack.\n"); + std::unique_ptr tmp_eutra_stack; + if (not rrc_cfg.cell_list.empty()) { + // add EUTRA stack + tmp_eutra_stack.reset(new enb_stack_lte(log_sink)); + if (tmp_eutra_stack == nullptr) { + srsran::console("Error creating EUTRA stack.\n"); return SRSRAN_ERROR; } + x2.set_eutra_stack(tmp_eutra_stack.get()); + } - std::unique_ptr lte_radio = std::unique_ptr(new srsran::radio); - if (!lte_radio) { - srsran::console("Error creating radio multi instance.\n"); + std::unique_ptr tmp_nr_stack; + if (not rrc_cfg.cell_list_nr.empty()) { + // add NR stack + tmp_nr_stack.reset(new gnb_stack_nr(log_sink)); + if (tmp_nr_stack == nullptr) { + srsran::console("Error creating NR stack.\n"); return SRSRAN_ERROR; } + x2.set_nr_stack(tmp_nr_stack.get()); + } - std::unique_ptr lte_phy = std::unique_ptr(new srsenb::phy(log_sink)); - if (!lte_phy) { - srsran::console("Error creating LTE PHY instance.\n"); - return SRSRAN_ERROR; - } + // Radio and PHY are RAT agnostic + std::unique_ptr tmp_radio = std::unique_ptr(new srsran::radio); + if (tmp_radio == nullptr) { + srsran::console("Error creating radio multi instance.\n"); + return SRSRAN_ERROR; + } - if (ret == SRSRAN_SUCCESS) { - if (lte_stack->init(args.stack, rrc_cfg, lte_phy.get(), lte_phy.get()) != SRSRAN_SUCCESS) { - srsran::console("Error initializing stack.\n"); - ret = SRSRAN_ERROR; - } - } + std::unique_ptr tmp_phy = std::unique_ptr(new srsenb::phy(log_sink)); + if (tmp_phy == nullptr) { + srsran::console("Error creating PHY instance.\n"); + return SRSRAN_ERROR; + } - // Init Radio - if (lte_radio->init(args.rf, lte_phy.get())) { - srsran::console("Error initializing radio.\n"); - return SRSRAN_ERROR; + // initialize layers, if they exist + if (tmp_eutra_stack) { + if (tmp_eutra_stack->init(args.stack, rrc_cfg, tmp_phy.get(), &x2) != SRSRAN_SUCCESS) { + srsran::console("Error initializing EUTRA stack.\n"); + ret = SRSRAN_ERROR; } + } - // Only Init PHY if radio could be initialized - if (ret == SRSRAN_SUCCESS) { - if (lte_phy->init(args.phy, phy_cfg, lte_radio.get(), lte_stack.get(), *lte_stack)) { - srsran::console("Error initializing PHY.\n"); - ret = SRSRAN_ERROR; - } + if (tmp_nr_stack) { + if (tmp_nr_stack->init(args.stack, rrc_nr_cfg, tmp_phy.get(), &x2) != SRSRAN_SUCCESS) { + srsran::console("Error initializing NR stack.\n"); + ret = SRSRAN_ERROR; } + } - stack = std::move(lte_stack); - phy = std::move(lte_phy); - radio = std::move(lte_radio); - - } else { - srsran::console("Stack type %s not supported.\n", args.stack.type.c_str()); + // Init Radio + if (tmp_radio->init(args.rf, tmp_phy.get())) { + srsran::console("Error initializing radio.\n"); return SRSRAN_ERROR; } + // Only Init PHY if radio could be initialized + if (ret == SRSRAN_SUCCESS) { + if (tmp_phy->init(args.phy, phy_cfg, tmp_radio.get(), tmp_eutra_stack.get(), *tmp_nr_stack, this)) { + srsran::console("Error initializing PHY.\n"); + ret = SRSRAN_ERROR; + } + } + + if (tmp_eutra_stack) { + eutra_stack = std::move(tmp_eutra_stack); + } + if (tmp_nr_stack) { + nr_stack = std::move(tmp_nr_stack); + } + phy = std::move(tmp_phy); + radio = std::move(tmp_radio); + started = true; // set to true in any case to allow stopping the eNB if an error happened // Now that everything is setup, log sector start events. @@ -136,8 +161,12 @@ void enb::stop() phy->stop(); } - if (stack) { - stack->stop(); + if (eutra_stack) { + eutra_stack->stop(); + } + + if (nr_stack) { + nr_stack->stop(); } if (radio) { @@ -176,7 +205,9 @@ bool enb::get_metrics(enb_metrics_t* m) { radio->get_metrics(&m->rf); phy->get_metrics(m->phy); - stack->get_metrics(&m->stack); + if (eutra_stack) { + eutra_stack->get_metrics(&m->stack); + } m->running = started; m->sys = sys_proc.get_metrics(); return true; @@ -209,7 +240,19 @@ std::string enb::get_build_string() void enb::toggle_padding() { - stack->toggle_padding(); + if (eutra_stack) { + eutra_stack->toggle_padding(); + } +} + +void enb::tti_clock() +{ + if (eutra_stack) { + eutra_stack->tti_clock(); + } + if (nr_stack) { + nr_stack->tti_clock(); + } } } // namespace srsenb diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index dcdbe4921..e174b58de 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -756,7 +756,9 @@ int parse_rr(all_args_t* args_, rrc_cfg_t* rrc_cfg_) cell_cnfg.add_field(new rr_sections::cell_list_section(args_, rrc_cfg_)); // NR RRC and cell config section + bool nr_cell_cnfg_present = false; parser::section nr_cell_cnfg("nr_cell_list"); + nr_cell_cnfg.set_optional(&nr_cell_cnfg_present); nr_cell_cnfg.add_field(new rr_sections::nr_cell_list_section(args_, rrc_cfg_)); // Run parser with two sections @@ -1203,12 +1205,9 @@ int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_ // auto-detect UL frequency if (cfg.ul_earfcn == 0) { // derive UL ARFCN from given DL ARFCN - uint16_t nr_band = band_helper.get_band_from_dl_freq_Hz(phy_cell_cfg.dl_freq_hz); - srsran_duplex_mode_t nr_duplex = band_helper.get_duplex_mode(nr_band); - if (nr_duplex == SRSRAN_DUPLEX_MODE_TDD) { - cfg.ul_earfcn = cfg.dl_earfcn; - } else { - ERROR("Can't derive UL ARFCN from DL ARFCN"); + cfg.ul_earfcn = band_helper.get_ul_arfcn_from_dl_arfcn(cfg.dl_earfcn); + if (cfg.ul_earfcn == 0) { + ERROR("Can't derive UL ARFCN from DL ARFCN %d", cfg.dl_earfcn); return SRSRAN_ERROR; } } diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 39fa9ab72..d06e32144 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -75,8 +75,6 @@ void parse_args(all_args_t* args, int argc, char* argv[]) // Command line or config file options bpo::options_description common("Configuration options"); common.add_options() - - ("enb.stack", bpo::value(&args->stack.type)->default_value("lte"), "Type of the upper stack [lte, nr]") ("enb.enb_id", bpo::value(&enb_id)->default_value("0x0"), "eNodeB ID") ("enb.name", bpo::value(&args->stack.s1ap.enb_name)->default_value("srsenb01"), "eNodeB Name") ("enb.mcc", bpo::value(&mcc)->default_value("001"), "Mobile Country Code") @@ -163,6 +161,7 @@ void parse_args(all_args_t* args, int argc, char* argv[]) ("scheduler.max_nof_ctrl_symbols", bpo::value(&args->stack.mac.sched.max_nof_ctrl_symbols)->default_value(3), "Number of control symbols") ("scheduler.min_nof_ctrl_symbols", bpo::value(&args->stack.mac.sched.min_nof_ctrl_symbols)->default_value(1), "Minimum number of control symbols") ("scheduler.pucch_multiplex_enable", bpo::value(&args->stack.mac.sched.pucch_mux_enabled)->default_value(false), "Enable PUCCH multiplexing") + ("scheduler.pucch_harq_max_rb", bpo::value(&args->stack.mac.sched.pucch_harq_max_rb)->default_value(0), "Maximum number of RB to be used for PUCCH on the edges of the grid") ("scheduler.target_bler", bpo::value(&args->stack.mac.sched.target_bler)->default_value(0.05), "Target BLER (in decimal) to achieve via adaptive link") ("scheduler.max_delta_dl_cqi", bpo::value(&args->stack.mac.sched.max_delta_dl_cqi)->default_value(5.0), "Maximum shift in CQI for adaptive DL link") ("scheduler.max_delta_ul_snr", bpo::value(&args->stack.mac.sched.max_delta_ul_snr)->default_value(5.0), "Maximum shift in UL SNR for adaptive UL link") diff --git a/srsenb/src/phy/phy.cc b/srsenb/src/phy/phy.cc index 56a7b44ba..1fa414831 100644 --- a/srsenb/src/phy/phy.cc +++ b/srsenb/src/phy/phy.cc @@ -106,9 +106,10 @@ int phy::init(const phy_args_t& args, const phy_cfg_t& cfg, srsran::radio_interface_phy* radio_, stack_interface_phy_lte* stack_lte_, - stack_interface_phy_nr& stack_nr_) + stack_interface_phy_nr& stack_nr_, + enb_time_interface* enb_) { - if (init(args, cfg, radio_, stack_lte_) != SRSRAN_SUCCESS) { + if (init(args, cfg, radio_, stack_lte_, enb_) != SRSRAN_SUCCESS) { phy_log.error("Couldn't initialize LTE PHY"); return SRSRAN_ERROR; } @@ -124,7 +125,8 @@ int phy::init(const phy_args_t& args, int phy::init(const phy_args_t& args, const phy_cfg_t& cfg, srsran::radio_interface_phy* radio_, - stack_interface_phy_lte* stack_) + stack_interface_phy_lte* stack_lte_, + enb_time_interface* enb_) { if (cfg.phy_cell_cfg.size() > SRSRAN_MAX_CARRIERS) { phy_log.error( @@ -151,7 +153,7 @@ int phy::init(const phy_args_t& args, workers_common.params = args; - workers_common.init(cfg.phy_cell_cfg, cfg.phy_cell_cfg_nr, radio, stack_); + workers_common.init(cfg.phy_cell_cfg, cfg.phy_cell_cfg_nr, radio, stack_lte_); parse_common_config(cfg); @@ -163,13 +165,18 @@ int phy::init(const phy_args_t& args, // For each carrier, initialise PRACH worker for (uint32_t cc = 0; cc < cfg.phy_cell_cfg.size(); cc++) { prach_cfg.root_seq_idx = cfg.phy_cell_cfg[cc].root_seq_idx; - prach.init( - cc, cfg.phy_cell_cfg[cc].cell, prach_cfg, stack_, phy_log, PRACH_WORKER_THREAD_PRIO, args.nof_prach_threads); + prach.init(cc, + cfg.phy_cell_cfg[cc].cell, + prach_cfg, + stack_lte_, + phy_log, + PRACH_WORKER_THREAD_PRIO, + args.nof_prach_threads); } prach.set_max_prach_offset_us(args.max_prach_offset_us); // Warning this must be initialized after all workers have been added to the pool - tx_rx.init(stack_, radio, <e_workers, &workers_common, &prach, SF_RECV_THREAD_PRIO); + tx_rx.init(enb_, radio, <e_workers, &workers_common, &prach, SF_RECV_THREAD_PRIO); initialized = true; diff --git a/srsenb/src/phy/txrx.cc b/srsenb/src/phy/txrx.cc index 96a08e6bc..a55ccca66 100644 --- a/srsenb/src/phy/txrx.cc +++ b/srsenb/src/phy/txrx.cc @@ -48,14 +48,14 @@ txrx::txrx(srslog::basic_logger& logger) : thread("TXRX"), logger(logger), runni /* Do nothing */ } -bool txrx::init(stack_interface_phy_lte* stack_, +bool txrx::init(enb_time_interface* enb_, srsran::radio_interface_phy* radio_h_, lte::worker_pool* lte_workers_, phy_common* worker_com_, prach_worker_pool* prach_, uint32_t prio_) { - stack = stack_; + enb = enb_; radio_h = radio_h_; lte_workers = lte_workers_; worker_com = worker_com_; @@ -222,8 +222,8 @@ void txrx::run_thread() lte_workers->start_worker(lte_worker); } - // Advance stack in time - stack->tti_clock(); + // Advance in time + enb->tti_clock(); } } diff --git a/srsenb/src/stack/enb_stack_lte.cc b/srsenb/src/stack/enb_stack_lte.cc index 3924829dd..ed0d04b29 100644 --- a/srsenb/src/stack/enb_stack_lte.cc +++ b/srsenb/src/stack/enb_stack_lte.cc @@ -22,8 +22,8 @@ #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/interfaces/enb_x2_interfaces.h" #include "srsran/rlc/bearer_mem_pool.h" #include "srsran/srslog/event_trace.h" @@ -36,10 +36,10 @@ class gtpu_pdcp_adapter final : public gtpu_interface_pdcp, public pdcp_interfac public: gtpu_pdcp_adapter(srslog::basic_logger& logger_, pdcp* pdcp_lte, - pdcp* pdcp_nr, + pdcp_interface_gtpu* pdcp_x2, gtpu* gtpu_, enb_bearer_manager& bearers_) : - logger(logger_), pdcp_obj(pdcp_lte), pdcp_nr_obj(pdcp_nr), gtpu_obj(gtpu_), bearers(&bearers_) + logger(logger_), pdcp_obj(pdcp_lte), pdcp_x2_obj(pdcp_x2), gtpu_obj(gtpu_), bearers(&bearers_) {} /// Converts LCID to EPS-BearerID and sends corresponding PDU to GTPU @@ -59,7 +59,7 @@ public: if (bearer.rat == srsran_rat_t::lte) { pdcp_obj->write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); } else if (bearer.rat == srsran_rat_t::nr) { - pdcp_nr_obj->write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); + pdcp_x2_obj->write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); } else { logger.warning("Can't deliver SDU for EPS bearer %d. Dropping it.", eps_bearer_id); } @@ -71,7 +71,7 @@ public: if (bearer.rat == srsran_rat_t::lte) { return pdcp_obj->get_buffered_pdus(rnti, bearer.lcid); } else if (bearer.rat == srsran_rat_t::nr) { - return pdcp_nr_obj->get_buffered_pdus(rnti, bearer.lcid); + return pdcp_x2_obj->get_buffered_pdus(rnti, bearer.lcid); } logger.error("Bearer rnti=0x%x, eps-BearerID=%d not found", rnti, eps_bearer_id); return {}; @@ -81,34 +81,26 @@ private: srslog::basic_logger& logger; gtpu* gtpu_obj = nullptr; pdcp* pdcp_obj = nullptr; - pdcp* pdcp_nr_obj = nullptr; + pdcp_interface_gtpu* pdcp_x2_obj = nullptr; enb_bearer_manager* bearers = nullptr; }; enb_stack_lte::enb_stack_lte(srslog::sink& log_sink) : thread("STACK"), mac_logger(srslog::fetch_basic_logger("MAC", log_sink)), - mac_nr_logger(srslog::fetch_basic_logger("MAC-NR", log_sink)), rlc_logger(srslog::fetch_basic_logger("RLC", log_sink, false)), - rlc_nr_logger(srslog::fetch_basic_logger("RLC-NR", log_sink, false)), pdcp_logger(srslog::fetch_basic_logger("PDCP", log_sink, false)), - pdcp_nr_logger(srslog::fetch_basic_logger("PDCP-NR", log_sink, false)), rrc_logger(srslog::fetch_basic_logger("RRC", log_sink, false)), - rrc_nr_logger(srslog::fetch_basic_logger("RRC-NR", log_sink, false)), s1ap_logger(srslog::fetch_basic_logger("S1AP", log_sink, false)), gtpu_logger(srslog::fetch_basic_logger("GTPU", log_sink, false)), stack_logger(srslog::fetch_basic_logger("STCK", log_sink, false)), task_sched(512, 128), pdcp(&task_sched, pdcp_logger), - pdcp_nr(&task_sched, pdcp_nr_logger), mac(&task_sched, mac_logger), - mac_nr(&task_sched), rlc(rlc_logger), - rlc_nr(rlc_nr_logger), gtpu(&task_sched, gtpu_logger, &rx_sockets), s1ap(&task_sched, s1ap_logger, &rx_sockets), rrc(&task_sched, bearers), - rrc_nr(&task_sched), mac_pcap(), pending_stack_metrics(64) { @@ -131,30 +123,11 @@ std::string enb_stack_lte::get_type() int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_, phy_interface_stack_lte* phy_, - phy_interface_stack_nr* phy_nr_) -{ - phy_nr = phy_nr_; - if (init(args_, rrc_cfg_, phy_)) { - return SRSRAN_ERROR; - } - - return SRSRAN_SUCCESS; -} - -int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_, phy_interface_stack_lte* phy_) -{ - phy = phy_; - if (init(args_, rrc_cfg_)) { - return SRSRAN_ERROR; - } - - return SRSRAN_SUCCESS; -} - -int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_) + x2_interface* x2_) { args = args_; rrc_cfg = rrc_cfg_; + phy = phy_; // Init RNTI and bearer memory pools reserve_rnti_memblocks(args.mac.nof_prealloc_ues); @@ -163,25 +136,17 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_) // setup logging for each layer mac_logger.set_level(srslog::str_to_basic_level(args.log.mac_level)); - mac_nr_logger.set_level(srslog::str_to_basic_level(args.log.mac_level)); rlc_logger.set_level(srslog::str_to_basic_level(args.log.rlc_level)); - rlc_nr_logger.set_level(srslog::str_to_basic_level(args.log.rlc_level)); pdcp_logger.set_level(srslog::str_to_basic_level(args.log.pdcp_level)); - pdcp_nr_logger.set_level(srslog::str_to_basic_level(args.log.pdcp_level)); rrc_logger.set_level(srslog::str_to_basic_level(args.log.rrc_level)); - rrc_nr_logger.set_level(srslog::str_to_basic_level(args.log.rrc_level)); gtpu_logger.set_level(srslog::str_to_basic_level(args.log.gtpu_level)); s1ap_logger.set_level(srslog::str_to_basic_level(args.log.s1ap_level)); stack_logger.set_level(srslog::str_to_basic_level(args.log.stack_level)); mac_logger.set_hex_dump_max_size(args.log.mac_hex_limit); - mac_nr_logger.set_hex_dump_max_size(args.log.mac_hex_limit); rlc_logger.set_hex_dump_max_size(args.log.rlc_hex_limit); - rlc_nr_logger.set_hex_dump_max_size(args.log.rlc_hex_limit); pdcp_logger.set_hex_dump_max_size(args.log.pdcp_hex_limit); - pdcp_nr_logger.set_hex_dump_max_size(args.log.pdcp_hex_limit); rrc_logger.set_hex_dump_max_size(args.log.rrc_hex_limit); - rrc_nr_logger.set_hex_dump_max_size(args.log.rrc_hex_limit); gtpu_logger.set_hex_dump_max_size(args.log.gtpu_hex_limit); s1ap_logger.set_hex_dump_max_size(args.log.s1ap_hex_limit); stack_logger.set_hex_dump_max_size(args.log.stack_hex_limit); @@ -209,7 +174,7 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_) sync_task_queue = task_sched.make_task_queue(args.sync_queue_size); // setup bearer managers - gtpu_adapter.reset(new gtpu_pdcp_adapter(stack_logger, &pdcp, &pdcp_nr, >pu, bearers)); + gtpu_adapter.reset(new gtpu_pdcp_adapter(stack_logger, &pdcp, x2_, >pu, bearers)); // Init all LTE layers if (!mac.init(args.mac, rrc_cfg.cell_list, phy, &rlc, &rrc)) { @@ -218,7 +183,7 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_) } rlc.init(&pdcp, &rrc, &mac, task_sched.get_timer_handler()); pdcp.init(&rlc, &rrc, gtpu_adapter.get()); - if (rrc.init(rrc_cfg, phy, &mac, &rlc, &pdcp, &s1ap, >pu, &rrc_nr) != SRSRAN_SUCCESS) { + if (rrc.init(rrc_cfg, phy, &mac, &rlc, &pdcp, &s1ap, >pu, x2_) != SRSRAN_SUCCESS) { stack_logger.error("Couldn't initialize RRC"); return SRSRAN_ERROR; } @@ -227,25 +192,6 @@ 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.fixed_dl_mcs = 28; - mac_args.fixed_ul_mcs = 10; - mac_args.pcap = args.mac_pcap; - mac_args.pcap.filename = "/tmp/enb_mac_nr.pcap"; - if (mac_nr.init(mac_args, phy_nr, 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, phy_nr, &mac_nr, &rlc_nr, &pdcp_nr, nullptr, nullptr, &rrc) != SRSRAN_SUCCESS) { - stack_logger.error("Couldn't initialize RRC-NR"); - return SRSRAN_ERROR; - } - rlc_nr.init(&pdcp_nr, &rrc_nr, &mac_nr, task_sched.get_timer_handler()); - pdcp_nr.init(&rlc_nr, &rrc_nr, gtpu_adapter.get()); - 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 f42cd5176..b9c35d903 100644 --- a/srsenb/src/stack/gnb_stack_nr.cc +++ b/srsenb/src/stack/gnb_stack_nr.cc @@ -20,21 +20,25 @@ */ #include "srsenb/hdr/stack/gnb_stack_nr.h" +#include "srsran/common/standard_streams.h" #include "srsran/srsran.h" #include namespace srsenb { -gnb_stack_nr::gnb_stack_nr() : task_sched{512, 128}, thread("gNB"), rlc_logger(srslog::fetch_basic_logger("RLC-NR")) +gnb_stack_nr::gnb_stack_nr(srslog::sink& log_sink) : + task_sched{512, 128}, + thread("gNB"), + mac_logger(srslog::fetch_basic_logger("MAC-NR", log_sink)), + rlc_logger(srslog::fetch_basic_logger("RLC-NR", log_sink, false)), + pdcp_logger(srslog::fetch_basic_logger("PDCP-NR", log_sink, false)), + rrc_logger(srslog::fetch_basic_logger("RRC-NR", log_sink, false)), + stack_logger(srslog::fetch_basic_logger("STCK-NR", log_sink, false)), + mac(&task_sched), + rrc(&task_sched), + pdcp(&task_sched, pdcp_logger), + rlc(rlc_logger) { - m_mac.reset(new mac_nr(&task_sched)); - m_rlc.reset(new rlc_nr("RLC-NR")); - 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(srslog::fetch_basic_logger("GW"))); - // m_gtpu.reset(new srsenb::gtpu()); - ue_task_queue = task_sched.make_task_queue(); sync_task_queue = task_sched.make_task_queue(); gw_task_queue = task_sched.make_task_queue(); @@ -51,46 +55,48 @@ std::string gnb_stack_nr::get_type() return "nr"; } -int gnb_stack_nr::init(const srsenb::stack_args_t& args_, const rrc_nr_cfg_t& rrc_cfg_, phy_interface_stack_nr* phy_) +int gnb_stack_nr::init(const srsenb::stack_args_t& args_, + const rrc_nr_cfg_t& rrc_cfg_, + phy_interface_stack_nr* phy_, + x2_interface* x2_) { + args = args_; + // rrc_cfg = rrc_cfg_; phy = phy_; - if (init(args_, rrc_cfg_)) { - return SRSRAN_ERROR; - } - return SRSRAN_SUCCESS; -} -int gnb_stack_nr::init(const srsenb::stack_args_t& args_, const rrc_nr_cfg_t& rrc_cfg_) -{ - args = args_; + // setup logging + mac_logger.set_level(srslog::str_to_basic_level(args.log.mac_level)); + rlc_logger.set_level(srslog::str_to_basic_level(args.log.rlc_level)); + pdcp_logger.set_level(srslog::str_to_basic_level(args.log.pdcp_level)); + rrc_logger.set_level(srslog::str_to_basic_level(args.log.rrc_level)); + stack_logger.set_level(srslog::str_to_basic_level(args.log.stack_level)); - // verify configuration correctness - // gtpu_log.init("GTPU", logger); - // gtpu_log.set_level(args.log.gtpu_level); - // gtpu_log.set_hex_limit(args.log.gtpu_hex_limit); + mac_logger.set_hex_dump_max_size(args.log.mac_hex_limit); + rlc_logger.set_hex_dump_max_size(args.log.rlc_hex_limit); + pdcp_logger.set_hex_dump_max_size(args.log.pdcp_hex_limit); + rrc_logger.set_hex_dump_max_size(args.log.rrc_hex_limit); + stack_logger.set_hex_dump_max_size(args.log.stack_hex_limit); // Init all layers mac_nr_args_t mac_args = {}; + mac_args.fixed_dl_mcs = 28; + mac_args.fixed_ul_mcs = 10; mac_args.pcap = args.mac_pcap; - 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); - m_rlc->init(m_pdcp.get(), m_rrc.get(), m_mac.get(), task_sched.get_timer_handler()); - - pdcp_nr_args_t pdcp_args = {}; - pdcp_args.log_level = args.log.pdcp_level; - 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(), nullptr, nullptr, nullptr, nullptr, nullptr); + mac_args.pcap.filename = "/tmp/enb_mac_nr.pcap"; + if (mac.init(mac_args, phy, nullptr, &rlc, &rrc) != SRSRAN_SUCCESS) { + stack_logger.error("Couldn't initialize MAC-NR"); + return SRSRAN_ERROR; + } - m_sdap->init(m_pdcp.get(), nullptr, m_gw.get()); + rlc.init(&pdcp, &rrc, &mac, task_sched.get_timer_handler()); + pdcp.init(&rlc, &rrc, nullptr); - srsue::gw_args_t gw_args = {}; - m_gw->init(gw_args, this); + if (rrc.init(rrc_cfg_, phy, &mac, &rlc, &pdcp, nullptr, nullptr, x2_) != SRSRAN_SUCCESS) { + stack_logger.error("Couldn't initialize RRC"); + return SRSRAN_ERROR; + } - // TODO: add NGAP + // TODO: add SDAP, NGAP // m_gtpu->init(args.s1ap.gtp_bind_addr, args.s1ap.mme_addr, // args.expert.m1u_multiaddr, args.expert.m1u_if_addr, nullptr, >pu_log, // args.expert.enable_mbsfn); @@ -105,11 +111,9 @@ int gnb_stack_nr::init(const srsenb::stack_args_t& args_, const rrc_nr_cfg_t& rr void gnb_stack_nr::stop() { if (running) { - m_gw->stop(); - // m_gtpu->stop(); - m_rrc->stop(); - m_pdcp->stop(); - m_mac->stop(); + rrc.stop(); + pdcp.stop(); + mac.stop(); srsran::get_background_workers().stop(); running = false; @@ -129,13 +133,12 @@ void gnb_stack_nr::run_thread() } } -void gnb_stack_nr::run_tti(uint32_t tti) +void gnb_stack_nr::tti_clock() { - current_tti = tti; - sync_task_queue.push([this, tti]() { run_tti_impl(tti); }); + sync_task_queue.push([this]() { tti_clock_impl(); }); } -void gnb_stack_nr::run_tti_impl(uint32_t tti) +void gnb_stack_nr::tti_clock_impl() { // m_ngap->run_tti(); task_sched.tic(); @@ -153,8 +156,8 @@ void gnb_stack_nr::process_pdus() bool gnb_stack_nr::get_metrics(srsenb::stack_metrics_t* metrics) { - m_mac->get_metrics(metrics->mac); - m_rrc->get_metrics(metrics->rrc); + mac.get_metrics(metrics->mac); + rrc.get_metrics(metrics->rrc); return true; } @@ -170,25 +173,28 @@ bool gnb_stack_nr::has_active_radio_bearer(uint32_t eps_bearer_id) } int gnb_stack_nr::slot_indication(const srsran_slot_cfg_t& slot_cfg) { - return m_mac->slot_indication(slot_cfg); + return mac.slot_indication(slot_cfg); } int gnb_stack_nr::get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) { - return m_mac->get_dl_sched(slot_cfg, dl_sched); + return mac.get_dl_sched(slot_cfg, dl_sched); } int gnb_stack_nr::get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) { - return m_mac->get_ul_sched(slot_cfg, ul_sched); + return mac.get_ul_sched(slot_cfg, ul_sched); } int gnb_stack_nr::pucch_info(const srsran_slot_cfg_t& slot_cfg, const mac_interface_phy_nr::pucch_info_t& pucch_info) { - return m_mac->pucch_info(slot_cfg, pucch_info); + return mac.pucch_info(slot_cfg, pucch_info); } int gnb_stack_nr::pusch_info(const srsran_slot_cfg_t& slot_cfg, mac_interface_phy_nr::pusch_info_t& pusch_info) { - return m_mac->pusch_info(slot_cfg, pusch_info); + return mac.pusch_info(slot_cfg, pusch_info); } -void gnb_stack_nr::rach_detected(const rach_info_t& rach_info) {} +void gnb_stack_nr::rach_detected(const rach_info_t& rach_info) +{ + mac.rach_detected(rach_info); +} -} // namespace srsenb +} // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc index c893f022d..e28eb391d 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc @@ -46,8 +46,8 @@ bwp_params::bwp_params(const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_, ui uint32_t nof_slots = SRSRAN_NSLOTS_PER_FRAME_NR(cfg.numerology_idx); for (size_t sl = 0; sl < nof_slots; ++sl) { slot_cfg sl_cfg{}; - sl_cfg.is_dl = srsran_tdd_nr_is_dl(&cell_cfg.tdd, cfg.numerology_idx, sl); - sl_cfg.is_ul = srsran_tdd_nr_is_ul(&cell_cfg.tdd, cfg.numerology_idx, sl); + sl_cfg.is_dl = srsran_duplex_nr_is_dl(&cell_cfg.duplex, cfg.numerology_idx, sl); + sl_cfg.is_ul = srsran_duplex_nr_is_ul(&cell_cfg.duplex, cfg.numerology_idx, sl); slots.push_back(sl_cfg); } diff --git a/srsenb/src/stack/mac/nr/sched_nr_ue.cc b/srsenb/src/stack/mac/nr/sched_nr_ue.cc index e85410115..711d5cccc 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_ue.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_ue.cc @@ -70,15 +70,15 @@ slot_ue ue_carrier::try_reserve(slot_point pdcch_slot, sfu.dl_pending_bytes = dl_pending_bytes; sfu.ul_pending_bytes = ul_pending_bytes; - const srsran_tdd_config_nr_t& tdd_cfg = cell_params.cell_cfg.tdd; - if (srsran_tdd_nr_is_dl(&tdd_cfg, 0, sfu.pdsch_slot.slot_idx())) { + const srsran_duplex_config_nr_t& tdd_cfg = cell_params.cell_cfg.duplex; + if (srsran_duplex_nr_is_dl(&tdd_cfg, 0, sfu.pdsch_slot.slot_idx())) { // If DL enabled sfu.h_dl = harq_ent.find_pending_dl_retx(); if (sfu.h_dl == nullptr and sfu.dl_pending_bytes > 0) { sfu.h_dl = harq_ent.find_empty_dl_harq(); } } - if (srsran_tdd_nr_is_ul(&tdd_cfg, 0, sfu.pusch_slot.slot_idx())) { + if (srsran_duplex_nr_is_ul(&tdd_cfg, 0, sfu.pusch_slot.slot_idx())) { // If UL enabled sfu.h_ul = harq_ent.find_pending_ul_retx(); if (sfu.h_ul == nullptr and sfu.ul_pending_bytes > 0) { diff --git a/srsenb/src/stack/mac/sched_grid.cc b/srsenb/src/stack/mac/sched_grid.cc index 397aa1cfb..d59cf4307 100644 --- a/srsenb/src/stack/mac/sched_grid.cc +++ b/srsenb/src/stack/mac/sched_grid.cc @@ -89,8 +89,15 @@ void sf_grid_t::init(const sched_cell_params_t& cell_params_) pucch_mask.resize(cc_cfg->nof_prb()); pucch_nrb = (cc_cfg->cfg.nrb_pucch > 0) ? (uint32_t)cc_cfg->cfg.nrb_pucch : 0; srsran_pucch_cfg_t pucch_cfg = cell_params_.pucch_cfg_common; - pucch_cfg.n_pucch = cc_cfg->nof_cce_table[SRSRAN_NOF_CFI - 1] - 1 + cc_cfg->cfg.n1pucch_an; - pucch_nrb = std::max(pucch_nrb, srsran_pucch_m(&pucch_cfg, cc_cfg->cfg.cell.cp) / 2 + 1); + uint32_t harq_pucch = 0; + if (cc_cfg->sched_cfg->pucch_harq_max_rb > 0) { + harq_pucch = cc_cfg->sched_cfg->pucch_harq_max_rb; + } else { + pucch_cfg.n_pucch = + cc_cfg->nof_cce_table[cell_params_.sched_cfg->max_nof_ctrl_symbols - 1] - 1 + cc_cfg->cfg.n1pucch_an; + harq_pucch = srsran_pucch_m(&pucch_cfg, cc_cfg->cfg.cell.cp) / 2 + 1; + } + pucch_nrb = std::max(pucch_nrb, harq_pucch); if (pucch_nrb > 0) { pucch_mask.fill(0, pucch_nrb); pucch_mask.fill(cc_cfg->nof_prb() - pucch_nrb, cc_cfg->nof_prb()); diff --git a/srsenb/src/stack/mac/sched_phy_ch/sf_cch_allocator.cc b/srsenb/src/stack/mac/sched_phy_ch/sf_cch_allocator.cc index 8992e2684..6b024c74f 100644 --- a/srsenb/src/stack/mac/sched_phy_ch/sf_cch_allocator.cc +++ b/srsenb/src/stack/mac/sched_phy_ch/sf_cch_allocator.cc @@ -190,6 +190,15 @@ bool sf_cch_allocator::alloc_dfs_node(const alloc_record& record, uint32_t start // PUCCH allocation would collide with other PUCCH/PUSCH grants. Try another CCE position continue; } + int low_rb = node.pucch_n_prb < (int)cc_cfg->cfg.cell.nof_prb / 2 + ? node.pucch_n_prb + : cc_cfg->cfg.cell.nof_prb - node.pucch_n_prb - 1; + if (cc_cfg->sched_cfg->pucch_harq_max_rb > 0 && low_rb >= cc_cfg->sched_cfg->pucch_harq_max_rb) { + // PUCCH allocation would fall outside the maximum allowed PUCCH HARQ region. Try another CCE position + logger.info("Skipping PDCCH allocation for CCE=%d due to PUCCH HARQ falling outside region\n", + node.dci_pos.ncce); + continue; + } } node.current_mask.reset(); diff --git a/srsenb/src/stack/rrc/rrc_nr.cc b/srsenb/src/stack/rrc/rrc_nr.cc index efa728a28..d6432c725 100644 --- a/srsenb/src/stack/rrc/rrc_nr.cc +++ b/srsenb/src/stack/rrc/rrc_nr.cc @@ -501,10 +501,8 @@ void rrc_nr::ue::send_dl_ccch(dl_ccch_msg_s* dl_ccch_msg) } // 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) +int rrc_nr::ue::pack_secondary_cell_group_config_common(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) { - auto& cell_group_cfg_pack = cell_group_cfg; - // RLC for DRB1 (with fixed LCID) cell_group_cfg_pack.rlc_bearer_to_add_mod_list_present = true; cell_group_cfg_pack.rlc_bearer_to_add_mod_list.resize(1); @@ -644,7 +642,6 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec 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; // UL config dedicated @@ -666,19 +663,10 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec sr_res1.sched_request_id = 0; sr_res1.periodicity_and_offset_present = true; sr_res1.periodicity_and_offset.set_sl40(); - sr_res1.periodicity_and_offset.sl40() = 7; sr_res1.res_present = true; - sr_res1.res = 2; // PUCCH resource for SR // DL data ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack_present = true; - ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack.resize(6); - ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[0] = 6; - ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[1] = 5; - ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[2] = 4; - ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[3] = 4; - ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[4] = 4; - ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[5] = 4; // PUCCH Resource for format 1 srsran_pucch_nr_resource_t resource_small = {}; @@ -764,8 +752,8 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec beta_offset_semi_static.beta_offset_ack_idx3_present = true; beta_offset_semi_static.beta_offset_ack_idx3 = 9; beta_offset_semi_static.beta_offset_csi_part1_idx1_present = true; - beta_offset_semi_static.beta_offset_csi_part1_idx2_present = true; beta_offset_semi_static.beta_offset_csi_part1_idx1 = 6; + beta_offset_semi_static.beta_offset_csi_part1_idx2_present = true; beta_offset_semi_static.beta_offset_csi_part1_idx2 = 6; beta_offset_semi_static.beta_offset_csi_part2_idx1_present = true; beta_offset_semi_static.beta_offset_csi_part2_idx1 = 6; @@ -805,10 +793,8 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec nzp_csi_res.res_map.freq_band.nrof_rbs = 52; nzp_csi_res.pwr_ctrl_offset = 0; // Skip pwr_ctrl_offset_ss_present - nzp_csi_res.scrambling_id = 0; nzp_csi_res.periodicity_and_offset_present = true; nzp_csi_res.periodicity_and_offset.set_slots80(); - nzp_csi_res.periodicity_and_offset.slots80() = 0; // optional nzp_csi_res.qcl_info_periodic_csi_rs_present = true; nzp_csi_res.qcl_info_periodic_csi_rs = 0; @@ -819,9 +805,7 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list.resize(1); auto& nzp_csi_res_set = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list[0]; - nzp_csi_res_set.nzp_csi_res_set_id = 0; nzp_csi_res_set.nzp_csi_rs_res.resize(1); - nzp_csi_res_set.nzp_csi_rs_res[0] = 0; // Skip TRS info // CSI report config @@ -835,7 +819,6 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec csi_report.csi_im_res_for_interference = 1; csi_report.report_cfg_type.set_periodic(); csi_report.report_cfg_type.periodic().report_slot_cfg.set_slots80(); - csi_report.report_cfg_type.periodic().report_slot_cfg.slots80() = 8; csi_report.report_cfg_type.periodic().pucch_csi_res_list.resize(1); csi_report.report_cfg_type.periodic().pucch_csi_res_list[0].ul_bw_part_id = 0; csi_report.report_cfg_type.periodic().pucch_csi_res_list[0].pucch_res = 0; // was 17 in orig PCAP @@ -857,11 +840,11 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec // Reconfig with Sync 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 = rnti; - 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.n_timing_advance_offset = + asn1::rrc_nr::serving_cell_cfg_common_s::n_timing_advance_offset_opts::n0; 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; @@ -875,13 +858,7 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec 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 = - 634176; // TODO: calculate from actual DL ARFCN - 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 = - 633928; // TODO: calculate from actual DL ARFCN 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); @@ -905,7 +882,6 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec 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( @@ -982,7 +958,6 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec 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; @@ -1033,12 +1008,181 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec // 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 + return SRSRAN_SUCCESS; +} + +// Helper for the RRC Reconfiguration sender to pack hard-coded config +int rrc_nr::ue::pack_secondary_cell_group_config_fdd(asn1::dyn_octstring& packed_secondary_cell_config) +{ + + auto& cell_group_cfg_pack = cell_group_cfg; + pack_secondary_cell_group_config_common(cell_group_cfg); + + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.first_active_dl_bwp_id = 0; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg_present = true; + + // UL config dedicated + auto& ul_config = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg; + // SR resources + auto& sr_res1 = ul_config.init_ul_bwp.pucch_cfg.setup().sched_request_res_to_add_mod_list[0]; + sr_res1.periodicity_and_offset.sl40() = 4; + sr_res1.res_present = true; + sr_res1.res = 16; // PUCCH resource for SR + + // DL data + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack_present = true; + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack.resize(1); + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[0] = 4; + + // nzp-CSI-RS Resource + auto& nzp_csi_res = + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list[0]; + nzp_csi_res.scrambling_id = 500; + nzp_csi_res.periodicity_and_offset_present = true; + nzp_csi_res.periodicity_and_offset.set_slots80(); + nzp_csi_res.periodicity_and_offset.slots80() = 1; + + // nzp-CSI-RS ResourceSet + auto& nzp_csi_res_set = + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list[0]; + nzp_csi_res_set.nzp_csi_res_set_id = 1; + nzp_csi_res_set.nzp_csi_rs_res[0] = 1; + + // CSI report config + auto& csi_report = + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().csi_report_cfg_to_add_mod_list[0]; + csi_report.report_cfg_type.periodic().report_slot_cfg.slots80() = 5; + + // Reconfig with Sync + 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 = -36; + + // 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.absolute_freq_ssb = + 176210; // TODO: calculate from actual DL ARFCN + + 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(5); + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.absolute_freq_point_a = + 175364; // TODO: calculate from actual DL ARFCN + + // 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 = 16; + + // 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_short_bitmap().from_number(0b1000); + + // 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; +} + +// Helper for the RRC Reconfiguration sender to pack hard-coded config +int rrc_nr::ue::pack_secondary_cell_group_config_tdd(asn1::dyn_octstring& packed_secondary_cell_config) +{ + + auto& cell_group_cfg_pack = cell_group_cfg; + pack_secondary_cell_group_config_common(cell_group_cfg); + + 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; + + // UL config dedicated + auto& ul_config = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg; + // SR resources + auto& sr_res1 = ul_config.init_ul_bwp.pucch_cfg.setup().sched_request_res_to_add_mod_list[0]; + // SR resources + sr_res1.periodicity_and_offset.sl40() = 7; + sr_res1.res_present = true; + sr_res1.res = 2; // PUCCH resource for SR + + // DL data + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack_present = true; + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack.resize(6); + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[0] = 6; + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[1] = 5; + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[2] = 4; + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[3] = 4; + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[4] = 4; + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[5] = 4; + + // nzp-CSI-RS Resource + auto& nzp_csi_res = + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list[0]; + nzp_csi_res.scrambling_id = 0; + nzp_csi_res.periodicity_and_offset_present = true; + nzp_csi_res.periodicity_and_offset.set_slots80(); + nzp_csi_res.periodicity_and_offset.slots80() = 0; + + // nzp-CSI-RS ResourceSet + auto& nzp_csi_res_set = + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list[0]; + nzp_csi_res_set.nzp_csi_res_set_id = 0; + nzp_csi_res_set.nzp_csi_rs_res[0] = 0; + // Skip TRS info + + // CSI report config + auto& csi_report = + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().csi_report_cfg_to_add_mod_list[0]; + csi_report.report_cfg_type.periodic().report_slot_cfg.slots80() = 8; + + // Reconfig with Sync + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.smtc.release(); + + 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; + + // 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.absolute_freq_ssb = + 634176; // TODO: calculate from actual DL ARFCN + + 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 = + 633928; // TODO: calculate from actual DL ARFCN + + 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; + + + // 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; + + // 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); + + // // 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; @@ -1069,8 +1213,8 @@ int rrc_nr::ue::pack_rrc_reconfiguraiton(asn1::dyn_octstring& packed_rrc_reconfi // 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"); + if (pack_secondary_cell_group_config_tdd(recfg_ies.secondary_cell_group) == SRSRAN_ERROR) { + parent->logger.error("Failed to pack TDD RRC Reconfiguration"); return SRSRAN_ERROR; } diff --git a/srsenb/src/stack/rrc/rrc_ue.cc b/srsenb/src/stack/rrc/rrc_ue.cc index cad938aec..e20f8c6d1 100644 --- a/srsenb/src/stack/rrc/rrc_ue.cc +++ b/srsenb/src/stack/rrc/rrc_ue.cc @@ -349,6 +349,7 @@ void rrc::ue::parse_ul_dcch(uint32_t lcid, srsran::unique_byte_buffer_t pdu) case ul_dcch_msg_type_c::c1_c_::types::rrc_conn_reest_complete: save_ul_message(std::move(original_pdu)); handle_rrc_con_reest_complete(&ul_dcch_msg.msg.c1().rrc_conn_reest_complete(), std::move(pdu)); + set_activity_timeout(UE_INACTIVITY_TIMEOUT); set_activity(); break; case ul_dcch_msg_type_c::c1_c_::types::ul_info_transfer: diff --git a/srsenb/src/stack/s1ap/s1ap.cc b/srsenb/src/stack/s1ap/s1ap.cc index 08cd8486c..93d1bb231 100644 --- a/srsenb/src/stack/s1ap/s1ap.cc +++ b/srsenb/src/stack/s1ap/s1ap.cc @@ -61,7 +61,10 @@ asn1::bounded_bitstring<1, 160, true, true> addr_to_asn1(const char* addr_str) { asn1::bounded_bitstring<1, 160, true, true> transport_layer_addr(32); uint8_t addr[4]; - inet_pton(AF_INET, addr_str, addr); + if (inet_pton(AF_INET, addr_str, addr) != 1) { + srsran::console("Invalid addr_str: %s\n", addr_str); + perror("inet_pton"); + } for (uint32_t j = 0; j < 4; ++j) { transport_layer_addr.data()[j] = addr[3 - j]; } @@ -1735,9 +1738,17 @@ void s1ap::ue::get_erab_addr(uint16_t erab_id, transp_addr_t& transp_addr, asn1: transp_addr.resize(32); uint8_t addr[4]; if (!s1ap_ptr->args.gtp_advertise_addr.empty()) { - inet_pton(AF_INET, s1ap_ptr->args.gtp_advertise_addr.c_str(), addr); + if (inet_pton(AF_INET, s1ap_ptr->args.gtp_advertise_addr.c_str(), addr) != 1) { + logger.error("Invalid gtp_advertise_addr: %s", s1ap_ptr->args.gtp_advertise_addr.c_str()); + srsran::console("Invalid gtp_advertise_addr: %s\n", s1ap_ptr->args.gtp_advertise_addr.c_str()); + perror("inet_pton"); + } } else { - inet_pton(AF_INET, s1ap_ptr->args.gtp_bind_addr.c_str(), addr); + if (inet_pton(AF_INET, s1ap_ptr->args.gtp_bind_addr.c_str(), addr) != 1) { + logger.error("Invalid gtp_bind_addr: %s", s1ap_ptr->args.gtp_bind_addr.c_str()); + srsran::console("Invalid gtp_bind_addr: %s\n", s1ap_ptr->args.gtp_bind_addr.c_str()); + perror("inet_pton"); + } } for (uint32_t j = 0; j < 4; ++j) { transp_addr.data()[j] = addr[3 - j]; diff --git a/srsenb/src/stack/upper/gtpu.cc b/srsenb/src/stack/upper/gtpu.cc index 3747ddc03..bfc4a59c9 100644 --- a/srsenb/src/stack/upper/gtpu.cc +++ b/srsenb/src/stack/upper/gtpu.cc @@ -403,13 +403,9 @@ int gtpu::init(const gtpu_args_t& gtpu_args, pdcp_interface_gtpu* pdcp_) struct sockaddr_in bindaddr; bzero(&bindaddr, sizeof(struct sockaddr_in)); - bindaddr.sin_family = AF_INET; - bindaddr.sin_addr.s_addr = inet_addr(gtp_bind_addr.c_str()); - bindaddr.sin_port = htons(GTPU_PORT); - - if (bind(fd, (struct sockaddr*)&bindaddr, sizeof(struct sockaddr_in))) { + // Bind socket + if (not net_utils::bind_addr(fd, gtp_bind_addr.c_str(), GTPU_PORT, &bindaddr)) { snprintf(errbuf, sizeof(errbuf), "%s", strerror(errno)); - logger.error("Failed to bind on address %s, port %d: %s", gtp_bind_addr.c_str(), int(GTPU_PORT), errbuf); srsran::console("Failed to bind on address %s, port %d: %s\n", gtp_bind_addr.c_str(), int(GTPU_PORT), errbuf); return SRSRAN_ERROR; } @@ -934,8 +930,20 @@ bool gtpu::m1u_handler::init(std::string m1u_multiaddr_, std::string m1u_if_addr /* Send an ADD MEMBERSHIP message via setsockopt */ struct ip_mreq mreq {}; - mreq.imr_multiaddr.s_addr = inet_addr(m1u_multiaddr.c_str()); // Multicast address of the service - mreq.imr_interface.s_addr = inet_addr(m1u_if_addr.c_str()); // Address of the IF the socket will listen to. + // Multicast address of the service + if (inet_pton(AF_INET, m1u_multiaddr.c_str(), &mreq.imr_multiaddr) != 1) { + logger.error("Invalid m1u_multiaddr: %s", m1u_multiaddr.c_str()); + srsran::console("Invalid m1u_multiaddr: %s\n", m1u_multiaddr.c_str()); + perror("inet_pton"); + return false; + } + // Address of the IF the socket will listen to. + if (inet_pton(AF_INET, m1u_if_addr.c_str(), &mreq.imr_interface) != 1) { + logger.error("Invalid m1u_if_addr: %s", m1u_if_addr.c_str()); + srsran::console("Invalid m1u_if_addr: %s\n", m1u_if_addr.c_str()); + perror("inet_pton"); + return false; + } if (setsockopt(m1u_sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { logger.error("Register musticast group for M1-U"); logger.error("M1-U infterface IP: %s, M1-U Multicast Address %s", m1u_if_addr.c_str(), m1u_multiaddr.c_str()); diff --git a/srsenb/test/mac/nr/CMakeLists.txt b/srsenb/test/mac/nr/CMakeLists.txt index b7e0e59be..1dfc11981 100644 --- a/srsenb/test/mac/nr/CMakeLists.txt +++ b/srsenb/test/mac/nr/CMakeLists.txt @@ -27,7 +27,7 @@ target_link_libraries(sched_nr_test srsran_common ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) -add_test(sched_nr_test sched_nr_test) +add_nr_test(sched_nr_test sched_nr_test) add_executable(sched_nr_prb_test sched_nr_prb_test.cc) target_link_libraries(sched_nr_prb_test @@ -35,8 +35,8 @@ target_link_libraries(sched_nr_prb_test srsran_common ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) -add_test(sched_nr_prb_test sched_nr_prb_test) +add_nr_test(sched_nr_prb_test sched_nr_prb_test) add_executable(sched_nr_rar_test sched_nr_rar_test.cc) target_link_libraries(sched_nr_rar_test srsgnb_mac sched_nr_test_suite srsran_common) -add_test(sched_nr_rar_test sched_nr_rar_test) \ No newline at end of file +add_nr_test(sched_nr_rar_test sched_nr_rar_test) \ No newline at end of file diff --git a/srsenb/test/mac/nr/sched_nr_cfg_generators.h b/srsenb/test/mac/nr/sched_nr_cfg_generators.h index 1a4bbcc6a..d6fddafe4 100644 --- a/srsenb/test/mac/nr/sched_nr_cfg_generators.h +++ b/srsenb/test/mac/nr/sched_nr_cfg_generators.h @@ -45,7 +45,7 @@ inline sched_nr_interface::cell_cfg_t get_default_cell_cfg( sched_nr_interface::cell_cfg_t cell_cfg{}; cell_cfg.carrier = phy_cfg.carrier; - cell_cfg.tdd = phy_cfg.tdd; + cell_cfg.duplex = phy_cfg.duplex; cell_cfg.bwps.resize(1); cell_cfg.bwps[0].pdcch = phy_cfg.pdcch; diff --git a/srsenb/test/mac/nr/sched_nr_test.cc b/srsenb/test/mac/nr/sched_nr_test.cc index b34ed0082..b7923f3af 100644 --- a/srsenb/test/mac/nr/sched_nr_test.cc +++ b/srsenb/test/mac/nr/sched_nr_test.cc @@ -91,7 +91,7 @@ void sched_nr_cfg_serialized_test() uint32_t max_nof_ttis = 1000, nof_sectors = 4; task_job_manager tasks; - sched_nr_interface::sched_cfg_t cfg; + sched_nr_interface::sched_cfg_t cfg; cfg.auto_refill_buffer = true; std::vector cells_cfg = get_default_cells_cfg(nof_sectors); @@ -120,7 +120,7 @@ void sched_nr_cfg_serialized_test() sched_nr_cc_output_res_t out{slot_tx, cc, &dl_res, &ul_res}; sched_tester.update(out); tasks.finish_cc(slot_rx, dl_res, ul_res); - TESTASSERT(not srsran_tdd_nr_is_dl(&cells_cfg[cc].tdd, 0, (slot_tx).slot_idx()) or + TESTASSERT(not srsran_duplex_nr_is_dl(&cells_cfg[cc].duplex, 0, (slot_tx).slot_idx()) or dl_res.dl_sched.pdcch_dl.size() == 1); } } diff --git a/srsenb/test/phy/enb_phy_test.cc b/srsenb/test/phy/enb_phy_test.cc index c0b7c8c91..d90a87b24 100644 --- a/srsenb/test/phy/enb_phy_test.cc +++ b/srsenb/test/phy/enb_phy_test.cc @@ -719,7 +719,7 @@ public: return SRSRAN_SUCCESS; } void set_sched_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs) override { notify_set_sched_dl_tti_mask(); } - void tti_clock() override { notify_tti_clock(); } + void tti_clock() { notify_tti_clock(); } int run_tti(bool enable_assert) { std::lock_guard lock(phy_mac_mutex); @@ -1159,7 +1159,7 @@ typedef std::unique_ptr unique_dummy_ue_phy_t; typedef std::unique_ptr unique_srsenb_phy_t; -class phy_test_bench +class phy_test_bench : public srsenb::enb_time_interface { public: struct args_t { @@ -1337,7 +1337,7 @@ public: stack->set_active_cell_list(args.ue_cell_list); /// Initiate eNb PHY with the given RNTI - if (enb_phy->init(phy_args, phy_cfg, radio.get(), stack.get()) < 0) { + if (enb_phy->init(phy_args, phy_cfg, radio.get(), stack.get(), this) < 0) { return SRSRAN_ERROR; } enb_phy->set_config(args.rnti, phy_rrc_cfg); @@ -1359,7 +1359,7 @@ public: enb_phy->stop(); } - ~phy_test_bench() = default; + virtual ~phy_test_bench() = default; int run_tti() { @@ -1431,6 +1431,11 @@ public: return ret; } + + void tti_clock() final + { + // nothing to do + } }; typedef std::unique_ptr unique_phy_test_bench; diff --git a/srsepc/src/mbms-gw/mbms-gw.cc b/srsepc/src/mbms-gw/mbms-gw.cc index 95d7c56cc..ce4e75f9f 100644 --- a/srsepc/src/mbms-gw/mbms-gw.cc +++ b/srsepc/src/mbms-gw/mbms-gw.cc @@ -21,6 +21,7 @@ #include "srsepc/hdr/mbms-gw/mbms-gw.h" #include "srsran/common/standard_streams.h" +#include "srsran/common/network_utils.h" #include "srsran/upper/gtpu.h" #include #include @@ -161,9 +162,12 @@ int mbms_gw::init_sgi_mb_if(mbms_gw_args_t* args) // Set IP of the interface struct sockaddr_in* addr = (struct sockaddr_in*)&ifr.ifr_addr; - addr->sin_family = AF_INET; - addr->sin_addr.s_addr = inet_addr(args->sgi_mb_if_addr.c_str()); - addr->sin_port = 0; + + if (not srsran::net_utils::set_sockaddr(addr, args->sgi_mb_if_addr.c_str(), 0)) { + m_logger.error("Invalid sgi_mb_if_addr: %s", args->sgi_mb_if_addr.c_str()); + srsran::console("Invalid sgi_mb_if_addr: %s\n", args->sgi_mb_if_addr.c_str()); + return SRSRAN_ERROR_CANT_START; + } if (ioctl(sgi_mb_sock, SIOCSIFADDR, &ifr) < 0) { m_logger.error( @@ -174,7 +178,12 @@ int mbms_gw::init_sgi_mb_if(mbms_gw_args_t* args) } ifr.ifr_netmask.sa_family = AF_INET; - ((struct sockaddr_in*)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr(args->sgi_mb_if_mask.c_str()); + if (inet_pton(ifr.ifr_netmask.sa_family, args->sgi_mb_if_mask.c_str(), &((struct sockaddr_in*)&ifr.ifr_netmask)->sin_addr.s_addr ) != 1) { + m_logger.error("Invalid sgi_mb_if_mask: %s", args->sgi_mb_if_mask.c_str()); + srsran::console("Invalid sgi_mb_if_mask: %s\n", args->sgi_mb_if_mask.c_str()); + perror("inet_pton"); + return SRSRAN_ERROR_CANT_START; + } if (ioctl(sgi_mb_sock, SIOCSIFNETMASK, &ifr) < 0) { m_logger.error("Failed to set TUN interface Netmask. Error: %s", strerror(errno)); close(m_sgi_mb_if); @@ -210,7 +219,12 @@ int mbms_gw::init_m1_u(mbms_gw_args_t* args) /* Set local interface for outbound multicast packets*/ /* The IP must be associated with a local multicast capable interface */ struct in_addr local_if; - local_if.s_addr = inet_addr(args->m1u_multi_if.c_str()); + if (inet_pton(AF_INET, args->m1u_multi_if.c_str(), &local_if.s_addr) != 1) { + m_logger.error("Invalid m1u_multi_if: %s", args->m1u_multi_if.c_str()); + srsran::console("Invalid m1u_multi_if: %s\n", args->m1u_multi_if.c_str()); + perror("inet_pton"); + return SRSRAN_ERROR_CANT_START; + } if (setsockopt(m_m1u, IPPROTO_IP, IP_MULTICAST_IF, (char*)&local_if, sizeof(struct in_addr)) < 0) { m_logger.error("Error %s setting multicast interface %s.", strerror(errno), args->m1u_multi_if.c_str()); return SRSRAN_ERROR_CANT_START; @@ -227,7 +241,12 @@ int mbms_gw::init_m1_u(mbms_gw_args_t* args) bzero(&m_m1u_multi_addr, sizeof(m_m1u_multi_addr)); m_m1u_multi_addr.sin_family = AF_INET; m_m1u_multi_addr.sin_port = htons(GTPU_RX_PORT + 1); - m_m1u_multi_addr.sin_addr.s_addr = inet_addr(args->m1u_multi_addr.c_str()); + if (inet_pton(m_m1u_multi_addr.sin_family, args->m1u_multi_addr.c_str(), &m_m1u_multi_addr.sin_addr.s_addr) != 1) { + m_logger.error("Invalid m1u_multi_addr: %s", args->m1u_multi_addr.c_str()); + srsran::console("Invalid m1u_multi_addr: %s\n", args->m1u_multi_addr.c_str()); + perror("inet_pton"); + return SRSRAN_ERROR_CANT_START; + } m_logger.info("Initialized M1-U"); return SRSRAN_SUCCESS; diff --git a/srsepc/src/mme/nas.cc b/srsepc/src/mme/nas.cc index bc582be5d..9d950884f 100644 --- a/srsepc/src/mme/nas.cc +++ b/srsepc/src/mme/nas.cc @@ -1547,7 +1547,12 @@ bool nas::pack_attach_accept(srsran::byte_buffer_t* nas_buffer) act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].len = 4; struct sockaddr_in dns_addr; - inet_pton(AF_INET, m_dns.c_str(), &(dns_addr.sin_addr)); + if (inet_pton(AF_INET, m_dns.c_str(), &(dns_addr.sin_addr)) != 1) { + m_logger.error("Invalid m_dns: %s", m_dns.c_str()); + srsran::console("Invalid m_dns: %s\n", m_dns.c_str()); + perror("inet_pton"); + return false; + } memcpy(act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].contents, &dns_addr.sin_addr.s_addr, 4); // Make sure all unused options are set to false diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 6f6550c09..1fdc89d39 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -23,6 +23,7 @@ #include "srsran/asn1/gtpc.h" #include "srsran/common/bcd_helpers.h" #include "srsran/common/liblte_security.h" +#include "srsran/common/network_utils.h" #include #include // for printing uint64_t #include @@ -95,7 +96,7 @@ int s1ap::init(const s1ap_args_t& s1ap_args) m_pcap.open(s1ap_args.pcap_filename.c_str()); } m_logger.info("S1AP Initialized"); - return 0; + return SRSRAN_SUCCESS; } void s1ap::stop() @@ -152,7 +153,7 @@ int s1ap::enb_listen() sock_fd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); if (sock_fd == -1) { srsran::console("Could not create SCTP socket\n"); - return -1; + return SRSRAN_ERROR; } // Sets the data_io_event to be able to use sendrecv_info @@ -163,20 +164,21 @@ int s1ap::enb_listen() if (setsockopt(sock_fd, IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof(evnts))) { close(sock_fd); srsran::console("Subscribing to sctp_data_io_events failed\n"); - return -1; + return SRSRAN_ERROR; } // S1-MME bind bzero(&s1mme_addr, sizeof(s1mme_addr)); - s1mme_addr.sin_family = AF_INET; - inet_pton(AF_INET, m_s1ap_args.mme_bind_addr.c_str(), &(s1mme_addr.sin_addr)); - s1mme_addr.sin_port = htons(S1MME_PORT); - err = bind(sock_fd, (struct sockaddr*)&s1mme_addr, sizeof(s1mme_addr)); - if (err != 0) { + if (not srsran::net_utils::set_sockaddr(&s1mme_addr, m_s1ap_args.mme_bind_addr.c_str(), S1MME_PORT)) { + m_logger.error("Invalid mme_bind_addr: %s", m_s1ap_args.mme_bind_addr.c_str()); + srsran::console("Invalid mme_bind_addr: %s\n", m_s1ap_args.mme_bind_addr.c_str()); + return SRSRAN_ERROR; + } + if (not srsran::net_utils::bind_addr(sock_fd, s1mme_addr)) { close(sock_fd); m_logger.error("Error binding SCTP socket"); srsran::console("Error binding SCTP socket\n"); - return -1; + return SRSRAN_ERROR; } // Listen for connections @@ -185,7 +187,7 @@ int s1ap::enb_listen() close(sock_fd); m_logger.error("Error in SCTP socket listen"); srsran::console("Error in SCTP socket listen\n"); - return -1; + return SRSRAN_ERROR; } return sock_fd; @@ -565,7 +567,7 @@ uint64_t s1ap::find_imsi_from_m_tmsi(uint32_t m_tmsi) return it->second; } else { m_logger.debug("Could not find IMSI from M-TMSI 0x%x", m_tmsi); - return 0; + return SRSRAN_SUCCESS; } } diff --git a/srsepc/src/spgw/gtpc.cc b/srsepc/src/spgw/gtpc.cc index 809b1ddaf..b3680a701 100644 --- a/srsepc/src/spgw/gtpc.cc +++ b/srsepc/src/spgw/gtpc.cc @@ -550,7 +550,10 @@ int spgw::gtpc::init_ue_ip(spgw_args_t* args, const std::map::const_iterator iter = ip_to_imsi.begin(); iter != ip_to_imsi.end(); ++iter) { struct in_addr in_addr; - in_addr.s_addr = inet_addr(iter->first.c_str()); + if (inet_pton(AF_INET, iter->first.c_str(), &in_addr.s_addr) != 1) { + perror("inet_pton"); + return SRSRAN_ERROR; + } if (!m_imsi_to_ip.insert(std::make_pair(iter->second, in_addr)).second) { m_logger.error( "SPGW: duplicate imsi %015" PRIu64 " for static ip address %s.", iter->second, iter->first.c_str()); @@ -562,7 +565,13 @@ int spgw::gtpc::init_ue_ip(spgw_args_t* args, const std::mapsgi_if_addr.c_str()) + htonl(n); + if (inet_pton(AF_INET, args->sgi_if_addr.c_str(), &ue_addr.s_addr) != 1) { + m_logger.error("Invalid sgi_if_addr: %s", args->sgi_if_addr.c_str()); + srsran::console("Invalid sgi_if_addr: %s\n", args->sgi_if_addr.c_str()); + perror("inet_pton"); + return SRSRAN_ERROR; + } + ue_addr.s_addr = ue_addr.s_addr + htonl(n); std::map::const_iterator iter = ip_to_imsi.find(inet_ntoa(ue_addr)); if (iter != ip_to_imsi.end()) { diff --git a/srsepc/src/spgw/gtpu.cc b/srsepc/src/spgw/gtpu.cc index 5bb074ed5..b8df8e53a 100644 --- a/srsepc/src/spgw/gtpu.cc +++ b/srsepc/src/spgw/gtpu.cc @@ -22,6 +22,7 @@ #include "srsepc/hdr/spgw/gtpu.h" #include "srsepc/hdr/mme/mme_gtpc.h" #include "srsran/common/string_helpers.h" +#include "srsran/common/network_utils.h" #include "srsran/upper/gtpu.h" #include #include @@ -140,9 +141,11 @@ int spgw::gtpu::init_sgi(spgw_args_t* args) // Set IP of the interface struct sockaddr_in* addr = (struct sockaddr_in*)&ifr.ifr_addr; - addr->sin_family = AF_INET; - addr->sin_addr.s_addr = inet_addr(args->sgi_if_addr.c_str()); - addr->sin_port = 0; + if (not srsran::net_utils::set_sockaddr(addr, args->sgi_if_addr.c_str(), 0)) { + m_logger.error("Invalid sgi_if_addr: %s", args->sgi_if_addr.c_str()); + srsran::console("Invalid sgi_if_addr: %s\n", args->sgi_if_addr.c_str()); + return SRSRAN_ERROR_CANT_START; + } if (ioctl(sgi_sock, SIOCSIFADDR, &ifr) < 0) { m_logger.error( @@ -152,8 +155,11 @@ int spgw::gtpu::init_sgi(spgw_args_t* args) return SRSRAN_ERROR_CANT_START; } - ifr.ifr_netmask.sa_family = AF_INET; - ((struct sockaddr_in*)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr("255.255.255.0"); + ifr.ifr_netmask.sa_family = AF_INET; + if (inet_pton(ifr.ifr_netmask.sa_family , "255.255.255.0", &((struct sockaddr_in*)&ifr.ifr_netmask)->sin_addr.s_addr) != 1) { + perror("inet_pton"); + return false; + } if (ioctl(sgi_sock, SIOCSIFNETMASK, &ifr) < 0) { m_logger.error("Failed to set TUN interface Netmask. Error: %s", strerror(errno)); close(m_sgi); @@ -179,7 +185,11 @@ int spgw::gtpu::init_s1u(spgw_args_t* args) // Bind the socket m_s1u_addr.sin_family = AF_INET; - m_s1u_addr.sin_addr.s_addr = inet_addr(args->gtpu_bind_addr.c_str()); + if (inet_pton(m_s1u_addr.sin_family, args->gtpu_bind_addr.c_str(), &m_s1u_addr.sin_addr.s_addr) != 1) { + m_logger.error("Invalid gtpu_bind_addr: %s", args->gtpu_bind_addr.c_str()); + srsran::console("Invalid gtpu_bind_addr: %s\n", args->gtpu_bind_addr.c_str()); + return SRSRAN_ERROR_CANT_START; + } m_s1u_addr.sin_port = htons(GTPU_RX_PORT); if (bind(m_s1u, (struct sockaddr*)&m_s1u_addr, sizeof(struct sockaddr_in))) { diff --git a/srsue/hdr/phy/nr/state.h b/srsue/hdr/phy/nr/state.h index 3c22f4c91..f690dbfb8 100644 --- a/srsue/hdr/phy/nr/state.h +++ b/srsue/hdr/phy/nr/state.h @@ -491,8 +491,8 @@ public: // Compute synch metrics and report it to the PHY state sync_metrics_t new_sync_metrics = {}; - new_sync_metrics.cfo = new_meas.cfo_hz; - set_sync_metrics(sync_metrics); + new_sync_metrics.cfo = new_meas.cfo_hz + ul_ext_cfo_hz; + set_sync_metrics(new_sync_metrics); // Convert to CSI channel measurement and report new NZP-CSI-RS measurement to the PHY state srsran_csi_channel_measurements_t measurements = {}; @@ -508,11 +508,10 @@ public: trs_measurements_mutex.lock(); trs_measurements.rsrp_dB = SRSRAN_VEC_SAFE_EMA(new_meas.rsrp_dB, trs_measurements.rsrp_dB, args.trs_epre_ema_alpha); trs_measurements.epre_dB = SRSRAN_VEC_SAFE_EMA(new_meas.epre_dB, trs_measurements.epre_dB, args.trs_rsrp_ema_alpha); + trs_measurements.snr_dB = SRSRAN_VEC_SAFE_EMA(new_meas.snr_dB, trs_measurements.snr_dB, args.trs_sinr_ema_alpha); // Consider CFO measurement invalid if the SNR is negative. In this case, set CFO to 0. - if (trs_measurements.snr_dB > 0.0f) { + if (new_meas.snr_dB > 0.0f) { trs_measurements.cfo_hz = SRSRAN_VEC_SAFE_EMA(new_meas.cfo_hz, trs_measurements.cfo_hz, args.trs_cfo_ema_alpha); - } else { - trs_measurements.cfo_hz = 0.0f; } trs_measurements.nof_re++; trs_measurements_mutex.unlock(); diff --git a/srsue/hdr/phy/phy_common.h b/srsue/hdr/phy/phy_common.h index ddbfaa058..8967ce5b2 100644 --- a/srsue/hdr/phy/phy_common.h +++ b/srsue/hdr/phy/phy_common.h @@ -65,6 +65,8 @@ public: srsran::phy_cfg_mbsfn_t mbsfn_config = {}; + std::atomic cell_is_selecting = {false}; + // Secondary serving cell states scell::state cell_state; @@ -305,7 +307,7 @@ private: std::mutex mtch_mutex; std::condition_variable mtch_cvar; - bool is_pending_tx_end = false; + std::atomic is_pending_tx_end{false}; srsran::radio_interface_phy* radio_h = nullptr; srslog::basic_logger& logger; diff --git a/srsue/hdr/stack/mac/mac.h b/srsue/hdr/stack/mac/mac.h index 898a4fe2e..bd7cf0f0a 100644 --- a/srsue/hdr/stack/mac/mac.h +++ b/srsue/hdr/stack/mac/mac.h @@ -158,8 +158,8 @@ private: srsran::task_multiqueue::queue_handle stack_task_dispatch_queue; // pointer to MAC PCAP object - srsran::mac_pcap* pcap = nullptr; - bool is_first_ul_grant = false; + srsran::mac_pcap* pcap = nullptr; + std::atomic is_first_ul_grant{false}; std::mutex metrics_mutex = {}; mac_metrics_t metrics[SRSRAN_MAX_CARRIERS] = {}; diff --git a/srsue/hdr/stack/mac/proc_phr.h b/srsue/hdr/stack/mac/proc_phr.h index bc499c3b0..ffdf953b5 100644 --- a/srsue/hdr/stack/mac/proc_phr.h +++ b/srsue/hdr/stack/mac/proc_phr.h @@ -61,6 +61,8 @@ private: srsran::timer_handler::unique_timer timer_periodic; srsran::timer_handler::unique_timer timer_prohibit; + + std::mutex mutex; }; } // namespace srsue diff --git a/srsue/hdr/stack/mac/ul_harq.h b/srsue/hdr/stack/mac/ul_harq.h index 2bfafdefd..48d8289b6 100644 --- a/srsue/hdr/stack/mac/ul_harq.h +++ b/srsue/hdr/stack/mac/ul_harq.h @@ -109,9 +109,9 @@ private: srsran::ul_harq_cfg_t harq_cfg = {}; - float average_retx = 0.0; - uint64_t nof_pkts = 0; - ra_proc* ra_procedure = nullptr; + std::atomic average_retx{0}; + std::atomic nof_pkts{0}; + ra_proc* ra_procedure = nullptr; uint8_t cc_idx = 0; }; diff --git a/srsue/hdr/stack/ue_stack_lte.h b/srsue/hdr/stack/ue_stack_lte.h index fe00213fb..d83fd079d 100644 --- a/srsue/hdr/stack/ue_stack_lte.h +++ b/srsue/hdr/stack/ue_stack_lte.h @@ -243,7 +243,7 @@ private: ue_bearer_manager bearers; // helper to manage mapping between EPS and radio bearers // Metrics helper - uint32_t ul_dropped_sdus = 0; + std::atomic ul_dropped_sdus{0}; }; } // namespace srsue diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 7d423a5ef..fecc4d20e 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -43,7 +43,7 @@ #include #include -extern bool simulate_rlf; +extern std::atomic simulate_rlf; using namespace std; using namespace srsue; @@ -648,7 +648,7 @@ static void* input_loop(void*) metrics_screen->toggle_print(do_metrics); } } else if (key == "rlf") { - simulate_rlf = true; + simulate_rlf.store(true, std::memory_order_relaxed); cout << "Sending Radio Link Failure" << endl; } else if (key == "q") { // let the signal handler do the job diff --git a/srsue/src/phy/lte/cc_worker.cc b/srsue/src/phy/lte/cc_worker.cc index 96f5dcc47..cdd9d9bba 100644 --- a/srsue/src/phy/lte/cc_worker.cc +++ b/srsue/src/phy/lte/cc_worker.cc @@ -289,7 +289,12 @@ bool cc_worker::work_dl_regular() // Decode PDSCH decode_pdsch(ack_resource, &dl_action, dl_ack); - // Informs Stack about the decoding status + // Informs Stack about the decoding status, send NACK if cell is in process of re-selection + if (phy->cell_is_selecting) { + for (uint32_t i = 0; i < SRSRAN_MAX_CODEWORDS; i++) { + dl_ack[i] = false; + } + } phy->stack->tb_decoded(cc_idx, mac_grant, dl_ack); } diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index 2f2f95b85..bab5982a8 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -184,20 +184,22 @@ void cc_worker::decode_pdcch_dl() if (logger.debug.enabled()) { for (uint32_t i = 0; i < ue_dl.pdcch_info_count; i++) { const srsran_ue_dl_nr_pdcch_info_t* info = &ue_dl.pdcch_info[i]; - logger.debug("PDCCH: dci=%s, rnti=%x, crst_id=%d, ss_type=%d, ncce=%d, al=%d, EPRE=%+.2f, RSRP=%+.2f, corr=%.3f; " - "evm=%f; nof_bits=%d; crc=%s;", - srsran_dci_format_nr_string(info->dci_ctx.format), - info->dci_ctx.rnti, - info->dci_ctx.coreset_id, - info->dci_ctx.ss_type, - info->dci_ctx.location.ncce, - info->dci_ctx.location.L, - info->measure.epre_dBfs, - info->measure.rsrp_dBfs, - info->measure.norm_corr, - info->result.evm, - info->nof_bits, - info->result.crc ? "OK" : "KO"); + logger.debug( + "PDCCH: dci=%s, %s-rnti=%x, crst_id=%d, ss_type=%s, ncce=%d, al=%d, EPRE=%+.2f, RSRP=%+.2f, corr=%.3f; " + "evm=%f; nof_bits=%d; crc=%s;", + srsran_dci_format_nr_string(info->dci_ctx.format), + srsran_rnti_type_str_short(info->dci_ctx.rnti_type), + info->dci_ctx.rnti, + info->dci_ctx.coreset_id, + srsran_ss_type_str(info->dci_ctx.ss_type), + info->dci_ctx.location.ncce, + info->dci_ctx.location.L, + info->measure.epre_dBfs, + info->measure.rsrp_dBfs, + info->measure.norm_corr, + info->result.evm, + info->nof_bits, + info->result.crc ? "OK" : "KO"); } } } @@ -482,7 +484,7 @@ bool cc_worker::work_dl() } // Check if it is a DL slot, if not skip - if (!srsran_tdd_nr_is_dl(&phy.cfg.tdd, 0, dl_slot_cfg.idx)) { + if (!srsran_duplex_nr_is_dl(&phy.cfg.duplex, 0, dl_slot_cfg.idx)) { return true; } @@ -494,10 +496,11 @@ bool cc_worker::work_dl() // Compensate CFO from TRS measurements if (std::isnormal(phy.args.enable_worker_cfo)) { - float dl_cfo_hz = phy.get_dl_cfo(); + float dl_cfo_hz = phy.get_dl_cfo(); + float dl_cfo_norm = -dl_cfo_hz / (1000.0f * ue_ul.ifft.sf_sz); for (cf_t* b : rx_buffer) { if (b != nullptr and ue_ul.ifft.sf_sz != 0) { - srsran_vec_apply_cfo(b, dl_cfo_hz / (1000.0f * ue_ul.ifft.sf_sz), b, ue_ul.ifft.sf_sz); + srsran_vec_apply_cfo(b, dl_cfo_norm, b, ue_ul.ifft.sf_sz); } } } @@ -529,7 +532,7 @@ bool cc_worker::work_ul() bool has_ul_ack = phy.get_pending_ack(ul_slot_cfg.idx, pdsch_ack); // Check if it is a UL slot, if not skip - if (!srsran_tdd_nr_is_ul(&phy.cfg.tdd, 0, ul_slot_cfg.idx)) { + if (!srsran_duplex_nr_is_ul(&phy.cfg.duplex, 0, ul_slot_cfg.idx)) { // No NR signal shall be transmitted srsran_vec_cf_zero(tx_buffer[0], ue_ul.ifft.sf_sz); diff --git a/srsue/src/phy/nr/worker_pool.cc b/srsue/src/phy/nr/worker_pool.cc index 9c9493a50..e5061dbff 100644 --- a/srsue/src/phy/nr/worker_pool.cc +++ b/srsue/src/phy/nr/worker_pool.cc @@ -88,7 +88,7 @@ sf_worker* worker_pool::wait_worker(uint32_t tti) if (prach_buffer->is_ready_to_send(tti, phy_state.cfg.carrier.pci)) { uint32_t nof_prach_sf = 0; float prach_target_power = 0.0f; - cf_t* prach_ptr = prach_buffer->generate(-phy_state.get_ul_cfo() / 15000, &nof_prach_sf, &prach_target_power); + cf_t* prach_ptr = prach_buffer->generate(phy_state.get_ul_cfo() / 15000, &nof_prach_sf, &prach_target_power); worker->set_prach(prach_ptr, prach_target_power); } diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index 848bcde3b..c91dbbf89 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -315,6 +315,10 @@ bool phy::cell_select(phy_cell_t cell) if (sfsync.cell_select_init(cell)) { // Update PCI before starting the background command to make sure PRACH gets the updated value selected_cell.id = cell.pci; + + // Indicate workers that cell selection is in progress + common.cell_is_selecting = true; + cmd_worker_cell.add_cmd([this, cell]() { // Wait SYNC transitions to IDLE sfsync.wait_idle(); @@ -329,6 +333,10 @@ bool phy::cell_select(phy_cell_t cell) selected_cell = sync_cell; } stack->cell_select_complete(ret); + + // Indicate workers that cell selection has finished + common.cell_is_selecting = false; + }); return true; } else { diff --git a/srsue/src/phy/sync.cc b/srsue/src/phy/sync.cc index 0754a54da..592a94987 100644 --- a/srsue/src/phy/sync.cc +++ b/srsue/src/phy/sync.cc @@ -501,9 +501,11 @@ void sync::run_camping_in_sync_state(lte::sf_worker* lte_worker, Debug("SYNC: Worker %d synchronized", lte_worker->get_id()); // Collect and provide metrics from last successful sync - metrics.sfo = sfo; - metrics.cfo = cfo; - metrics.ta_us = worker_com->ta.get_usec(); + metrics.sfo = sfo; + metrics.cfo = cfo; + metrics.ta_us = worker_com->ta.get_usec(); + metrics.distance_km = worker_com->ta.get_km(); + metrics.speed_kmph = worker_com->ta.get_speed_kmph(tti); for (uint32_t i = 0; i < worker_com->args->nof_lte_carriers; i++) { worker_com->set_sync_metrics(i, metrics); } @@ -552,7 +554,7 @@ void sync::run_camping_in_sync_state(lte::sf_worker* lte_worker, // As UE sync compensates CFO externally based on LTE signal and the NR carrier may estimate the CFO from the LTE // signal. It is necessary setting an NR external CFO offset to compensate it. - nr_worker_pool->set_ul_ext_cfo(-srsran_ue_sync_get_cfo(&ue_sync)); + nr_worker_pool->set_ul_ext_cfo(srsran_ue_sync_get_cfo(&ue_sync)); // NR worker needs to be launched first, phy_common::worker_end expects first the NR worker and the LTE worker. worker_com->semaphore.push(nr_worker); diff --git a/srsue/src/stack/mac/mac.cc b/srsue/src/stack/mac/mac.cc index 82bb5a140..62bb6bd06 100644 --- a/srsue/src/stack/mac/mac.cc +++ b/srsue/src/stack/mac/mac.cc @@ -155,7 +155,10 @@ void mac::reconfiguration(const uint32_t& cc_idx, const bool& enable) // Implement Section 5.9 void mac::reset() { - bzero(&metrics, sizeof(mac_metrics_t)); + { + std::lock_guard lock(metrics_mutex); + bzero(&metrics, sizeof(mac_metrics_t)); + } Info("Resetting MAC"); @@ -210,6 +213,7 @@ void mac::run_tti(const uint32_t tti) ra_procedure.update_rar_window(ra_window); // Count TTI for metrics + std::lock_guard lock(metrics_mutex); for (uint32_t i = 0; i < SRSRAN_MAX_CARRIERS; i++) { metrics[i].nof_tti++; } @@ -355,10 +359,13 @@ void mac::mch_decoded(uint32_t len, bool crc) pcap->write_dl_mch(mch_payload_buffer, len, true, phy_h->get_current_tti(), 0); } + std::lock_guard lock(metrics_mutex); metrics[0].rx_brate += len * 8; } else { + std::lock_guard lock(metrics_mutex); metrics[0].rx_errors++; } + std::lock_guard lock(metrics_mutex); metrics[0].rx_pkts++; } diff --git a/srsue/src/stack/mac/proc_bsr.cc b/srsue/src/stack/mac/proc_bsr.cc index 8e99c2812..a9f5a50f6 100644 --- a/srsue/src/stack/mac/proc_bsr.cc +++ b/srsue/src/stack/mac/proc_bsr.cc @@ -122,6 +122,8 @@ void bsr_proc::timer_expired(uint32_t timer_id) uint32_t bsr_proc::get_buffer_state() { + std::lock_guard lock(mutex); + uint32_t buffer = 0; for (int i = 0; i < NOF_LCG; i++) { buffer += get_buffer_state_lcg(i); diff --git a/srsue/src/stack/mac/proc_phr.cc b/srsue/src/stack/mac/proc_phr.cc index fa5dd840a..7ff724ea8 100644 --- a/srsue/src/stack/mac/proc_phr.cc +++ b/srsue/src/stack/mac/proc_phr.cc @@ -50,6 +50,7 @@ void phr_proc::init(phy_interface_mac_lte* phy_h_, srsran::ext_task_sched_handle void phr_proc::reset() { + std::lock_guard lock(mutex); timer_periodic.stop(); timer_prohibit.stop(); phr_is_triggered = false; @@ -57,6 +58,8 @@ void phr_proc::reset() void phr_proc::set_config(srsran::phr_cfg_t& cfg) { + std::lock_guard lock(mutex); + phr_cfg = cfg; // First stop timers. If enabled==false or value is Inf, won't be re-started @@ -99,6 +102,7 @@ bool phr_proc::pathloss_changed() void phr_proc::start_periodic_timer() { + std::lock_guard lock(mutex); if (phr_cfg.enabled && phr_cfg.periodic_timer > 0) { timer_periodic.run(); } @@ -107,6 +111,7 @@ void phr_proc::start_periodic_timer() /* Trigger PHR when timers exires */ void phr_proc::timer_expired(uint32_t timer_id) { + std::lock_guard lock(mutex); if (!phr_cfg.enabled) { Warning("PHR: %s timer triggered but PHR has been disabled", timer_id == timer_periodic.id() ? "Periodic" : "Prohibit"); @@ -128,6 +133,8 @@ void phr_proc::timer_expired(uint32_t timer_id) void phr_proc::step() { + std::lock_guard lock(mutex); + if (phr_cfg.enabled && initiated) { if (pathloss_changed() && timer_prohibit.is_expired()) { Info("PHR: Triggered by pathloss difference. cur_pathloss_db=%d", last_pathloss_db); @@ -138,6 +145,7 @@ void phr_proc::step() bool phr_proc::generate_phr_on_ul_grant(float* phr) { + std::lock_guard lock(mutex); if (phr_is_triggered) { if (phr) { *phr = phy_h->get_phr(); @@ -158,6 +166,7 @@ bool phr_proc::generate_phr_on_ul_grant(float* phr) bool phr_proc::is_extended() { + std::lock_guard lock(mutex); return phr_cfg.extended; } } // namespace srsue diff --git a/srsue/src/stack/mac/ul_harq.cc b/srsue/src/stack/mac/ul_harq.cc index 33c673b23..e48311a72 100644 --- a/srsue/src/stack/mac/ul_harq.cc +++ b/srsue/src/stack/mac/ul_harq.cc @@ -112,7 +112,7 @@ int ul_harq_entity::get_current_tbs(uint32_t pid) float ul_harq_entity::get_average_retx() { - return average_retx; + return average_retx.load(std::memory_order_relaxed); } ul_harq_entity::ul_harq_process::ul_harq_process() : logger(srslog::fetch_basic_logger("MAC")) @@ -357,12 +357,15 @@ void ul_harq_entity::ul_harq_process::generate_new_tx(mac_interface_phy_lte::mac mac_interface_phy_lte::tb_action_ul_t* action) { // Compute average number of retransmissions per packet considering previous packet - harq_entity->average_retx = SRSRAN_VEC_CMA((float)current_tx_nb, harq_entity->average_retx, harq_entity->nof_pkts++); - cur_grant = grant; - harq_feedback = false; - is_grant_configured = true; - current_tx_nb = 0; - current_irv = 0; + harq_entity->average_retx.store(SRSRAN_VEC_CMA((float)current_tx_nb, + harq_entity->average_retx.load(std::memory_order_relaxed), + harq_entity->nof_pkts++), + std::memory_order_relaxed); + cur_grant = grant; + harq_feedback = false; + is_grant_configured = true; + current_tx_nb = 0; + current_irv = 0; action->is_rar = grant.is_rar || (grant.rnti == harq_entity->rntis->get_temp_rnti()); diff --git a/srsue/src/stack/mac_nr/mux_nr.cc b/srsue/src/stack/mac_nr/mux_nr.cc index 5acd07ad8..3703e7ac5 100644 --- a/srsue/src/stack/mac_nr/mux_nr.cc +++ b/srsue/src/stack/mac_nr/mux_nr.cc @@ -187,6 +187,7 @@ void mux_nr::generate_bsr_mac_ce(const srsran::bsr_format_nr_t& format) break; case srsran::LONG_BSR: add_bsr_ce = lbsr_ce; + break; default: logger.error("MUX can only be instructred to generate short or long BSRs."); } diff --git a/srsue/src/stack/rrc/rrc.cc b/srsue/src/stack/rrc/rrc.cc index 668fe0239..e3c00849b 100644 --- a/srsue/src/stack/rrc/rrc.cc +++ b/srsue/src/stack/rrc/rrc.cc @@ -41,7 +41,7 @@ #include #include -bool simulate_rlf = false; +std::atomic simulate_rlf{false}; using namespace srsran; using namespace asn1::rrc; @@ -212,9 +212,9 @@ void rrc::run_tti() return; } - if (simulate_rlf) { + if (simulate_rlf.load(std::memory_order_relaxed)) { radio_link_failure_process(); - simulate_rlf = false; + simulate_rlf.store(false, std::memory_order_relaxed); } // Process pending PHY measurements in IDLE/CONNECTED @@ -2788,7 +2788,7 @@ void rrc::release_drb(uint32_t drb_id) */ uint32_t rrc::get_lcid_for_drb_id(const uint32_t& drb_id) { - uint32_t lcid = 0; + uint32_t lcid = 0; if (drbs.find(drb_id) != drbs.end()) { asn1::rrc::drb_to_add_mod_s drb_cnfg = drbs[drb_id]; if (drb_cnfg.lc_ch_id_present) { diff --git a/srsue/src/stack/rrc/rrc_nr.cc b/srsue/src/stack/rrc/rrc_nr.cc index 5cf4b62ef..79606f703 100644 --- a/srsue/src/stack/rrc/rrc_nr.cc +++ b/srsue/src/stack/rrc/rrc_nr.cc @@ -1202,11 +1202,11 @@ bool rrc_nr::apply_sp_cell_cfg(const sp_cell_cfg_s& sp_cell_cfg) } if (recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common_present) { - srsran_tdd_config_nr_t tdd; - if (make_phy_tdd_cfg(recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common, &tdd) == true) { - phy_cfg.tdd = tdd; + srsran_duplex_config_nr_t duplex; + if (make_phy_tdd_cfg(recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common, &duplex) == true) { + phy_cfg.duplex = duplex; } else { - logger.warning("Warning while building tdd structure"); + logger.warning("Warning while building duplex structure"); return false; } } else { diff --git a/srsue/src/stack/ue_stack_nr.cc b/srsue/src/stack/ue_stack_nr.cc index c914b918a..a357e3745 100644 --- a/srsue/src/stack/ue_stack_nr.cc +++ b/srsue/src/stack/ue_stack_nr.cc @@ -120,7 +120,12 @@ bool ue_stack_nr::switch_on() { // statically setup TUN (will be done through RRC later) char* err_str = nullptr; - if (gw->setup_if_addr(5, LIBLTE_MME_PDN_TYPE_IPV4, htonl(inet_addr("192.168.1.3")), nullptr, err_str)) { + struct in_addr in_addr; + if (inet_pton(AF_INET, "192.168.1.3", &in_addr.s_addr) != 1) { + perror("inet_pton"); + return false; + } + if (gw->setup_if_addr(5, LIBLTE_MME_PDN_TYPE_IPV4, htonl(in_addr.s_addr), nullptr, err_str)) { printf("Error configuring TUN interface\n"); } return true; diff --git a/srsue/src/stack/upper/gw.cc b/srsue/src/stack/upper/gw.cc index ee5f96b81..242939dc2 100644 --- a/srsue/src/stack/upper/gw.cc +++ b/srsue/src/stack/upper/gw.cc @@ -62,8 +62,11 @@ int gw::init(const gw_args_t& args_, stack_interface_gw* stack_) return SRSRAN_ERROR; } - mbsfn_sock_addr.sin_family = AF_INET; - mbsfn_sock_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); + mbsfn_sock_addr.sin_family = AF_INET; + if (inet_pton(mbsfn_sock_addr.sin_family, "127.0.0.1", &mbsfn_sock_addr.sin_addr.s_addr) != 1) { + perror("inet_pton"); + return false; + } return SRSRAN_SUCCESS; } @@ -462,8 +465,13 @@ int gw::setup_if_addr4(uint32_t ip_addr, char* err_str) close(tun_fd); return SRSRAN_ERROR_CANT_START; } - ifr.ifr_netmask.sa_family = AF_INET; - ((struct sockaddr_in*)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr(args.tun_dev_netmask.c_str()); + ifr.ifr_netmask.sa_family = AF_INET; + if (inet_pton(ifr.ifr_netmask.sa_family, args.tun_dev_netmask.c_str(), &((struct sockaddr_in*)&ifr.ifr_netmask)->sin_addr.s_addr) != 1) { + logger.error("Invalid tun_dev_netmask: %s", args.tun_dev_netmask.c_str()); + srsran::console("Invalid tun_dev_netmask: %s\n", args.tun_dev_netmask.c_str()); + perror("inet_pton"); + return SRSRAN_ERROR_CANT_START; + } if (0 > ioctl(sock, SIOCSIFNETMASK, &ifr)) { err_str = strerror(errno); logger.debug("Failed to set socket netmask: %s", err_str); diff --git a/srsue/src/stack/upper/test/gw_test.cc b/srsue/src/stack/upper/test/gw_test.cc index f1e132bbe..6f547fb10 100644 --- a/srsue/src/stack/upper/test/gw_test.cc +++ b/srsue/src/stack/upper/test/gw_test.cc @@ -52,7 +52,12 @@ int gw_test() char* err_str = nullptr; int rtn = 0; - rtn = gw.setup_if_addr(eps_bearer_id, LIBLTE_MME_PDN_TYPE_IPV4, htonl(inet_addr("192.168.56.32")), nullptr, err_str); + struct in_addr in_addr; + if (inet_pton(AF_INET, "192.168.56.32", &in_addr.s_addr) != 1) { + perror("inet_pton"); + return SRSRAN_ERROR; + } + rtn = gw.setup_if_addr(eps_bearer_id, LIBLTE_MME_PDN_TYPE_IPV4, htonl(in_addr.s_addr), nullptr, err_str); if (rtn != SRSRAN_SUCCESS) { srslog::fetch_basic_logger("TEST", false) diff --git a/srsue/src/test/ttcn3/hdr/ttcn3_port_handler.h b/srsue/src/test/ttcn3/hdr/ttcn3_port_handler.h index ed1b8adea..58b78f9af 100644 --- a/srsue/src/test/ttcn3/hdr/ttcn3_port_handler.h +++ b/srsue/src/test/ttcn3/hdr/ttcn3_port_handler.h @@ -29,6 +29,7 @@ #include "srsran/common/epoll_helper.h" #include "srsran/common/standard_streams.h" +#include "srsran/common/network_utils.h" #include "srsran/srslog/srslog.h" #include "ttcn3_common.h" #include @@ -188,10 +189,10 @@ public: // Port bind struct sockaddr_in bind_addr = {}; - bind_addr.sin_family = AF_INET; - inet_pton(AF_INET, net_ip.c_str(), &(bind_addr.sin_addr)); - bind_addr.sin_port = htons(net_port); - + if (not srsran::net_utils::set_sockaddr(&bind_addr, net_ip.c_str(), net_port)) { + srsran::console("Invalid net_ip: %s\n", net_ip.c_str()); + return SRSRAN_ERROR; + } int one = 1; setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); ret = bind(sock_fd, (struct sockaddr*)&bind_addr, sizeof(bind_addr)); diff --git a/test/phy/CMakeLists.txt b/test/phy/CMakeLists.txt index 2f959c22c..3689ba83c 100644 --- a/test/phy/CMakeLists.txt +++ b/test/phy/CMakeLists.txt @@ -37,15 +37,18 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) ${Boost_LIBRARIES} ${ATOMIC_LIBS}) + # For each supported bandwidth foreach (NR_PHY_TEST_BW "10MHz" "20MHz") - foreach (NR_PHY_TEST_TDD "6D+4U" "FR1.15-1") + # For each supported frame structure + foreach (NR_PHY_TEST_DUPLEX "FDD" "6D+4U" "FR1.15-1") set(NR_PHY_TEST_DURATION_MS 20) + # DL flooding only foreach (NR_PHY_TEST_PDSCH "default" "ts38101/5.2-1") - add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_TDD}_dl_${NR_PHY_TEST_PDSCH} nr_phy_test - --reference=carrier=${NR_PHY_TEST_BW},tdd=${NR_PHY_TEST_TDD},pdsch=${NR_PHY_TEST_PDSCH} + add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_DUPLEX}_dl_${NR_PHY_TEST_PDSCH} nr_phy_test + --reference=carrier=${NR_PHY_TEST_BW},duplex=${NR_PHY_TEST_DUPLEX},pdsch=${NR_PHY_TEST_PDSCH} --duration=${NR_PHY_TEST_DURATION_MS} - --gnb.stack.pdsch.slots=0,1,2,3,4,5 # All possible DL slots + --gnb.stack.pdsch.slots=all --gnb.stack.pdsch.start=0 # Start at RB 0 --gnb.stack.pdsch.length=52 # Full 10 MHz BW --gnb.stack.pdsch.mcs=27 # Maximum MCS @@ -55,11 +58,12 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) ) endforeach () - add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_TDD}_ul_only nr_phy_test - --reference=carrier=${NR_PHY_TEST_BW},tdd=${NR_PHY_TEST_TDD} + # UL flooding + add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_DUPLEX}_ul_only nr_phy_test + --reference=carrier=${NR_PHY_TEST_BW},duplex=${NR_PHY_TEST_DUPLEX} --duration=${NR_PHY_TEST_DURATION_MS} - --gnb.stack.pdsch.slots=6 # No PDSCH - --gnb.stack.pusch.slots=6,7,8,9 # All possible UL slots + --gnb.stack.pdsch.slots=none + --gnb.stack.pusch.slots=all --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 @@ -67,14 +71,15 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) --ue.phy.nof_threads=${NR_PHY_TEST_UE_NOF_THREADS} ) - add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_TDD}_bidir nr_phy_test - --reference=carrier=${NR_PHY_TEST_BW},tdd=${NR_PHY_TEST_TDD} + # DL and UL flooding + add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_DUPLEX}_bidir nr_phy_test + --reference=carrier=${NR_PHY_TEST_BW},duplex=${NR_PHY_TEST_DUPLEX} --duration=${NR_PHY_TEST_DURATION_MS} - --gnb.stack.pdsch.slots=0,1,2,3,4,5 # All possible DL slots + --gnb.stack.pdsch.slots=all --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=6,7,8,9 # All possible UL slots + --gnb.stack.pusch.slots=all --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 diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index e1552bc1d..4b48644cb 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -369,10 +369,22 @@ public: ul.mcs = args.pusch.mcs; if (args.pdsch.slots != "none" and not args.pdsch.slots.empty()) { - srsran::string_parse_list(args.pdsch.slots, ',', dl.slots); + if (args.pdsch.slots == "all") { + for (uint32_t n = 0; n < SRSRAN_NSLOTS_PER_FRAME_NR(phy_cfg.carrier.scs); n++) { + dl.slots.insert(n); + } + } else { + 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); + if (args.pusch.slots == "all") { + for (uint32_t n = 0; n < SRSRAN_NSLOTS_PER_FRAME_NR(phy_cfg.carrier.scs); n++) { + ul.slots.insert(n); + } + } else { + srsran::string_parse_list(args.pusch.slots, ',', ul.slots); + } } // Select DCI locations @@ -414,7 +426,11 @@ public: // Setup DL Data to ACK timing for (uint32_t i = 0; i < SRSRAN_NOF_SF_X_FRAME; i++) { - dl_data_to_ul_ack[i] = args.phy_cfg.harq_ack.dl_data_to_ul_ack[i % args.phy_cfg.tdd.pattern1.period_ms]; + if (args.phy_cfg.duplex.mode == SRSRAN_DUPLEX_MODE_TDD) { + dl_data_to_ul_ack[i] = args.phy_cfg.harq_ack.dl_data_to_ul_ack[i % args.phy_cfg.duplex.tdd.pattern1.period_ms]; + } else { + dl_data_to_ul_ack[i] = args.phy_cfg.harq_ack.dl_data_to_ul_ack[i % args.phy_cfg.harq_ack.nof_dl_data_to_ul_ack]; + } } // If reached this point the configuration is valid @@ -450,7 +466,7 @@ public: } // 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)) { + if (not srsran_duplex_nr_is_dl(&phy_cfg.duplex, phy_cfg.carrier.scs, slot_cfg.idx)) { return SRSRAN_SUCCESS; } @@ -460,7 +476,7 @@ public: } // Check if the UL slot is valid, if not skip UL scheduling - if (not srsran_tdd_nr_is_ul(&phy_cfg.tdd, phy_cfg.carrier.scs, TTI_TX(slot_cfg.idx))) { + if (not srsran_duplex_nr_is_ul(&phy_cfg.duplex, phy_cfg.carrier.scs, TTI_TX(slot_cfg.idx))) { return SRSRAN_SUCCESS; }