Merge branch 'next' into agpl_next

master
Codebot 3 years ago committed by Your Name
commit ecd0580b9e

@ -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_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, 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, 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); 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); bool make_phy_coreset_cfg(const asn1::rrc_nr::ctrl_res_set_s& ctrl_res_set, srsran_coreset_t* srsran_coreset);

@ -113,11 +113,23 @@ public:
/// All registered bearer are removed (e.g. after connection release) /// All registered bearer are removed (e.g. after connection release)
void reset(); void reset();
bool has_active_radio_bearer(uint32_t eps_bearer_id) { return impl.has_active_radio_bearer(eps_bearer_id); } bool has_active_radio_bearer(uint32_t eps_bearer_id)
{
radio_bearer_t get_radio_bearer(uint32_t eps_bearer_id) { return impl.get_radio_bearer(eps_bearer_id); } srsran::rwlock_read_guard rw_lock(rwlock);
return impl.has_active_radio_bearer(eps_bearer_id);
radio_bearer_t get_lcid_bearer(uint32_t lcid) { return impl.get_lcid_bearer(lcid); } }
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: private:
pthread_rwlock_t rwlock = {}; /// RW lock to protect access from RRC/GW threads pthread_rwlock_t rwlock = {}; /// RW lock to protect access from RRC/GW threads

@ -44,16 +44,16 @@ struct phy_cfg_nr_t {
srsran_subcarrier_spacing_t scs = srsran_subcarrier_spacing_30kHz; srsran_subcarrier_spacing_t scs = srsran_subcarrier_spacing_30kHz;
}; };
srsran_tdd_config_nr_t tdd = {}; srsran_duplex_config_nr_t duplex = {};
srsran_sch_hl_cfg_nr_t pdsch = {}; srsran_sch_hl_cfg_nr_t pdsch = {};
srsran_sch_hl_cfg_nr_t pusch = {}; srsran_sch_hl_cfg_nr_t pusch = {};
srsran_pucch_nr_hl_cfg_t pucch = {}; srsran_pucch_nr_hl_cfg_t pucch = {};
srsran_prach_cfg_t prach = {}; srsran_prach_cfg_t prach = {};
srsran_pdcch_cfg_nr_t pdcch = {}; srsran_pdcch_cfg_nr_t pdcch = {};
srsran_harq_ack_cfg_hl_t harq_ack = {}; srsran_harq_ack_cfg_hl_t harq_ack = {};
srsran_csi_hl_cfg_t csi = {}; srsran_csi_hl_cfg_t csi = {};
srsran_carrier_nr_t carrier = {}; srsran_carrier_nr_t carrier = {};
ssb_cfg_t ssb; ssb_cfg_t ssb;
phy_cfg_nr_t() {} phy_cfg_nr_t() {}

@ -52,18 +52,23 @@ public:
const std::array<std::string, R_CARRIER_COUNT> R_CARRIER_STRING = {{"10MHz", "20MHz"}}; const std::array<std::string, R_CARRIER_COUNT> R_CARRIER_STRING = {{"10MHz", "20MHz"}};
enum { enum {
/**
* @brief FDD, all slots for DL and UL
*/
R_DUPLEX_FDD = 0,
/** /**
* @brief TDD custom reference 5 slot DL and 5 slot UL * @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 * @brief TDD pattern FR1.15-1 defined in TS38.101-4 Table A.1.2-1
*/ */
R_TDD_FR1_15_1, R_DUPLEX_TDD_FR1_15_1,
R_TDD_COUNT, R_DUPLEX_COUNT,
} tdd = R_TDD_CUSTOM_6_4; } duplex = R_DUPLEX_TDD_CUSTOM_6_4;
const std::array<std::string, R_TDD_COUNT> R_TDD_STRING = {{"6D+4U", "FR1.15-1"}}; const std::array<std::string, R_DUPLEX_COUNT> R_DUPLEX_STRING = {{"FDD", "6D+4U", "FR1.15-1"}};
enum { enum {
/** /**
@ -153,8 +158,8 @@ private:
/** /**
* TDD make helper methods * TDD make helper methods
*/ */
static void make_tdd_custom_6_4(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_tdd_config_nr_t& tdd); static void make_tdd_fr1_15_1(srsran_duplex_config_nr_t& duplex);
/** /**
* PDCCH make helper methods * PDCCH make helper methods
@ -180,9 +185,9 @@ private:
/** /**
* HARQ make helper methods * HARQ make helper methods
*/ */
static void make_harq_auto(srsran_harq_ack_cfg_hl_t& harq, static void make_harq_auto(srsran_harq_ack_cfg_hl_t& harq,
const srsran_carrier_nr_t& carrier, const srsran_carrier_nr_t& carrier,
const srsran_tdd_config_nr_t& tdd_cfg); const srsran_duplex_config_nr_t& duplex_cfg);
/** /**
* PRACH make helper methods * PRACH make helper methods

@ -23,6 +23,8 @@
#include "srsran/common/interfaces_common.h" #include "srsran/common/interfaces_common.h"
#include "srsran/srsran.h" #include "srsran/srsran.h"
#include "srsran/interfaces/enb_rrc_interfaces.h"
#ifndef SRSRAN_ENB_INTERFACES_H #ifndef SRSRAN_ENB_INTERFACES_H
#define SRSRAN_ENB_INTERFACES_H #define SRSRAN_ENB_INTERFACES_H
@ -36,8 +38,6 @@ public:
virtual void remove_eps_bearers(uint16_t rnti) = 0; virtual void remove_eps_bearers(uint16_t rnti) = 0;
}; };
class stack_interface_phy_lte;
} // namespace srsenb } // namespace srsenb
#endif // SRSRAN_ENB_INTERFACES_H #endif // SRSRAN_ENB_INTERFACES_H

@ -267,8 +267,6 @@ public:
// Combined interface for PHY to access stack (MAC and RRC) // Combined interface for PHY to access stack (MAC and RRC)
class stack_interface_phy_lte : public mac_interface_phy_lte class stack_interface_phy_lte : public mac_interface_phy_lte
{ {
public:
virtual void tti_clock() = 0;
}; };
} // namespace srsenb } // namespace srsenb

@ -129,67 +129,6 @@ public:
virtual void notify_pdcp_integrity_error(uint16_t rnti, uint32_t lcid) = 0; 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 } // namespace srsenb
#endif // SRSRAN_ENB_RRC_INTERFACES_H #endif // SRSRAN_ENB_RRC_INTERFACES_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

@ -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

@ -189,6 +189,7 @@ struct phy_args_nr_t {
bool store_pdsch_ko = false; bool store_pdsch_ko = false;
float trs_epre_ema_alpha = 0.1f; ///< EPRE measurement exponential average alpha 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_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 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 bool enable_worker_cfo = true; ///< Enable/Disable open loop CFO correction at the workers

@ -137,4 +137,6 @@ typedef struct SRSRAN_API {
uint32_t count; ///< Number of resources in the set uint32_t count; ///< Number of resources in the set
} srsran_csi_rs_zp_set_t; } 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 #endif // SRSRAN_CSI_RS_CFG_H

@ -467,6 +467,17 @@ typedef struct SRSRAN_API {
srsran_tdd_pattern_t pattern2; srsran_tdd_pattern_t pattern2;
} srsran_tdd_config_nr_t; } 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 * @brief Describes a measurement based on NZP-CSI-RS or SSB-CSI
* @note Used for tracking RSRP, SNR, CFO, SFO, and so on * @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); 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 * @brief Get the RNTI type name for NR
* @param rnti_type RNTI type name * @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 * @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 numerology Provides BWP numerology
* @param slot_idx Slot index in the frame for the given numerology * @param slot_idx Slot index in the frame for the given numerology
* @return true if the provided slot index is configured for Downlink * @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 * @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 numerology Provides BWP numerology
* @param slot_idx Slot index in the frame for the given numerology * @param slot_idx Slot index in the frame for the given numerology
* @return true if the provided slot index is configured for Uplink * @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); SRSRAN_API int srsran_carrier_to_cell(const srsran_carrier_nr_t* carrier, srsran_cell_t* cell);

@ -76,6 +76,8 @@ SRSRAN_API int srsran_gnb_dl_pdsch_put(srsran_gnb_dl_t* q,
const srsran_sch_cfg_nr_t* cfg, const srsran_sch_cfg_nr_t* cfg,
uint8_t* data[SRSRAN_MAX_TB]); 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_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); srsran_gnb_dl_pdsch_info(const srsran_gnb_dl_t* q, const srsran_sch_cfg_nr_t* cfg, char* str, uint32_t str_len);

@ -337,6 +337,7 @@ public:
srsue::pdcp_interface_rlc* pdcp_, srsue::pdcp_interface_rlc* pdcp_,
srsue::rrc_interface_rlc* rrc_, srsue::rrc_interface_rlc* rrc_,
srsran::timer_handler* timers_); srsran::timer_handler* timers_);
bool configure(const rlc_config_t& cfg_); bool configure(const rlc_config_t& cfg_);
void reestablish(); void reestablish();
void stop(); void stop();
@ -564,6 +565,7 @@ private:
rlc_am_lte_tx tx; rlc_am_lte_tx tx;
rlc_am_lte_rx rx; rlc_am_lte_rx rx;
std::mutex metrics_mutex;
rlc_bearer_metrics_t metrics = {}; rlc_bearer_metrics_t metrics = {};
}; };

@ -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, 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) { switch (tdd_ul_dl_cfg_common.pattern1.dl_ul_tx_periodicity) {
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms1: 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; break;
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms2: 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; break;
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms5: 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; break;
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms10: 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; break;
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms1p25: 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()); tdd_ul_dl_cfg_common.pattern1.dl_ul_tx_periodicity.to_string());
return false; return false;
} }
srsran_tdd_config_nr.pattern1.nof_dl_slots = tdd_ul_dl_cfg_common.pattern1.nrof_dl_slots; srsran_duplex_config_nr.tdd.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_duplex_config_nr.tdd.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_duplex_config_nr.tdd.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_ul_symbols = tdd_ul_dl_cfg_common.pattern1.nrof_ul_symbols;
// Copy and return struct // 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) { if (not tdd_ul_dl_cfg_common.pattern2_present) {
return true; 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) { switch (tdd_ul_dl_cfg_common.pattern2.dl_ul_tx_periodicity) {
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms1: 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; break;
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms2: 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; break;
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms5: 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; break;
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms10: 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; break;
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms1p25: 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; return false;
} }
srsran_tdd_config_nr.pattern2.nof_dl_slots = tdd_ul_dl_cfg_common.pattern2.nrof_dl_slots; srsran_duplex_config_nr.tdd.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_duplex_config_nr.tdd.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_duplex_config_nr.tdd.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_ul_symbols = tdd_ul_dl_cfg_common.pattern2.nrof_ul_symbols;
// Copy and return struct // Copy and return struct
*in_srsran_tdd_config_nr = srsran_tdd_config_nr; *in_srsran_duplex_config_nr = srsran_duplex_config_nr;
return true; 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.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; 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) { if (zp_csi_rs_res.periodicity_and_offset_present) {
switch (zp_csi_rs_res.periodicity_and_offset.type()) { switch (zp_csi_rs_res.periodicity_and_offset.type()) {
case csi_res_periodicity_and_offset_c::types_opts::options::slots4: 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.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; 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; 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) { 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(); csi_rs_nzp_resource.power_control_offset_ss = asn1_nzp_csi_rs_res.pwr_ctrl_offset_ss.to_number();

@ -111,6 +111,7 @@ void ue_bearer_manager::remove_eps_bearer(uint8_t eps_bearer_id)
void ue_bearer_manager::reset() void ue_bearer_manager::reset()
{ {
srsran::rwlock_write_guard rw_lock(rwlock);
impl.reset(); impl.reset();
logger.info("Bearers: Reset EPS bearer manager"); logger.info("Bearers: Reset EPS bearer manager");
} }

@ -58,9 +58,11 @@ uint32_t mac_pcap_net::open(std::string client_ip_addr_,
client_udp_port_, client_udp_port_,
bind_addr_str.c_str(), bind_addr_str.c_str(),
bind_udp_port_); bind_udp_port_);
client_addr.sin_family = AF_INET;
client_addr.sin_addr.s_addr = inet_addr(client_ip_addr_.c_str()); if (not net_utils::set_sockaddr(&client_addr, client_ip_addr_.c_str(), client_udp_port_)) {
client_addr.sin_port = htons(client_udp_port_); logger.error("Invalid client_ip_addr: %s", client_ip_addr_.c_str());
return SRSRAN_ERROR;
}
running = true; running = true;
ue_id = ue_id_; ue_id = ue_id_;
// start writer thread // start writer thread

@ -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()); srsran_assert(carrier != R_CARRIER_COUNT, "Invalid carrier reference configuration '%s'", param.back().c_str());
} else if (param.front() == "tdd") { } else if (param.front() == "duplex") {
for (tdd = R_TDD_CUSTOM_6_4; tdd < R_TDD_COUNT; tdd = inc(tdd)) { for (duplex = R_DUPLEX_FDD; duplex < R_DUPLEX_COUNT; duplex = inc(duplex)) {
if (R_TDD_STRING[tdd] == param.back()) { if (R_DUPLEX_STRING[duplex] == param.back()) {
break; 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") { } else if (param.front() == "pdsch") {
for (pdsch = R_PDSCH_DEFAULT; pdsch < R_PDSCH_COUNT; pdsch = inc(pdsch)) { for (pdsch = R_PDSCH_DEFAULT; pdsch < R_PDSCH_COUNT; pdsch = inc(pdsch)) {
if (R_PDSCH_STRING[pdsch] == param.back()) { 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; 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.period_ms = 10;
tdd.pattern1.nof_dl_slots = 6; tdd.pattern1.nof_dl_slots = 6;
tdd.pattern1.nof_dl_symbols = 0; 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; 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.period_ms = 5;
tdd.pattern1.nof_dl_slots = 3; tdd.pattern1.nof_dl_slots = 3;
tdd.pattern1.nof_dl_symbols = 10; 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; pucch.sr_resources[1].resource = resource_sr;
} }
void phy_cfg_nr_default_t::make_harq_auto(srsran_harq_ack_cfg_hl_t& harq, void phy_cfg_nr_default_t::make_harq_auto(srsran_harq_ack_cfg_hl_t& harq,
const srsran_carrier_nr_t& carrier, const srsran_carrier_nr_t& carrier,
const srsran_tdd_config_nr_t& tdd_cfg) const srsran_duplex_config_nr_t& duplex_cfg)
{ {
// Generate as many entries as DL slots if (duplex_cfg.mode == SRSRAN_DUPLEX_MODE_TDD) {
harq.nof_dl_data_to_ul_ack = SRSRAN_MIN(tdd_cfg.pattern1.nof_dl_slots, SRSRAN_MAX_NOF_DL_DATA_TO_UL); const srsran_tdd_config_nr_t& tdd_cfg = duplex_cfg.tdd;
if (tdd_cfg.pattern1.nof_dl_symbols > 0) {
harq.nof_dl_data_to_ul_ack++;
}
// Set PDSCH to ACK timing delay to 4 or more // Generate as many entries as DL slots
for (uint32_t n = 0; n < harq.nof_dl_data_to_ul_ack; n++) { harq.nof_dl_data_to_ul_ack = SRSRAN_MIN(tdd_cfg.pattern1.nof_dl_slots, SRSRAN_MAX_NOF_DL_DATA_TO_UL);
// Set the first slots into the first UL slot if (tdd_cfg.pattern1.nof_dl_symbols > 0) {
if (harq.nof_dl_data_to_ul_ack >= 4 and n < (harq.nof_dl_data_to_ul_ack - 4)) { harq.nof_dl_data_to_ul_ack++;
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 // Set PDSCH to ACK timing delay to 4 or more
if (srsran_tdd_nr_is_ul(&tdd_cfg, carrier.scs, n + 4)) { for (uint32_t n = 0; n < harq.nof_dl_data_to_ul_ack; n++) {
harq.dl_data_to_ul_ack[n] = 4; // Set the first slots into the first UL slot
continue; 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 // 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; 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 // 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"); srsran_assertion_failure("Invalid carrier reference");
} }
switch (reference_cfg.tdd) { switch (reference_cfg.duplex) {
case reference_cfg_t::R_TDD_CUSTOM_6_4: case reference_cfg_t::R_DUPLEX_FDD:
make_tdd_custom_6_4(tdd); duplex.mode = SRSRAN_DUPLEX_MODE_FDD;
break;
case reference_cfg_t::R_DUPLEX_TDD_CUSTOM_6_4:
make_tdd_custom_6_4(duplex);
break; break;
case reference_cfg_t::R_TDD_FR1_15_1: case reference_cfg_t::R_DUPLEX_TDD_FR1_15_1:
make_tdd_fr1_15_1(tdd); make_tdd_fr1_15_1(duplex);
break; break;
case reference_cfg_t::R_TDD_COUNT: case reference_cfg_t::R_DUPLEX_COUNT:
srsran_assertion_failure("Invalid TDD reference"); 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) { switch (reference_cfg.harq) {
case reference_cfg_t::R_HARQ_AUTO: case reference_cfg_t::R_HARQ_AUTO:
make_harq_auto(harq_ack, carrier, tdd); make_harq_auto(harq_ack, carrier, duplex);
break; break;
} }

@ -63,7 +63,7 @@ bool pdcp_entity_lte::configure(const pdcp_config_t& cnfg_)
if (active) { if (active) {
// Already configured // Already configured
if (cnfg_ != cfg) { 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 false;
} }
return true; return true;

@ -55,7 +55,7 @@ bool pdcp_entity_nr::configure(const pdcp_config_t& cnfg_)
if (active) { if (active) {
// Already configured // Already configured
if (cnfg_ != cfg) { 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 false;
} }
return true; return true;

@ -98,8 +98,7 @@ static int csi_rs_location_get_k_list(const srsran_csi_rs_resource_mapping_t* re
} }
// Row 2 // Row 2
if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->nof_ports == 1 && if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->cdm == srsran_csi_rs_cdm_nocdm) {
resource->cdm == srsran_csi_rs_cdm_nocdm) {
if (resource->density == srsran_csi_rs_resource_mapping_density_one || 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_even ||
resource->density == srsran_csi_rs_resource_mapping_density_dot5_odd) { 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 // Row 2
if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->nof_ports == 1 && if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->cdm == srsran_csi_rs_cdm_nocdm) {
resource->cdm == srsran_csi_rs_cdm_nocdm) {
if (resource->density == srsran_csi_rs_resource_mapping_density_one || 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_even ||
resource->density == srsran_csi_rs_resource_mapping_density_dot5_odd) { 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) 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 && 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) { resource->density == srsran_csi_rs_resource_mapping_density_three && resource->cdm == srsran_csi_rs_cdm_nocdm) {
return 1; 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 // Row 2
if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->nof_ports == 1 && if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->cdm == srsran_csi_rs_cdm_nocdm) {
resource->cdm == srsran_csi_rs_cdm_nocdm) {
if (resource->density == srsran_csi_rs_resource_mapping_density_one || 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_even ||
resource->density == srsran_csi_rs_resource_mapping_density_dot5_odd) { 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; 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) uint32_t csi_rs_count(srsran_csi_rs_density_t density, uint32_t nprb)
{ {
switch (density) { switch (density) {
@ -705,7 +716,7 @@ int srsran_csi_rs_nzp_measure_trs(const srsran_carrier_nr_t* carrier,
float cfo_max = 0.0f; float cfo_max = 0.0f;
for (uint32_t i = 1; i < count; i++) { 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 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; float cfo_max_temp = 0.0f;
// Avoid zero division // Avoid zero division

@ -72,6 +72,31 @@ const char* srsran_rnti_type_str_short(srsran_rnti_type_t rnti_type)
return "unknown"; 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) const char* srsran_dci_format_nr_string(srsran_dci_format_nr_t format)
{ {
switch (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); 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 // Prevent zero division
if (cfg->pattern1.period_ms == 0 && cfg->pattern2.period_ms == 0) { if (cfg->pattern1.period_ms == 0 && cfg->pattern2.period_ms == 0) {
return false; 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)); (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 // Protect NULL pointer access
if (cfg == NULL) { if (cfg == NULL) {
return false; 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 // Prevent zero division
if (cfg->pattern1.period_ms == 0 && cfg->pattern2.period_ms == 0) { if (cfg->pattern1.period_ms == 0 && cfg->pattern2.period_ms == 0) {
return false; 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)); 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) int srsran_carrier_to_cell(const srsran_carrier_nr_t* carrier, srsran_cell_t* cell)
{ {
// Protect memory access // Protect memory access

@ -59,7 +59,21 @@ __attribute__((constructor)) static void srsran_dft_load()
#ifdef FFTW_WISDOM_FILE #ifdef FFTW_WISDOM_FILE
char full_path[256]; char full_path[256];
get_fftw_wisdom_file(full_path, sizeof(full_path)); 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 #else
printf("Warning: FFTW Wisdom file not defined\n"); printf("Warning: FFTW Wisdom file not defined\n");
#endif #endif
@ -71,7 +85,20 @@ __attribute__((destructor)) static void srsran_dft_exit()
#ifdef FFTW_WISDOM_FILE #ifdef FFTW_WISDOM_FILE
char full_path[256]; char full_path[256];
get_fftw_wisdom_file(full_path, sizeof(full_path)); 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 #endif
fftwf_cleanup(); fftwf_cleanup();
} }

@ -22,6 +22,11 @@
#include "srsran/phy/gnb/gnb_dl.h" #include "srsran/phy/gnb/gnb_dl.h"
#include <complex.h> #include <complex.h>
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) static int gnb_dl_alloc_prb(srsran_gnb_dl_t* q, uint32_t new_nof_prb)
{ {
if (q->max_prb < 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; 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++) { for (uint32_t i = 0; i < q->nof_tx_antennas; i++) {
srsran_ofdm_tx_sf(&q->fft[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) int srsran_gnb_dl_base_zero(srsran_gnb_dl_t* q)
{ {
if (q == NULL) { if (q == NULL) {

@ -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); q->sockfd = socket(AF_INET, type == SRSRAN_NETSINK_TCP ? SOCK_STREAM : SOCK_DGRAM, 0);
if (q->sockfd < 0) { if (q->sockfd < 0) {
perror("socket"); perror("socket");
return -1; return SRSRAN_ERROR;
} }
int enable = 1; int enable = 1;
@ -53,12 +53,15 @@ int srsran_netsink_init(srsran_netsink_t* q, const char* address, uint16_t port,
#endif #endif
q->servaddr.sin_family = AF_INET; 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->servaddr.sin_port = htons(port);
q->connected = false; q->connected = false;
q->type = type; q->type = type;
return 0; return SRSRAN_SUCCESS;
} }
void srsran_netsink_free(srsran_netsink_t* q) 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)) { if (fcntl(q->sockfd, F_SETFL, O_NONBLOCK)) {
perror("fcntl"); 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) 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 (!q->connected) {
if (connect(q->sockfd, &q->servaddr, sizeof(q->servaddr)) < 0) { if (connect(q->sockfd, &q->servaddr, sizeof(q->servaddr)) < 0) {
if (errno == ECONNREFUSED || errno == EINPROGRESS) { if (errno == ECONNREFUSED || errno == EINPROGRESS) {
return 0; return SRSRAN_SUCCESS;
} else { } else {
perror("connect"); perror("connect");
exit(-1); exit(-1);
return -1; return SRSRAN_ERROR;
} }
} else { } else {
q->connected = true; 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); q->sockfd = socket(AF_INET, q->type == SRSRAN_NETSINK_TCP ? SOCK_STREAM : SOCK_DGRAM, 0);
if (q->sockfd < 0) { if (q->sockfd < 0) {
perror("socket"); perror("socket");
return -1; return SRSRAN_ERROR;
} }
q->connected = false; q->connected = false;
return 0; return SRSRAN_SUCCESS;
} }
} }
} }

@ -39,7 +39,7 @@ int srsran_netsource_init(srsran_netsource_t* q, const char* address, uint16_t p
if (q->sockfd < 0) { if (q->sockfd < 0) {
perror("socket"); perror("socket");
return -1; return SRSRAN_ERROR;
} }
// Make sockets reusable // 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->type = type;
q->servaddr.sin_family = AF_INET; 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->servaddr.sin_port = htons(port);
if (bind(q->sockfd, (struct sockaddr*)&q->servaddr, sizeof(struct sockaddr_in))) { if (bind(q->sockfd, (struct sockaddr*)&q->servaddr, sizeof(struct sockaddr_in))) {
perror("bind"); perror("bind");
return -1; return SRSRAN_ERROR;
} }
q->connfd = 0; q->connfd = 0;
return 0; return SRSRAN_SUCCESS;
} }
void srsran_netsource_free(srsran_netsource_t* q) 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 (n == -1) {
if (errno == EAGAIN) { if (errno == EAGAIN) {
return 0; return SRSRAN_SUCCESS;
} else { } else {
return -1; return SRSRAN_ERROR;
} }
} else { } else {
return n; 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); q->connfd = accept(q->sockfd, (struct sockaddr*)&q->cliaddr, &clilen);
if (q->connfd < 0) { if (q->connfd < 0) {
perror("accept"); perror("accept");
return -1; return SRSRAN_ERROR;
} }
} }
int n = read(q->connfd, buffer, nbytes); 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"); printf("Connection closed\n");
close(q->connfd); close(q->connfd);
q->connfd = 0; q->connfd = 0;
return 0; return SRSRAN_SUCCESS;
} }
if (n == -1) { if (n == -1) {
perror("read"); perror("read");
@ -136,7 +139,7 @@ int srsran_netsource_set_nonblocking(srsran_netsource_t* q)
perror("fcntl"); perror("fcntl");
return -1; return -1;
} }
return 0; return SRSRAN_SUCCESS;
} }
int srsran_netsource_set_timeout(srsran_netsource_t* q, uint32_t microseconds) 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; t.tv_usec = microseconds;
if (setsockopt(q->sockfd, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(struct timeval))) { if (setsockopt(q->sockfd, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(struct timeval))) {
perror("setsockopt"); perror("setsockopt");
return -1; return SRSRAN_ERROR;
} }
return 0; return SRSRAN_SUCCESS;
} }

@ -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); srsran_ra_dl_nr_time_default_A(m, cfg->typeA_pos, grant);
} }
} else { } 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 // 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); return srsran_sliv_from_s_and_l(N_prb, start_rb, length_rb);
} }

@ -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 // 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 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_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 // Compute average RSRP
float rsrp_pss = SRSRAN_CSQABS(corr_pss); float rsrp_pss = SRSRAN_CSQABS(corr_pss);

@ -80,7 +80,7 @@ static void run_channel()
} }
// CFO // 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 // AWGN
srsran_channel_awgn_run_c(&awgn, buffer, buffer, sf_len); srsran_channel_awgn_run_c(&awgn, buffer, buffer, sf_len);

@ -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 // Print PDCCH blind search candidates
for (uint32_t i = 0; i < ue_dl->pdcch_info_count; i++) { 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]; 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;", "nof_bits=%d; crc=%s;",
srsran_rnti_type_str_short(info->dci_ctx.rnti_type),
info->dci_ctx.rnti, info->dci_ctx.rnti,
info->dci_ctx.coreset_id, 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.ncce,
info->dci_ctx.location.L, info->dci_ctx.location.L,
info->measure.epre_dBfs, info->measure.epre_dBfs,

@ -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); INFO("Calibration samples received start at %ld + %f", q->last_timestamp.full_secs, q->last_timestamp.frac_secs);
// round to nearest second // 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); srsran_timestamp_copy(&ts_next_rx, &q->last_timestamp);
ts_next_rx.full_secs++; ts_next_rx.full_secs++;
ts_next_rx.frac_secs = 0.0; 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 // 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_tmp, 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, 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", DEBUG("Difference between first recv is %ld + %f, realigning %" PRIu64 " samples\n",
ts_next_rx.full_secs, ts_next_rx_tmp.full_secs,
ts_next_rx.frac_secs, ts_next_rx_tmp.frac_secs,
align_len); align_len);
// receive align_len samples into dummy_buffer, make sure to not exceed buffer len // receive align_len samples into dummy_buffer, make sure to not exceed buffer len
uint32_t sample_count = 0; uint32_t sample_count = 0;
while (sample_count < align_len) { while (align_len > q->sf_len) {
uint32_t actual_rx_len = SRSRAN_MIN(align_len, DUMMY_BUFFER_NUM_SAMPLES); uint32_t actual_rx_len = SRSRAN_MIN(align_len, q->sf_len);
actual_rx_len = SRSRAN_MIN(align_len - sample_count, actual_rx_len);
q->recv_callback(q->stream, dummy_offset_buffer, actual_rx_len, &q->last_timestamp); 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); 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; time_t t_cur = rx_timestamp->full_secs;
DEBUG("t_cur=%ld", t_cur); DEBUG("t_cur=%ld", t_cur);
// time_t of reference UTC time on 1. Jan 1900 at 0:00 // 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 // If we put this date in https://www.epochconverter.com it returns a negative number (-2208988800)
time_t t_ref = {0}; // as epoch time starts at 1. Jan 1970 at 0:00
#if 0 uint64_t epoch_offset_3gpp = 2208988800;
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);
static const uint32_t MSECS_PER_SEC = 1000; static const uint32_t MSECS_PER_SEC = 1000;
DEBUG("diff=%f", difftime(t_cur, t_ref)); uint64_t time_3gpp_secs = t_cur + epoch_offset_3gpp;
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);
// convert to ms and add fractional part // convert to ms and add fractional part
double time_diff_msecs = time_diff_secs * MSECS_PER_SEC + rx_timestamp->frac_secs; uint64_t time_3gpp_msecs = (time_3gpp_secs + rx_timestamp->frac_secs) * MSECS_PER_SEC;
DEBUG("time diff in ms %f", time_diff_msecs); 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 // 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->frame_number = (uint32_t)(((uint64_t)floor(0.1 * (time_3gpp_msecs - q->sfn_offset))) % 1024);
q->sf_idx = ((uint32_t)floor(time_diff_msecs - q->sfn_offset)) % 10; q->sf_idx = (uint32_t)(((uint64_t)floor(time_3gpp_msecs - q->sfn_offset)) % 10);
return SRSRAN_SUCCESS; return SRSRAN_SUCCESS;
} }

@ -110,7 +110,7 @@ void srsran_ue_ul_nr_set_freq_offset(srsran_ue_ul_nr_t* q, float freq_offset_hz)
return; 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, int srsran_ue_ul_nr_encode_pusch(srsran_ue_ul_nr_t* q,

@ -212,13 +212,19 @@ uint32_t rlc_am_lte::get_bearer()
rlc_bearer_metrics_t rlc_am_lte::get_metrics() rlc_bearer_metrics_t rlc_am_lte::get_metrics()
{ {
// update values that aren't calculated on the fly // update values that aren't calculated on the fly
metrics.rx_latency_ms = rx.get_sdu_rx_latency_ms(); uint32_t latency = rx.get_sdu_rx_latency_ms();
metrics.rx_buffered_bytes = rx.get_rx_buffered_bytes(); uint32_t buffered_bytes = rx.get_rx_buffered_bytes();
std::lock_guard<std::mutex> lock(metrics_mutex);
metrics.rx_latency_ms = latency;
metrics.rx_buffered_bytes = buffered_bytes;
return metrics; return metrics;
} }
void rlc_am_lte::reset_metrics() void rlc_am_lte::reset_metrics()
{ {
std::lock_guard<std::mutex> lock(metrics_mutex);
metrics = {}; metrics = {};
} }
@ -229,6 +235,7 @@ void rlc_am_lte::reset_metrics()
void rlc_am_lte::write_sdu(unique_byte_buffer_t sdu) void rlc_am_lte::write_sdu(unique_byte_buffer_t sdu)
{ {
if (tx.write_sdu(std::move(sdu)) == SRSRAN_SUCCESS) { if (tx.write_sdu(std::move(sdu)) == SRSRAN_SUCCESS) {
std::lock_guard<std::mutex> lock(metrics_mutex);
metrics.num_tx_sdus++; 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) void rlc_am_lte::discard_sdu(uint32_t discard_sn)
{ {
tx.discard_sdu(discard_sn); tx.discard_sdu(discard_sn);
std::lock_guard<std::mutex> lock(metrics_mutex);
metrics.num_lost_sdus++; 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 rlc_am_lte::read_pdu(uint8_t* payload, uint32_t nof_bytes)
{ {
uint32_t read_bytes = tx.read_pdu(payload, nof_bytes); uint32_t read_bytes = tx.read_pdu(payload, nof_bytes);
std::lock_guard<std::mutex> lock(metrics_mutex);
metrics.num_tx_pdus++; metrics.num_tx_pdus++;
metrics.num_tx_pdu_bytes += read_bytes; metrics.num_tx_pdu_bytes += read_bytes;
return read_bytes; return read_bytes;
} }
void rlc_am_lte::write_pdu(uint8_t* payload, uint32_t nof_bytes) void rlc_am_lte::write_pdu(uint8_t* payload, uint32_t nof_bytes)
{ {
rx.write_pdu(payload, nof_bytes); rx.write_pdu(payload, nof_bytes);
std::lock_guard<std::mutex> lock(metrics_mutex);
metrics.num_rx_pdus++; metrics.num_rx_pdus++;
metrics.num_rx_pdu_bytes += nof_bytes; 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()); pdcp_sns.push_back(segment.pdcp_sn());
} }
parent->pdcp->notify_failure(parent->lcid, pdcp_sns); parent->pdcp->notify_failure(parent->lcid, pdcp_sns);
std::lock_guard<std::mutex> lock(parent->metrics_mutex);
parent->metrics.num_lost_pdus++; 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()) std::chrono::high_resolution_clock::now() - rx_sdu->get_timestamp())
.count()); .count());
parent->pdcp->write_pdu(parent->lcid, std::move(rx_sdu)); parent->pdcp->write_pdu(parent->lcid, std::move(rx_sdu));
parent->metrics.num_rx_sdus++; {
std::lock_guard<std::mutex> lock(parent->metrics_mutex);
parent->metrics.num_rx_sdus++;
}
rx_sdu = srsran::make_byte_buffer(); rx_sdu = srsran::make_byte_buffer();
if (rx_sdu == nullptr) { 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()) std::chrono::high_resolution_clock::now() - rx_sdu->get_timestamp())
.count()); .count());
parent->pdcp->write_pdu(parent->lcid, std::move(rx_sdu)); parent->pdcp->write_pdu(parent->lcid, std::move(rx_sdu));
parent->metrics.num_rx_sdus++; {
std::lock_guard<std::mutex> lock(parent->metrics_mutex);
parent->metrics.num_rx_sdus++;
}
rx_sdu = srsran::make_byte_buffer(); rx_sdu = srsran::make_byte_buffer();
if (rx_sdu == NULL) { 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()) { if (not lock.owns_lock()) {
return 0; return 0;
} }
rlc_status_pdu_t status = {}; rlc_status_pdu_t status = {};
status.ack_sn = vr_ms; status.ack_sn = vr_ms;
uint32_t i = vr_r; uint32_t i = vr_r;
while (RX_MOD_BASE(i) < RX_MOD_BASE(vr_ms) && status.N_nack < RLC_AM_WINDOW_SIZE) { while (RX_MOD_BASE(i) < RX_MOD_BASE(vr_ms) && status.N_nack < RLC_AM_WINDOW_SIZE) {
if (not rx_window.has_sn(i)) { if (not rx_window.has_sn(i)) {
status.N_nack++; status.N_nack++;

@ -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_slots = 2;
tdd_ul_dl_cfg_common.pattern1.nrof_ul_symbols = 4; tdd_ul_dl_cfg_common.pattern1.nrof_ul_symbols = 4;
srsran_tdd_config_nr_t srsran_tdd_config_nr; srsran_duplex_config_nr_t srsran_duplex_config_nr;
TESTASSERT(make_phy_tdd_cfg(tdd_ul_dl_cfg_common, &srsran_tdd_config_nr) == true); TESTASSERT(make_phy_tdd_cfg(tdd_ul_dl_cfg_common, &srsran_duplex_config_nr) == true);
TESTASSERT(srsran_tdd_config_nr.pattern1.period_ms == 10); TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.period_ms == 10);
TESTASSERT(srsran_tdd_config_nr.pattern1.nof_dl_slots == 7); TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.nof_dl_slots == 7);
TESTASSERT(srsran_tdd_config_nr.pattern1.nof_dl_symbols == 6); TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.nof_dl_symbols == 6);
TESTASSERT(srsran_tdd_config_nr.pattern1.nof_ul_slots == 2); TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.nof_ul_slots == 2);
TESTASSERT(srsran_tdd_config_nr.pattern1.nof_ul_symbols == 4); TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.nof_ul_symbols == 4);
TESTASSERT(srsran_tdd_config_nr.pattern2.period_ms == 0); TESTASSERT(srsran_duplex_config_nr.tdd.pattern2.period_ms == 0);
return SRSRAN_SUCCESS; return SRSRAN_SUCCESS;
} }

@ -294,7 +294,7 @@ int test_radio_bearer_config()
return SRSRAN_SUCCESS; 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" 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" "\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; 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<rach_cfg_common_s>::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() int main()
{ {
auto& asn1_logger = srslog::fetch_basic_logger("ASN1", false); 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_mrdc_capabilities() == SRSRAN_SUCCESS);
TESTASSERT(test_ue_rrc_reconfiguration() == SRSRAN_SUCCESS); TESTASSERT(test_ue_rrc_reconfiguration() == SRSRAN_SUCCESS);
TESTASSERT(test_radio_bearer_config() == 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(); srslog::flush();

@ -170,7 +170,11 @@ enable = false
# pusch_mcs: Optional fixed PUSCH MCS (ignores reported CQIs if specified) # pusch_mcs: Optional fixed PUSCH MCS (ignores reported CQIs if specified)
# pusch_max_mcs: Optional PUSCH MCS limit # pusch_max_mcs: Optional PUSCH MCS limit
# min_nof_ctrl_symbols: Minimum number of control symbols # 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 # 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_dl_cqi: Maximum shift in CQI for adaptive DL link
# max_delta_ul_snr: Maximum shift in UL SNR for adaptive UL 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 #min_nof_ctrl_symbols = 1
#max_nof_ctrl_symbols = 3 #max_nof_ctrl_symbols = 3
#pucch_multiplex_enable = false #pucch_multiplex_enable = false
#pucch_harq_max_rb = 0
#target_bler = 0.05 #target_bler = 0.05
#max_delta_dl_cqi = 5 #max_delta_dl_cqi = 5
#max_delta_ul_snr = 5 #max_delta_ul_snr = 5

@ -33,12 +33,14 @@
#include <string> #include <string>
#include "phy/phy.h" #include "phy/phy.h"
#include "x2_adapter.h"
#include "srsran/radio/radio.h" #include "srsran/radio/radio.h"
#include "srsenb/hdr/phy/enb_phy_base.h" #include "srsenb/hdr/phy/enb_phy_base.h"
#include "srsenb/hdr/stack/enb_stack_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.h"
#include "srsenb/hdr/stack/rrc/rrc_config_nr.h"
#include "srsenb/hdr/stack/mac/sched_interface.h" #include "srsenb/hdr/stack/mac/sched_interface.h"
#include "srsran/common/bcd_helpers.h" #include "srsran/common/bcd_helpers.h"
@ -48,6 +50,7 @@
#include "srsran/common/security.h" #include "srsran/common/security.h"
#include "srsran/interfaces/enb_command_interface.h" #include "srsran/interfaces/enb_command_interface.h"
#include "srsran/interfaces/enb_metrics_interface.h" #include "srsran/interfaces/enb_metrics_interface.h"
#include "srsran/interfaces/enb_time_interface.h"
#include "srsran/interfaces/ue_interfaces.h" #include "srsran/interfaces/ue_interfaces.h"
#include "srsran/srslog/srslog.h" #include "srsran/srslog/srslog.h"
#include "srsran/system/sys_metrics_processor.h" #include "srsran/system/sys_metrics_processor.h"
@ -126,7 +129,7 @@ struct rrc_cfg_t;
Main eNB class 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: public:
enb(srslog::sink& log_sink); enb(srslog::sink& log_sink);
@ -149,6 +152,8 @@ public:
void toggle_padding() override; void toggle_padding() override;
void tti_clock() override;
private: private:
const static int ENB_POOL_SIZE = 1024 * 10; const static int ENB_POOL_SIZE = 1024 * 10;
@ -160,11 +165,14 @@ private:
all_args_t args = {}; all_args_t args = {};
bool started = false; bool started = false;
phy_cfg_t phy_cfg = {}; phy_cfg_t phy_cfg = {};
rrc_cfg_t rrc_cfg = {}; rrc_cfg_t rrc_cfg = {};
rrc_nr_cfg_t rrc_nr_cfg = {};
// eNB components // eNB components
std::unique_ptr<enb_stack_base> stack = nullptr; x2_adapter x2;
std::unique_ptr<enb_stack_base> eutra_stack = nullptr;
std::unique_ptr<enb_stack_base> nr_stack = nullptr;
std::unique_ptr<srsran::radio_base> radio = nullptr; std::unique_ptr<srsran::radio_base> radio = nullptr;
std::unique_ptr<enb_phy_base> phy = nullptr; std::unique_ptr<enb_phy_base> phy = nullptr;

@ -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_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; } 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 set_sched_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs) override {}
void tti_clock() override {}
}; };
srsran::phy_common_interface& common; srsran::phy_common_interface& common;

@ -27,6 +27,7 @@
#include "srsenb/hdr/phy/enb_phy_base.h" #include "srsenb/hdr/phy/enb_phy_base.h"
#include "srsran/common/trace.h" #include "srsran/common/trace.h"
#include "srsran/interfaces/enb_metrics_interface.h" #include "srsran/interfaces/enb_metrics_interface.h"
#include "srsran/interfaces/enb_time_interface.h"
#include "srsran/interfaces/radio_interfaces.h" #include "srsran/interfaces/radio_interfaces.h"
#include "srsran/radio/radio.h" #include "srsran/radio/radio.h"
#include "srsran/srslog/srslog.h" #include "srsran/srslog/srslog.h"
@ -46,12 +47,14 @@ public:
int init(const phy_args_t& args, int init(const phy_args_t& args,
const phy_cfg_t& cfg, const phy_cfg_t& cfg,
srsran::radio_interface_phy* radio_, 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, int init(const phy_args_t& args,
const phy_cfg_t& cfg, const phy_cfg_t& cfg,
srsran::radio_interface_phy* radio_, srsran::radio_interface_phy* radio_,
stack_interface_phy_lte* stack_lte_, 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; void stop() override;
std::string get_type() override { return "lte"; }; std::string get_type() override { return "lte"; };

@ -27,6 +27,7 @@
#include "srsenb/hdr/phy/lte/worker_pool.h" #include "srsenb/hdr/phy/lte/worker_pool.h"
#include "srsenb/hdr/phy/nr/worker_pool.h" #include "srsenb/hdr/phy/nr/worker_pool.h"
#include "srsran/config.h" #include "srsran/config.h"
#include "srsran/interfaces/enb_time_interface.h"
#include "srsran/phy/channel/channel.h" #include "srsran/phy/channel/channel.h"
#include "srsran/radio/radio.h" #include "srsran/radio/radio.h"
#include <atomic> #include <atomic>
@ -37,7 +38,7 @@ class txrx final : public srsran::thread
{ {
public: public:
txrx(srslog::basic_logger& logger); txrx(srslog::basic_logger& logger);
bool init(stack_interface_phy_lte* stack_, bool init(enb_time_interface* enb_,
srsran::radio_interface_phy* radio_handler, srsran::radio_interface_phy* radio_handler,
lte::worker_pool* lte_workers_, lte::worker_pool* lte_workers_,
phy_common* worker_com, phy_common* worker_com,
@ -49,7 +50,7 @@ public:
private: private:
void run_thread() override; void run_thread() override;
stack_interface_phy_lte* stack = nullptr; enb_time_interface* enb = nullptr;
srsran::radio_interface_phy* radio_h = nullptr; srsran::radio_interface_phy* radio_h = nullptr;
srslog::basic_logger& logger; srslog::basic_logger& logger;
lte::worker_pool* lte_workers = nullptr; lte::worker_pool* lte_workers = nullptr;

@ -69,7 +69,6 @@ typedef struct {
} stack_log_args_t; } stack_log_args_t;
typedef struct { typedef struct {
std::string type;
uint32_t sync_queue_size; // Max allowed difference between PHY and Stack clocks (in TTI) uint32_t sync_queue_size; // Max allowed difference between PHY and Stack clocks (in TTI)
uint32_t gtpu_indirect_tunnel_timeout_msec; uint32_t gtpu_indirect_tunnel_timeout_msec;
mac_args_t mac; mac_args_t mac;
@ -95,6 +94,8 @@ public:
virtual void toggle_padding() = 0; virtual void toggle_padding() = 0;
// eNB metrics interface // eNB metrics interface
virtual bool get_metrics(stack_metrics_t* metrics) = 0; virtual bool get_metrics(stack_metrics_t* metrics) = 0;
virtual void tti_clock() = 0;
}; };
} // namespace srsenb } // namespace srsenb

@ -28,9 +28,7 @@
#define SRSRAN_ENB_STACK_LTE_H #define SRSRAN_ENB_STACK_LTE_H
#include "mac/mac.h" #include "mac/mac.h"
#include "mac/nr/mac_nr.h"
#include "rrc/rrc.h" #include "rrc/rrc.h"
#include "rrc/rrc_nr.h"
#include "s1ap/s1ap.h" #include "s1ap/s1ap.h"
#include "srsran/common/task_scheduler.h" #include "srsran/common/task_scheduler.h"
#include "upper/gtpu.h" #include "upper/gtpu.h"
@ -49,7 +47,7 @@ class gtpu_pdcp_adapter;
class enb_stack_lte final : public enb_stack_base, class enb_stack_lte final : public enb_stack_base,
public stack_interface_phy_lte, public stack_interface_phy_lte,
public stack_interface_phy_nr, public rrc_eutra_interface_rrc_nr,
public srsran::thread public srsran::thread
{ {
public: public:
@ -57,12 +55,7 @@ public:
~enb_stack_lte() final; ~enb_stack_lte() final;
// eNB stack base interface // eNB stack base interface
int init(const stack_args_t& args_, int init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_, phy_interface_stack_lte* phy_, x2_interface* x2_);
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_);
void stop() final; void stop() final;
std::string get_type() final; std::string get_type() final;
bool get_metrics(stack_metrics_t* metrics) final; bool get_metrics(stack_metrics_t* metrics) final;
@ -124,25 +117,16 @@ public:
void toggle_padding() override { mac.toggle_padding(); } void toggle_padding() override { mac.toggle_padding(); }
void tti_clock() override; void tti_clock() override;
// mac_interface_phy_nr // rrc_eutra_interface_rrc_nr
int slot_indication(const srsran_slot_cfg_t& slot_cfg) override { return mac_nr.slot_indication(slot_cfg); } void sgnb_addition_ack(uint16_t eutra_rnti, sgnb_addition_ack_params_t params) final
int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, srsenb::mac_interface_phy_nr::dl_sched_t& dl_sched) override
{ {
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: private:
static const int STACK_MAIN_THREAD_PRIO = 4; static const int STACK_MAIN_THREAD_PRIO = 4;
@ -164,10 +148,6 @@ private:
srslog::basic_logger& s1ap_logger; srslog::basic_logger& s1ap_logger;
srslog::basic_logger& gtpu_logger; srslog::basic_logger& gtpu_logger;
srslog::basic_logger& stack_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 // PCAP and trace option
srsran::mac_pcap mac_pcap; srsran::mac_pcap mac_pcap;
@ -189,15 +169,8 @@ private:
srsenb::gtpu gtpu; srsenb::gtpu gtpu;
srsenb::s1ap s1ap; 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 // RAT-specific interfaces
phy_interface_stack_lte* phy = nullptr; phy_interface_stack_lte* phy = nullptr;
phy_interface_stack_nr* phy_nr = nullptr;
// state // state
std::atomic<bool> started{false}; std::atomic<bool> started{false};

@ -27,16 +27,15 @@
#ifndef SRSRAN_GNB_STACK_NR_H #ifndef SRSRAN_GNB_STACK_NR_H
#define 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/mac/nr/mac_nr.h"
#include "srsenb/hdr/stack/rrc/rrc_nr.h" #include "srsenb/hdr/stack/rrc/rrc_nr.h"
#include "srsenb/hdr/stack/upper/pdcp_nr.h" #include "srsenb/hdr/stack/upper/pdcp_nr.h"
#include "srsenb/hdr/stack/upper/rlc_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 "upper/sdap.h"
#include "enb_stack_base.h" #include "enb_stack_base.h"
#include "srsenb/hdr/enb.h"
#include "srsran/interfaces/gnb_interfaces.h" #include "srsran/interfaces/gnb_interfaces.h"
// This is needed for GW // 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_phy_nr,
public stack_interface_mac, public stack_interface_mac,
public srsue::stack_interface_gw, public srsue::stack_interface_gw,
public rrc_nr_interface_rrc,
public pdcp_interface_gtpu, // for user-plane over X2
public srsran::thread public srsran::thread
{ {
public: public:
explicit gnb_stack_nr(); explicit gnb_stack_nr(srslog::sink& log_sink);
~gnb_stack_nr() final; ~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_,
int init(const srsenb::stack_args_t& args_, const rrc_nr_cfg_t& rrc_cfg_); const rrc_nr_cfg_t& rrc_cfg_,
phy_interface_stack_nr* phy_,
x2_interface* x2_);
// eNB stack base interface // eNB stack base interface
void stop() final; void stop() final;
@ -71,12 +74,12 @@ public:
void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) override; 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 has_active_radio_bearer(uint32_t eps_bearer_id) override;
bool switch_on(); bool switch_on();
void run_tti(uint32_t tti); void tti_clock() override;
// MAC interface to trigger processing of received PDUs // MAC interface to trigger processing of received PDUs
void process_pdus() final; 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 slot_indication(const srsran_slot_cfg_t& slot_cfg) override;
int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) override; int get_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; 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; 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<uint32_t, srsran::unique_byte_buffer_t> get_buffered_pdus(uint16_t rnti, uint32_t lcid) final
{
return pdcp.get_buffered_pdus(rnti, lcid);
}
private: private:
void run_thread() final; void run_thread() final;
void run_tti_impl(uint32_t tti); void tti_clock_impl();
// args // args
srsenb::stack_args_t args = {}; srsenb::stack_args_t args = {};
phy_interface_stack_nr* phy = nullptr; phy_interface_stack_nr* phy = nullptr;
srslog::basic_logger& rrc_logger;
srslog::basic_logger& mac_logger;
srslog::basic_logger& rlc_logger; srslog::basic_logger& rlc_logger;
srslog::basic_logger& pdcp_logger;
srslog::basic_logger& stack_logger;
// task scheduling // task scheduling
static const int STACK_MAIN_THREAD_PRIO = 4; 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; srsran::task_multiqueue::queue_handle sync_task_queue, ue_task_queue, gw_task_queue, mac_task_queue;
// derived // derived
std::unique_ptr<mac_nr> m_mac; srsenb::mac_nr mac;
std::unique_ptr<rlc_nr> m_rlc; srsenb::rlc rlc;
std::unique_ptr<pdcp_nr> m_pdcp; srsenb::pdcp pdcp;
std::unique_ptr<sdap> m_sdap; srsenb::rrc_nr rrc;
std::unique_ptr<rrc_nr> m_rrc; // std::unique_ptr<sdap> m_sdap;
std::unique_ptr<srsue::gw> m_gw;
// std::unique_ptr<ngap> m_ngap;
// std::unique_ptr<srsenb::gtpu> m_gtpu;
// state // state
bool running = false; std::atomic<bool> running = {false};
uint32_t current_tti = 10240;
}; };
} // namespace srsenb } // namespace srsenb

@ -69,7 +69,7 @@ public:
struct cell_cfg_t { struct cell_cfg_t {
srsran_carrier_nr_t carrier = {}; 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::phy_cfg_nr_t::ssb_cfg_t ssb = {};
srsran::bounded_vector<bwp_cfg_t, SCHED_NR_MAX_BWP_PER_CELL> bwps{1}; // idx0 for BWP-common srsran::bounded_vector<bwp_cfg_t, SCHED_NR_MAX_BWP_PER_CELL> bwps{1}; // idx0 for BWP-common
}; };

@ -67,6 +67,7 @@ public:
int max_aggr_level = 3; int max_aggr_level = 3;
bool adaptive_aggr_level = false; bool adaptive_aggr_level = false;
bool pucch_mux_enabled = false; bool pucch_mux_enabled = false;
int pucch_harq_max_rb = 0;
float target_bler = 0.05; float target_bler = 0.05;
float max_delta_dl_cqi = 5; float max_delta_dl_cqi = 5;
float max_delta_ul_snr = 5; float max_delta_ul_snr = 5;

@ -208,6 +208,7 @@ public:
*/ */
void start() void start()
{ {
std::lock_guard<std::mutex> lock(mutex);
// Transition to idle only if the current state is idle // Transition to idle only if the current state is idle
if (state == state_idle) { if (state == state_idle) {
state = state_measure; state = state_measure;

@ -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_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); 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); 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); 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); srsran::unique_byte_buffer_t release_pdu(uint32_t tti, uint32_t enb_cc_idx);
void clear_old_buffers(uint32_t tti); void clear_old_buffers(uint32_t tti);
std::mutex metrics_mutex = {}; std::mutex metrics_mutex = {};
void metrics_read(mac_ue_metrics_t* metrics_); void metrics_read(mac_ue_metrics_t* metrics_);
void metrics_rx(bool crc, uint32_t tbs); void metrics_rx(bool crc, uint32_t tbs);
void metrics_tx(bool crc, uint32_t tbs); void metrics_tx(bool crc, uint32_t tbs);
void metrics_phr(float phr); void metrics_phr(float phr);
void metrics_dl_ri(uint32_t dl_cqi); void metrics_dl_ri(uint32_t dl_cqi);
void metrics_dl_pmi(uint32_t dl_cqi); void metrics_dl_pmi(uint32_t dl_cqi);
void metrics_dl_cqi(uint32_t dl_cqi); void metrics_dl_cqi(uint32_t dl_cqi);
void metrics_cnt(); void metrics_cnt();
uint32_t read_pdu(uint32_t lcid, uint8_t* payload, uint32_t requested_bytes) final; uint32_t read_pdu(uint32_t lcid, uint8_t* payload, uint32_t requested_bytes) final;
@ -197,11 +197,11 @@ private:
srslog::basic_logger& logger; srslog::basic_logger& logger;
sched_interface* sched = nullptr; sched_interface* sched = nullptr;
srsran::mac_pcap* pcap = nullptr; srsran::mac_pcap* pcap = nullptr;
srsran::mac_pcap_net* pcap_net = nullptr; srsran::mac_pcap_net* pcap_net = nullptr;
uint64_t conres_id = 0; uint64_t conres_id = 0;
uint16_t rnti = 0; uint16_t rnti = 0;
uint32_t last_tti = 0; std::atomic<uint32_t> last_tti{0};
uint32_t nof_failures = 0; uint32_t nof_failures = 0;
std::atomic<bool> active_state{true}; std::atomic<bool> active_state{true};

@ -35,6 +35,7 @@
#include "srsran/common/task_scheduler.h" #include "srsran/common/task_scheduler.h"
#include "srsran/common/timeout.h" #include "srsran/common/timeout.h"
#include "srsran/interfaces/enb_rrc_interfaces.h" #include "srsran/interfaces/enb_rrc_interfaces.h"
#include "srsran/interfaces/enb_x2_interfaces.h"
#include "srsran/srslog/srslog.h" #include "srsran/srslog/srslog.h"
#include <map> #include <map>

@ -36,6 +36,7 @@
#include "srsran/interfaces/enb_pdcp_interfaces.h" #include "srsran/interfaces/enb_pdcp_interfaces.h"
#include "srsran/interfaces/enb_rlc_interfaces.h" #include "srsran/interfaces/enb_rlc_interfaces.h"
#include "srsran/interfaces/enb_rrc_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_interfaces.h"
#include "srsran/interfaces/gnb_mac_interfaces.h" #include "srsran/interfaces/gnb_mac_interfaces.h"
#include "srsran/interfaces/gnb_ngap_interfaces.h" #include "srsran/interfaces/gnb_ngap_interfaces.h"
@ -126,7 +127,9 @@ public:
uint16_t rnti = SRSRAN_INVALID_RNTI; uint16_t rnti = SRSRAN_INVALID_RNTI;
int pack_rrc_reconfiguraiton(asn1::dyn_octstring& packed_rrc_reconfig); 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 pack_nr_radio_bearer_config(asn1::dyn_octstring& packed_nr_bearer_config);
int add_drb(); int add_drb();

@ -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<uint32_t, srsran::unique_byte_buffer_t> 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

@ -12,9 +12,9 @@
// t_reordering = 35; // t_reordering = 35;
// t_status_prohibit = 0; // t_status_prohibit = 0;
// }; // };
// }; // enb_specific = {
// enb_specific = { // dl_max_retx_thresh = 32;
// dl_max_retx_thresh = 32; // };
// }; // };
// } // }
@ -30,9 +30,9 @@
// t_reordering = 35; // t_reordering = 35;
// t_status_prohibit = 0; // t_status_prohibit = 0;
// }; // };
// }; // enb_specific = {
// enb_specific = { // dl_max_retx_thresh = 32;
// dl_max_retx_thresh = 32; // };
// }; // };
// } // }

@ -39,7 +39,8 @@ enb::enb(srslog::sink& log_sink) :
enb::~enb() enb::~enb()
{ {
stack.reset(); eutra_stack.reset();
nr_stack.reset();
} }
int enb::init(const all_args_t& args_) 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); srsran::byte_buffer_pool::get_instance()->enable_logger(true);
// Create layers // Create layers
if (args.stack.type == "lte") { std::unique_ptr<enb_stack_lte> tmp_eutra_stack;
std::unique_ptr<enb_stack_lte> lte_stack(new enb_stack_lte(log_sink)); if (not rrc_cfg.cell_list.empty()) {
if (!lte_stack) { // add EUTRA stack
srsran::console("Error creating eNB stack.\n"); 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; return SRSRAN_ERROR;
} }
x2.set_eutra_stack(tmp_eutra_stack.get());
}
std::unique_ptr<srsran::radio> lte_radio = std::unique_ptr<srsran::radio>(new srsran::radio); std::unique_ptr<gnb_stack_nr> tmp_nr_stack;
if (!lte_radio) { if (not rrc_cfg.cell_list_nr.empty()) {
srsran::console("Error creating radio multi instance.\n"); // 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; return SRSRAN_ERROR;
} }
x2.set_nr_stack(tmp_nr_stack.get());
}
std::unique_ptr<srsenb::phy> lte_phy = std::unique_ptr<srsenb::phy>(new srsenb::phy(log_sink)); // Radio and PHY are RAT agnostic
if (!lte_phy) { std::unique_ptr<srsran::radio> tmp_radio = std::unique_ptr<srsran::radio>(new srsran::radio);
srsran::console("Error creating LTE PHY instance.\n"); if (tmp_radio == nullptr) {
return SRSRAN_ERROR; srsran::console("Error creating radio multi instance.\n");
} return SRSRAN_ERROR;
}
if (ret == SRSRAN_SUCCESS) { std::unique_ptr<srsenb::phy> tmp_phy = std::unique_ptr<srsenb::phy>(new srsenb::phy(log_sink));
if (lte_stack->init(args.stack, rrc_cfg, lte_phy.get(), lte_phy.get()) != SRSRAN_SUCCESS) { if (tmp_phy == nullptr) {
srsran::console("Error initializing stack.\n"); srsran::console("Error creating PHY instance.\n");
ret = SRSRAN_ERROR; return SRSRAN_ERROR;
} }
}
// Init Radio // initialize layers, if they exist
if (lte_radio->init(args.rf, lte_phy.get())) { if (tmp_eutra_stack) {
srsran::console("Error initializing radio.\n"); if (tmp_eutra_stack->init(args.stack, rrc_cfg, tmp_phy.get(), &x2) != SRSRAN_SUCCESS) {
return SRSRAN_ERROR; srsran::console("Error initializing EUTRA stack.\n");
ret = SRSRAN_ERROR;
} }
}
// Only Init PHY if radio could be initialized if (tmp_nr_stack) {
if (ret == SRSRAN_SUCCESS) { if (tmp_nr_stack->init(args.stack, rrc_nr_cfg, tmp_phy.get(), &x2) != SRSRAN_SUCCESS) {
if (lte_phy->init(args.phy, phy_cfg, lte_radio.get(), lte_stack.get(), *lte_stack)) { srsran::console("Error initializing NR stack.\n");
srsran::console("Error initializing PHY.\n"); ret = SRSRAN_ERROR;
ret = SRSRAN_ERROR;
}
} }
}
stack = std::move(lte_stack); // Init Radio
phy = std::move(lte_phy); if (tmp_radio->init(args.rf, tmp_phy.get())) {
radio = std::move(lte_radio); srsran::console("Error initializing radio.\n");
} else {
srsran::console("Stack type %s not supported.\n", args.stack.type.c_str());
return SRSRAN_ERROR; 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 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. // Now that everything is setup, log sector start events.
@ -136,8 +161,12 @@ void enb::stop()
phy->stop(); phy->stop();
} }
if (stack) { if (eutra_stack) {
stack->stop(); eutra_stack->stop();
}
if (nr_stack) {
nr_stack->stop();
} }
if (radio) { if (radio) {
@ -176,7 +205,9 @@ bool enb::get_metrics(enb_metrics_t* m)
{ {
radio->get_metrics(&m->rf); radio->get_metrics(&m->rf);
phy->get_metrics(m->phy); phy->get_metrics(m->phy);
stack->get_metrics(&m->stack); if (eutra_stack) {
eutra_stack->get_metrics(&m->stack);
}
m->running = started; m->running = started;
m->sys = sys_proc.get_metrics(); m->sys = sys_proc.get_metrics();
return true; return true;
@ -209,7 +240,19 @@ std::string enb::get_build_string()
void enb::toggle_padding() 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 } // namespace srsenb

@ -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_)); cell_cnfg.add_field(new rr_sections::cell_list_section(args_, rrc_cfg_));
// NR RRC and cell config section // NR RRC and cell config section
bool nr_cell_cnfg_present = false;
parser::section nr_cell_cnfg("nr_cell_list"); 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_)); nr_cell_cnfg.add_field(new rr_sections::nr_cell_list_section(args_, rrc_cfg_));
// Run parser with two sections // 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 // auto-detect UL frequency
if (cfg.ul_earfcn == 0) { if (cfg.ul_earfcn == 0) {
// derive UL ARFCN from given DL ARFCN // 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); cfg.ul_earfcn = band_helper.get_ul_arfcn_from_dl_arfcn(cfg.dl_earfcn);
srsran_duplex_mode_t nr_duplex = band_helper.get_duplex_mode(nr_band); if (cfg.ul_earfcn == 0) {
if (nr_duplex == SRSRAN_DUPLEX_MODE_TDD) { ERROR("Can't derive UL ARFCN from DL ARFCN %d", cfg.dl_earfcn);
cfg.ul_earfcn = cfg.dl_earfcn;
} else {
ERROR("Can't derive UL ARFCN from DL ARFCN");
return SRSRAN_ERROR; return SRSRAN_ERROR;
} }
} }

@ -75,8 +75,6 @@ void parse_args(all_args_t* args, int argc, char* argv[])
// Command line or config file options // Command line or config file options
bpo::options_description common("Configuration options"); bpo::options_description common("Configuration options");
common.add_options() common.add_options()
("enb.stack", bpo::value<string>(&args->stack.type)->default_value("lte"), "Type of the upper stack [lte, nr]")
("enb.enb_id", bpo::value<string>(&enb_id)->default_value("0x0"), "eNodeB ID") ("enb.enb_id", bpo::value<string>(&enb_id)->default_value("0x0"), "eNodeB ID")
("enb.name", bpo::value<string>(&args->stack.s1ap.enb_name)->default_value("srsenb01"), "eNodeB Name") ("enb.name", bpo::value<string>(&args->stack.s1ap.enb_name)->default_value("srsenb01"), "eNodeB Name")
("enb.mcc", bpo::value<string>(&mcc)->default_value("001"), "Mobile Country Code") ("enb.mcc", bpo::value<string>(&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<uint32_t>(&args->stack.mac.sched.max_nof_ctrl_symbols)->default_value(3), "Number of control symbols") ("scheduler.max_nof_ctrl_symbols", bpo::value<uint32_t>(&args->stack.mac.sched.max_nof_ctrl_symbols)->default_value(3), "Number of control symbols")
("scheduler.min_nof_ctrl_symbols", bpo::value<uint32_t>(&args->stack.mac.sched.min_nof_ctrl_symbols)->default_value(1), "Minimum number of control symbols") ("scheduler.min_nof_ctrl_symbols", bpo::value<uint32_t>(&args->stack.mac.sched.min_nof_ctrl_symbols)->default_value(1), "Minimum number of control symbols")
("scheduler.pucch_multiplex_enable", bpo::value<bool>(&args->stack.mac.sched.pucch_mux_enabled)->default_value(false), "Enable PUCCH multiplexing") ("scheduler.pucch_multiplex_enable", bpo::value<bool>(&args->stack.mac.sched.pucch_mux_enabled)->default_value(false), "Enable PUCCH multiplexing")
("scheduler.pucch_harq_max_rb", bpo::value<int>(&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<float>(&args->stack.mac.sched.target_bler)->default_value(0.05), "Target BLER (in decimal) to achieve via adaptive link") ("scheduler.target_bler", bpo::value<float>(&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<float>(&args->stack.mac.sched.max_delta_dl_cqi)->default_value(5.0), "Maximum shift in CQI for adaptive DL link") ("scheduler.max_delta_dl_cqi", bpo::value<float>(&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<float>(&args->stack.mac.sched.max_delta_ul_snr)->default_value(5.0), "Maximum shift in UL SNR for adaptive UL link") ("scheduler.max_delta_ul_snr", bpo::value<float>(&args->stack.mac.sched.max_delta_ul_snr)->default_value(5.0), "Maximum shift in UL SNR for adaptive UL link")

@ -106,9 +106,10 @@ int phy::init(const phy_args_t& args,
const phy_cfg_t& cfg, const phy_cfg_t& cfg,
srsran::radio_interface_phy* radio_, srsran::radio_interface_phy* radio_,
stack_interface_phy_lte* stack_lte_, 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"); phy_log.error("Couldn't initialize LTE PHY");
return SRSRAN_ERROR; return SRSRAN_ERROR;
} }
@ -124,7 +125,8 @@ int phy::init(const phy_args_t& args,
int phy::init(const phy_args_t& args, int phy::init(const phy_args_t& args,
const phy_cfg_t& cfg, const phy_cfg_t& cfg,
srsran::radio_interface_phy* radio_, 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) { if (cfg.phy_cell_cfg.size() > SRSRAN_MAX_CARRIERS) {
phy_log.error( phy_log.error(
@ -151,7 +153,7 @@ int phy::init(const phy_args_t& args,
workers_common.params = 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); parse_common_config(cfg);
@ -163,13 +165,18 @@ int phy::init(const phy_args_t& args,
// For each carrier, initialise PRACH worker // For each carrier, initialise PRACH worker
for (uint32_t cc = 0; cc < cfg.phy_cell_cfg.size(); cc++) { 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_cfg.root_seq_idx = cfg.phy_cell_cfg[cc].root_seq_idx;
prach.init( prach.init(cc,
cc, cfg.phy_cell_cfg[cc].cell, prach_cfg, stack_, phy_log, PRACH_WORKER_THREAD_PRIO, args.nof_prach_threads); 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); 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 // Warning this must be initialized after all workers have been added to the pool
tx_rx.init(stack_, radio, &lte_workers, &workers_common, &prach, SF_RECV_THREAD_PRIO); tx_rx.init(enb_, radio, &lte_workers, &workers_common, &prach, SF_RECV_THREAD_PRIO);
initialized = true; initialized = true;

@ -48,14 +48,14 @@ txrx::txrx(srslog::basic_logger& logger) : thread("TXRX"), logger(logger), runni
/* Do nothing */ /* Do nothing */
} }
bool txrx::init(stack_interface_phy_lte* stack_, bool txrx::init(enb_time_interface* enb_,
srsran::radio_interface_phy* radio_h_, srsran::radio_interface_phy* radio_h_,
lte::worker_pool* lte_workers_, lte::worker_pool* lte_workers_,
phy_common* worker_com_, phy_common* worker_com_,
prach_worker_pool* prach_, prach_worker_pool* prach_,
uint32_t prio_) uint32_t prio_)
{ {
stack = stack_; enb = enb_;
radio_h = radio_h_; radio_h = radio_h_;
lte_workers = lte_workers_; lte_workers = lte_workers_;
worker_com = worker_com_; worker_com = worker_com_;
@ -222,8 +222,8 @@ void txrx::run_thread()
lte_workers->start_worker(lte_worker); lte_workers->start_worker(lte_worker);
} }
// Advance stack in time // Advance in time
stack->tti_clock(); enb->tti_clock();
} }
} }

@ -22,8 +22,8 @@
#include "srsenb/hdr/stack/enb_stack_lte.h" #include "srsenb/hdr/stack/enb_stack_lte.h"
#include "srsenb/hdr/common/rnti_pool.h" #include "srsenb/hdr/common/rnti_pool.h"
#include "srsenb/hdr/enb.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_metrics_interface.h"
#include "srsran/interfaces/enb_x2_interfaces.h"
#include "srsran/rlc/bearer_mem_pool.h" #include "srsran/rlc/bearer_mem_pool.h"
#include "srsran/srslog/event_trace.h" #include "srsran/srslog/event_trace.h"
@ -36,10 +36,10 @@ class gtpu_pdcp_adapter final : public gtpu_interface_pdcp, public pdcp_interfac
public: public:
gtpu_pdcp_adapter(srslog::basic_logger& logger_, gtpu_pdcp_adapter(srslog::basic_logger& logger_,
pdcp* pdcp_lte, pdcp* pdcp_lte,
pdcp* pdcp_nr, pdcp_interface_gtpu* pdcp_x2,
gtpu* gtpu_, gtpu* gtpu_,
enb_bearer_manager& bearers_) : 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 /// Converts LCID to EPS-BearerID and sends corresponding PDU to GTPU
@ -59,7 +59,7 @@ public:
if (bearer.rat == srsran_rat_t::lte) { if (bearer.rat == srsran_rat_t::lte) {
pdcp_obj->write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); pdcp_obj->write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn);
} else if (bearer.rat == srsran_rat_t::nr) { } 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 { } else {
logger.warning("Can't deliver SDU for EPS bearer %d. Dropping it.", eps_bearer_id); 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) { if (bearer.rat == srsran_rat_t::lte) {
return pdcp_obj->get_buffered_pdus(rnti, bearer.lcid); return pdcp_obj->get_buffered_pdus(rnti, bearer.lcid);
} else if (bearer.rat == srsran_rat_t::nr) { } 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); logger.error("Bearer rnti=0x%x, eps-BearerID=%d not found", rnti, eps_bearer_id);
return {}; return {};
@ -81,34 +81,26 @@ private:
srslog::basic_logger& logger; srslog::basic_logger& logger;
gtpu* gtpu_obj = nullptr; gtpu* gtpu_obj = nullptr;
pdcp* pdcp_obj = nullptr; pdcp* pdcp_obj = nullptr;
pdcp* pdcp_nr_obj = nullptr; pdcp_interface_gtpu* pdcp_x2_obj = nullptr;
enb_bearer_manager* bearers = nullptr; enb_bearer_manager* bearers = nullptr;
}; };
enb_stack_lte::enb_stack_lte(srslog::sink& log_sink) : enb_stack_lte::enb_stack_lte(srslog::sink& log_sink) :
thread("STACK"), thread("STACK"),
mac_logger(srslog::fetch_basic_logger("MAC", log_sink)), 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_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_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_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)), s1ap_logger(srslog::fetch_basic_logger("S1AP", log_sink, false)),
gtpu_logger(srslog::fetch_basic_logger("GTPU", log_sink, false)), gtpu_logger(srslog::fetch_basic_logger("GTPU", log_sink, false)),
stack_logger(srslog::fetch_basic_logger("STCK", log_sink, false)), stack_logger(srslog::fetch_basic_logger("STCK", log_sink, false)),
task_sched(512, 128), task_sched(512, 128),
pdcp(&task_sched, pdcp_logger), pdcp(&task_sched, pdcp_logger),
pdcp_nr(&task_sched, pdcp_nr_logger),
mac(&task_sched, mac_logger), mac(&task_sched, mac_logger),
mac_nr(&task_sched),
rlc(rlc_logger), rlc(rlc_logger),
rlc_nr(rlc_nr_logger),
gtpu(&task_sched, gtpu_logger, &rx_sockets), gtpu(&task_sched, gtpu_logger, &rx_sockets),
s1ap(&task_sched, s1ap_logger, &rx_sockets), s1ap(&task_sched, s1ap_logger, &rx_sockets),
rrc(&task_sched, bearers), rrc(&task_sched, bearers),
rrc_nr(&task_sched),
mac_pcap(), mac_pcap(),
pending_stack_metrics(64) 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_, int enb_stack_lte::init(const stack_args_t& args_,
const rrc_cfg_t& rrc_cfg_, const rrc_cfg_t& rrc_cfg_,
phy_interface_stack_lte* phy_, phy_interface_stack_lte* phy_,
phy_interface_stack_nr* phy_nr_) x2_interface* x2_)
{
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_)
{ {
args = args_; args = args_;
rrc_cfg = rrc_cfg_; rrc_cfg = rrc_cfg_;
phy = phy_;
// Init RNTI and bearer memory pools // Init RNTI and bearer memory pools
reserve_rnti_memblocks(args.mac.nof_prealloc_ues); 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 // setup logging for each layer
mac_logger.set_level(srslog::str_to_basic_level(args.log.mac_level)); 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_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_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_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)); 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)); 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)); 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_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_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_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_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); gtpu_logger.set_hex_dump_max_size(args.log.gtpu_hex_limit);
s1ap_logger.set_hex_dump_max_size(args.log.s1ap_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); 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); sync_task_queue = task_sched.make_task_queue(args.sync_queue_size);
// setup bearer managers // setup bearer managers
gtpu_adapter.reset(new gtpu_pdcp_adapter(stack_logger, &pdcp, &pdcp_nr, &gtpu, bearers)); gtpu_adapter.reset(new gtpu_pdcp_adapter(stack_logger, &pdcp, x2_, &gtpu, bearers));
// Init all LTE layers // Init all LTE layers
if (!mac.init(args.mac, rrc_cfg.cell_list, phy, &rlc, &rrc)) { 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()); rlc.init(&pdcp, &rrc, &mac, task_sched.get_timer_handler());
pdcp.init(&rlc, &rrc, gtpu_adapter.get()); pdcp.init(&rlc, &rrc, gtpu_adapter.get());
if (rrc.init(rrc_cfg, phy, &mac, &rlc, &pdcp, &s1ap, &gtpu, &rrc_nr) != SRSRAN_SUCCESS) { if (rrc.init(rrc_cfg, phy, &mac, &rlc, &pdcp, &s1ap, &gtpu, x2_) != SRSRAN_SUCCESS) {
stack_logger.error("Couldn't initialize RRC"); stack_logger.error("Couldn't initialize RRC");
return SRSRAN_ERROR; 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; 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_t gtpu_args;
gtpu_args.embms_enable = args.embms.enable; gtpu_args.embms_enable = args.embms.enable;
gtpu_args.embms_m1u_multiaddr = args.embms.m1u_multiaddr; gtpu_args.embms_m1u_multiaddr = args.embms.m1u_multiaddr;

@ -20,21 +20,25 @@
*/ */
#include "srsenb/hdr/stack/gnb_stack_nr.h" #include "srsenb/hdr/stack/gnb_stack_nr.h"
#include "srsran/common/standard_streams.h"
#include "srsran/srsran.h" #include "srsran/srsran.h"
#include <srsran/interfaces/enb_metrics_interface.h> #include <srsran/interfaces/enb_metrics_interface.h>
namespace srsenb { 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(); ue_task_queue = task_sched.make_task_queue();
sync_task_queue = task_sched.make_task_queue(); sync_task_queue = task_sched.make_task_queue();
gw_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"; 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_; 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_) // setup logging
{ mac_logger.set_level(srslog::str_to_basic_level(args.log.mac_level));
args = args_; 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 mac_logger.set_hex_dump_max_size(args.log.mac_hex_limit);
// gtpu_log.init("GTPU", logger); rlc_logger.set_hex_dump_max_size(args.log.rlc_hex_limit);
// gtpu_log.set_level(args.log.gtpu_level); pdcp_logger.set_hex_dump_max_size(args.log.pdcp_hex_limit);
// gtpu_log.set_hex_limit(args.log.gtpu_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 // Init all layers
mac_nr_args_t mac_args = {}; 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 = args.mac_pcap;
m_mac->init(mac_args, phy, this, nullptr, m_rrc.get()); mac_args.pcap.filename = "/tmp/enb_mac_nr.pcap";
if (mac.init(mac_args, phy, nullptr, &rlc, &rrc) != SRSRAN_SUCCESS) {
rlc_logger.set_level(srslog::str_to_basic_level(args.log.rlc_level)); stack_logger.error("Couldn't initialize MAC-NR");
rlc_logger.set_hex_dump_max_size(args.log.rlc_hex_limit); return SRSRAN_ERROR;
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);
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 = {}; if (rrc.init(rrc_cfg_, phy, &mac, &rlc, &pdcp, nullptr, nullptr, x2_) != SRSRAN_SUCCESS) {
m_gw->init(gw_args, this); 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, // m_gtpu->init(args.s1ap.gtp_bind_addr, args.s1ap.mme_addr,
// args.expert.m1u_multiaddr, args.expert.m1u_if_addr, nullptr, &gtpu_log, // args.expert.m1u_multiaddr, args.expert.m1u_if_addr, nullptr, &gtpu_log,
// args.expert.enable_mbsfn); // 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() void gnb_stack_nr::stop()
{ {
if (running) { if (running) {
m_gw->stop(); rrc.stop();
// m_gtpu->stop(); pdcp.stop();
m_rrc->stop(); mac.stop();
m_pdcp->stop();
m_mac->stop();
srsran::get_background_workers().stop(); srsran::get_background_workers().stop();
running = false; 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_clock_impl(); });
sync_task_queue.push([this, tti]() { run_tti_impl(tti); });
} }
void gnb_stack_nr::run_tti_impl(uint32_t tti) void gnb_stack_nr::tti_clock_impl()
{ {
// m_ngap->run_tti(); // m_ngap->run_tti();
task_sched.tic(); task_sched.tic();
@ -153,8 +156,8 @@ void gnb_stack_nr::process_pdus()
bool gnb_stack_nr::get_metrics(srsenb::stack_metrics_t* metrics) bool gnb_stack_nr::get_metrics(srsenb::stack_metrics_t* metrics)
{ {
m_mac->get_metrics(metrics->mac); mac.get_metrics(metrics->mac);
m_rrc->get_metrics(metrics->rrc); rrc.get_metrics(metrics->rrc);
return true; 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) 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) 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) 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) 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) 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

@ -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); uint32_t nof_slots = SRSRAN_NSLOTS_PER_FRAME_NR(cfg.numerology_idx);
for (size_t sl = 0; sl < nof_slots; ++sl) { for (size_t sl = 0; sl < nof_slots; ++sl) {
slot_cfg sl_cfg{}; slot_cfg sl_cfg{};
sl_cfg.is_dl = srsran_tdd_nr_is_dl(&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_tdd_nr_is_ul(&cell_cfg.tdd, 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); slots.push_back(sl_cfg);
} }

@ -70,15 +70,15 @@ slot_ue ue_carrier::try_reserve(slot_point pdcch_slot,
sfu.dl_pending_bytes = dl_pending_bytes; sfu.dl_pending_bytes = dl_pending_bytes;
sfu.ul_pending_bytes = ul_pending_bytes; sfu.ul_pending_bytes = ul_pending_bytes;
const srsran_tdd_config_nr_t& tdd_cfg = cell_params.cell_cfg.tdd; const srsran_duplex_config_nr_t& tdd_cfg = cell_params.cell_cfg.duplex;
if (srsran_tdd_nr_is_dl(&tdd_cfg, 0, sfu.pdsch_slot.slot_idx())) { if (srsran_duplex_nr_is_dl(&tdd_cfg, 0, sfu.pdsch_slot.slot_idx())) {
// If DL enabled // If DL enabled
sfu.h_dl = harq_ent.find_pending_dl_retx(); sfu.h_dl = harq_ent.find_pending_dl_retx();
if (sfu.h_dl == nullptr and sfu.dl_pending_bytes > 0) { if (sfu.h_dl == nullptr and sfu.dl_pending_bytes > 0) {
sfu.h_dl = harq_ent.find_empty_dl_harq(); 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 // If UL enabled
sfu.h_ul = harq_ent.find_pending_ul_retx(); sfu.h_ul = harq_ent.find_pending_ul_retx();
if (sfu.h_ul == nullptr and sfu.ul_pending_bytes > 0) { if (sfu.h_ul == nullptr and sfu.ul_pending_bytes > 0) {

@ -89,8 +89,15 @@ void sf_grid_t::init(const sched_cell_params_t& cell_params_)
pucch_mask.resize(cc_cfg->nof_prb()); pucch_mask.resize(cc_cfg->nof_prb());
pucch_nrb = (cc_cfg->cfg.nrb_pucch > 0) ? (uint32_t)cc_cfg->cfg.nrb_pucch : 0; 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; 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; uint32_t harq_pucch = 0;
pucch_nrb = std::max(pucch_nrb, srsran_pucch_m(&pucch_cfg, cc_cfg->cfg.cell.cp) / 2 + 1); 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) { if (pucch_nrb > 0) {
pucch_mask.fill(0, pucch_nrb); pucch_mask.fill(0, pucch_nrb);
pucch_mask.fill(cc_cfg->nof_prb() - pucch_nrb, cc_cfg->nof_prb()); pucch_mask.fill(cc_cfg->nof_prb() - pucch_nrb, cc_cfg->nof_prb());

@ -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 // PUCCH allocation would collide with other PUCCH/PUSCH grants. Try another CCE position
continue; 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(); node.current_mask.reset();

@ -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 // 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) // 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_present = true;
cell_group_cfg_pack.rlc_bearer_to_add_mod_list.resize(1); 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); 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_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; cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg_present = true;
// UL config dedicated // 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.sched_request_id = 0;
sr_res1.periodicity_and_offset_present = true; sr_res1.periodicity_and_offset_present = true;
sr_res1.periodicity_and_offset.set_sl40(); sr_res1.periodicity_and_offset.set_sl40();
sr_res1.periodicity_and_offset.sl40() = 7;
sr_res1.res_present = true; sr_res1.res_present = true;
sr_res1.res = 2; // PUCCH resource for SR
// DL data // 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_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 // PUCCH Resource for format 1
srsran_pucch_nr_resource_t resource_small = {}; 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_present = true;
beta_offset_semi_static.beta_offset_ack_idx3 = 9; 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_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_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_part1_idx2 = 6;
beta_offset_semi_static.beta_offset_csi_part2_idx1_present = true; 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_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.res_map.freq_band.nrof_rbs = 52;
nzp_csi_res.pwr_ctrl_offset = 0; nzp_csi_res.pwr_ctrl_offset = 0;
// Skip pwr_ctrl_offset_ss_present // 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_present = true;
nzp_csi_res.periodicity_and_offset.set_slots80(); nzp_csi_res.periodicity_and_offset.set_slots80();
nzp_csi_res.periodicity_and_offset.slots80() = 0;
// optional // optional
nzp_csi_res.qcl_info_periodic_csi_rs_present = true; nzp_csi_res.qcl_info_periodic_csi_rs_present = true;
nzp_csi_res.qcl_info_periodic_csi_rs = 0; 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); 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 = 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]; 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.resize(1);
nzp_csi_res_set.nzp_csi_rs_res[0] = 0;
// Skip TRS info // Skip TRS info
// CSI report config // 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.csi_im_res_for_interference = 1;
csi_report.report_cfg_type.set_periodic(); 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.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.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].ul_bw_part_id = 0;
csi_report.report_cfg_type.periodic().pucch_csi_res_list[0].pucch_res = 0; // was 17 in orig PCAP 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 // 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_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.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.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_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 = 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; 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_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_present = true;
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl 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; .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 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); .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 = 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; 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.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_present = true;
pdcch_cfg_common.setup().common_ctrl_res_set.ctrl_res_set_id = 1; 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( 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; 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.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_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.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.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) // SSB config (optional)
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_positions_in_burst_present = true; 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; 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_present = true;
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_periodicity_serving_cell = 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; 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; 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; auto& tdd_config = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common;
tdd_config.ref_subcarrier_spacing = subcarrier_spacing_e::khz15; tdd_config.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 // add secondary cell group config
recfg_ies.secondary_cell_group_present = true; recfg_ies.secondary_cell_group_present = true;
if (pack_secondary_cell_group_config(recfg_ies.secondary_cell_group) == SRSRAN_ERROR) { if (pack_secondary_cell_group_config_tdd(recfg_ies.secondary_cell_group) == SRSRAN_ERROR) {
parent->logger.error("Failed to pack RRC Reconfiguration"); parent->logger.error("Failed to pack TDD RRC Reconfiguration");
return SRSRAN_ERROR; return SRSRAN_ERROR;
} }

@ -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: case ul_dcch_msg_type_c::c1_c_::types::rrc_conn_reest_complete:
save_ul_message(std::move(original_pdu)); save_ul_message(std::move(original_pdu));
handle_rrc_con_reest_complete(&ul_dcch_msg.msg.c1().rrc_conn_reest_complete(), std::move(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(); set_activity();
break; break;
case ul_dcch_msg_type_c::c1_c_::types::ul_info_transfer: case ul_dcch_msg_type_c::c1_c_::types::ul_info_transfer:

@ -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); asn1::bounded_bitstring<1, 160, true, true> transport_layer_addr(32);
uint8_t addr[4]; 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) { for (uint32_t j = 0; j < 4; ++j) {
transport_layer_addr.data()[j] = addr[3 - 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); transp_addr.resize(32);
uint8_t addr[4]; uint8_t addr[4];
if (!s1ap_ptr->args.gtp_advertise_addr.empty()) { 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 { } 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) { for (uint32_t j = 0; j < 4; ++j) {
transp_addr.data()[j] = addr[3 - j]; transp_addr.data()[j] = addr[3 - j];

@ -403,13 +403,9 @@ int gtpu::init(const gtpu_args_t& gtpu_args, pdcp_interface_gtpu* pdcp_)
struct sockaddr_in bindaddr; struct sockaddr_in bindaddr;
bzero(&bindaddr, sizeof(struct sockaddr_in)); bzero(&bindaddr, sizeof(struct sockaddr_in));
bindaddr.sin_family = AF_INET; // Bind socket
bindaddr.sin_addr.s_addr = inet_addr(gtp_bind_addr.c_str()); if (not net_utils::bind_addr(fd, gtp_bind_addr.c_str(), GTPU_PORT, &bindaddr)) {
bindaddr.sin_port = htons(GTPU_PORT);
if (bind(fd, (struct sockaddr*)&bindaddr, sizeof(struct sockaddr_in))) {
snprintf(errbuf, sizeof(errbuf), "%s", strerror(errno)); 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); srsran::console("Failed to bind on address %s, port %d: %s\n", gtp_bind_addr.c_str(), int(GTPU_PORT), errbuf);
return SRSRAN_ERROR; 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 */ /* Send an ADD MEMBERSHIP message via setsockopt */
struct ip_mreq mreq {}; struct ip_mreq mreq {};
mreq.imr_multiaddr.s_addr = inet_addr(m1u_multiaddr.c_str()); // Multicast address of the service // 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. 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) { if (setsockopt(m1u_sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
logger.error("Register musticast group for M1-U"); 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()); logger.error("M1-U infterface IP: %s, M1-U Multicast Address %s", m1u_if_addr.c_str(), m1u_multiaddr.c_str());

@ -27,7 +27,7 @@ target_link_libraries(sched_nr_test
srsran_common srsran_common
${CMAKE_THREAD_LIBS_INIT} ${CMAKE_THREAD_LIBS_INIT}
${Boost_LIBRARIES}) ${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) add_executable(sched_nr_prb_test sched_nr_prb_test.cc)
target_link_libraries(sched_nr_prb_test target_link_libraries(sched_nr_prb_test
@ -35,8 +35,8 @@ target_link_libraries(sched_nr_prb_test
srsran_common srsran_common
${CMAKE_THREAD_LIBS_INIT} ${CMAKE_THREAD_LIBS_INIT}
${Boost_LIBRARIES}) ${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) 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) 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) add_nr_test(sched_nr_rar_test sched_nr_rar_test)

@ -45,7 +45,7 @@ inline sched_nr_interface::cell_cfg_t get_default_cell_cfg(
sched_nr_interface::cell_cfg_t cell_cfg{}; sched_nr_interface::cell_cfg_t cell_cfg{};
cell_cfg.carrier = phy_cfg.carrier; 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.resize(1);
cell_cfg.bwps[0].pdcch = phy_cfg.pdcch; cell_cfg.bwps[0].pdcch = phy_cfg.pdcch;

@ -91,7 +91,7 @@ void sched_nr_cfg_serialized_test()
uint32_t max_nof_ttis = 1000, nof_sectors = 4; uint32_t max_nof_ttis = 1000, nof_sectors = 4;
task_job_manager tasks; task_job_manager tasks;
sched_nr_interface::sched_cfg_t cfg; sched_nr_interface::sched_cfg_t cfg;
cfg.auto_refill_buffer = true; cfg.auto_refill_buffer = true;
std::vector<sched_nr_interface::cell_cfg_t> cells_cfg = get_default_cells_cfg(nof_sectors); std::vector<sched_nr_interface::cell_cfg_t> 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_nr_cc_output_res_t out{slot_tx, cc, &dl_res, &ul_res};
sched_tester.update(out); sched_tester.update(out);
tasks.finish_cc(slot_rx, dl_res, ul_res); 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); dl_res.dl_sched.pdcch_dl.size() == 1);
} }
} }

@ -719,7 +719,7 @@ public:
return SRSRAN_SUCCESS; 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 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) int run_tti(bool enable_assert)
{ {
std::lock_guard<std::mutex> lock(phy_mac_mutex); std::lock_guard<std::mutex> lock(phy_mac_mutex);
@ -1159,7 +1159,7 @@ typedef std::unique_ptr<dummy_ue> unique_dummy_ue_phy_t;
typedef std::unique_ptr<srsenb::phy> unique_srsenb_phy_t; typedef std::unique_ptr<srsenb::phy> unique_srsenb_phy_t;
class phy_test_bench class phy_test_bench : public srsenb::enb_time_interface
{ {
public: public:
struct args_t { struct args_t {
@ -1337,7 +1337,7 @@ public:
stack->set_active_cell_list(args.ue_cell_list); stack->set_active_cell_list(args.ue_cell_list);
/// Initiate eNb PHY with the given RNTI /// 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; return SRSRAN_ERROR;
} }
enb_phy->set_config(args.rnti, phy_rrc_cfg); enb_phy->set_config(args.rnti, phy_rrc_cfg);
@ -1359,7 +1359,7 @@ public:
enb_phy->stop(); enb_phy->stop();
} }
~phy_test_bench() = default; virtual ~phy_test_bench() = default;
int run_tti() int run_tti()
{ {
@ -1431,6 +1431,11 @@ public:
return ret; return ret;
} }
void tti_clock() final
{
// nothing to do
}
}; };
typedef std::unique_ptr<phy_test_bench> unique_phy_test_bench; typedef std::unique_ptr<phy_test_bench> unique_phy_test_bench;

@ -21,6 +21,7 @@
#include "srsepc/hdr/mbms-gw/mbms-gw.h" #include "srsepc/hdr/mbms-gw/mbms-gw.h"
#include "srsran/common/standard_streams.h" #include "srsran/common/standard_streams.h"
#include "srsran/common/network_utils.h"
#include "srsran/upper/gtpu.h" #include "srsran/upper/gtpu.h"
#include <algorithm> #include <algorithm>
#include <fcntl.h> #include <fcntl.h>
@ -161,9 +162,12 @@ int mbms_gw::init_sgi_mb_if(mbms_gw_args_t* args)
// Set IP of the interface // Set IP of the interface
struct sockaddr_in* addr = (struct sockaddr_in*)&ifr.ifr_addr; 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()); if (not srsran::net_utils::set_sockaddr(addr, args->sgi_mb_if_addr.c_str(), 0)) {
addr->sin_port = 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) { if (ioctl(sgi_mb_sock, SIOCSIFADDR, &ifr) < 0) {
m_logger.error( 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; 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) { if (ioctl(sgi_mb_sock, SIOCSIFNETMASK, &ifr) < 0) {
m_logger.error("Failed to set TUN interface Netmask. Error: %s", strerror(errno)); m_logger.error("Failed to set TUN interface Netmask. Error: %s", strerror(errno));
close(m_sgi_mb_if); 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*/ /* Set local interface for outbound multicast packets*/
/* The IP must be associated with a local multicast capable interface */ /* The IP must be associated with a local multicast capable interface */
struct in_addr local_if; 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) { 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()); m_logger.error("Error %s setting multicast interface %s.", strerror(errno), args->m1u_multi_if.c_str());
return SRSRAN_ERROR_CANT_START; 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)); bzero(&m_m1u_multi_addr, sizeof(m_m1u_multi_addr));
m_m1u_multi_addr.sin_family = AF_INET; m_m1u_multi_addr.sin_family = AF_INET;
m_m1u_multi_addr.sin_port = htons(GTPU_RX_PORT + 1); 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"); m_logger.info("Initialized M1-U");
return SRSRAN_SUCCESS; return SRSRAN_SUCCESS;

@ -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; act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].len = 4;
struct sockaddr_in dns_addr; 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); 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 // Make sure all unused options are set to false

@ -23,6 +23,7 @@
#include "srsran/asn1/gtpc.h" #include "srsran/asn1/gtpc.h"
#include "srsran/common/bcd_helpers.h" #include "srsran/common/bcd_helpers.h"
#include "srsran/common/liblte_security.h" #include "srsran/common/liblte_security.h"
#include "srsran/common/network_utils.h"
#include <cmath> #include <cmath>
#include <inttypes.h> // for printing uint64_t #include <inttypes.h> // for printing uint64_t
#include <random> #include <random>
@ -95,7 +96,7 @@ int s1ap::init(const s1ap_args_t& s1ap_args)
m_pcap.open(s1ap_args.pcap_filename.c_str()); m_pcap.open(s1ap_args.pcap_filename.c_str());
} }
m_logger.info("S1AP Initialized"); m_logger.info("S1AP Initialized");
return 0; return SRSRAN_SUCCESS;
} }
void s1ap::stop() void s1ap::stop()
@ -152,7 +153,7 @@ int s1ap::enb_listen()
sock_fd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); sock_fd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
if (sock_fd == -1) { if (sock_fd == -1) {
srsran::console("Could not create SCTP socket\n"); 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 // 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))) { if (setsockopt(sock_fd, IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof(evnts))) {
close(sock_fd); close(sock_fd);
srsran::console("Subscribing to sctp_data_io_events failed\n"); srsran::console("Subscribing to sctp_data_io_events failed\n");
return -1; return SRSRAN_ERROR;
} }
// S1-MME bind // S1-MME bind
bzero(&s1mme_addr, sizeof(s1mme_addr)); bzero(&s1mme_addr, sizeof(s1mme_addr));
s1mme_addr.sin_family = AF_INET; if (not srsran::net_utils::set_sockaddr(&s1mme_addr, m_s1ap_args.mme_bind_addr.c_str(), S1MME_PORT)) {
inet_pton(AF_INET, m_s1ap_args.mme_bind_addr.c_str(), &(s1mme_addr.sin_addr)); m_logger.error("Invalid mme_bind_addr: %s", m_s1ap_args.mme_bind_addr.c_str());
s1mme_addr.sin_port = htons(S1MME_PORT); srsran::console("Invalid mme_bind_addr: %s\n", m_s1ap_args.mme_bind_addr.c_str());
err = bind(sock_fd, (struct sockaddr*)&s1mme_addr, sizeof(s1mme_addr)); return SRSRAN_ERROR;
if (err != 0) { }
if (not srsran::net_utils::bind_addr(sock_fd, s1mme_addr)) {
close(sock_fd); close(sock_fd);
m_logger.error("Error binding SCTP socket"); m_logger.error("Error binding SCTP socket");
srsran::console("Error binding SCTP socket\n"); srsran::console("Error binding SCTP socket\n");
return -1; return SRSRAN_ERROR;
} }
// Listen for connections // Listen for connections
@ -185,7 +187,7 @@ int s1ap::enb_listen()
close(sock_fd); close(sock_fd);
m_logger.error("Error in SCTP socket listen"); m_logger.error("Error in SCTP socket listen");
srsran::console("Error in SCTP socket listen\n"); srsran::console("Error in SCTP socket listen\n");
return -1; return SRSRAN_ERROR;
} }
return sock_fd; return sock_fd;
@ -565,7 +567,7 @@ uint64_t s1ap::find_imsi_from_m_tmsi(uint32_t m_tmsi)
return it->second; return it->second;
} else { } else {
m_logger.debug("Could not find IMSI from M-TMSI 0x%x", m_tmsi); m_logger.debug("Could not find IMSI from M-TMSI 0x%x", m_tmsi);
return 0; return SRSRAN_SUCCESS;
} }
} }

@ -550,7 +550,10 @@ int spgw::gtpc::init_ue_ip(spgw_args_t* args, const std::map<std::string, uint64
// load our imsi to ip lookup table // load our imsi to ip lookup table
for (std::map<std::string, uint64_t>::const_iterator iter = ip_to_imsi.begin(); iter != ip_to_imsi.end(); ++iter) { for (std::map<std::string, uint64_t>::const_iterator iter = ip_to_imsi.begin(); iter != ip_to_imsi.end(); ++iter) {
struct in_addr in_addr; 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) { if (!m_imsi_to_ip.insert(std::make_pair(iter->second, in_addr)).second) {
m_logger.error( m_logger.error(
"SPGW: duplicate imsi %015" PRIu64 " for static ip address %s.", iter->second, iter->first.c_str()); "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::map<std::string, uint64
// first address is allocated to the epc tun interface, start w/next addr // first address is allocated to the epc tun interface, start w/next addr
for (uint32_t n = 1; n < 254; ++n) { for (uint32_t n = 1; n < 254; ++n) {
struct in_addr ue_addr; struct in_addr ue_addr;
ue_addr.s_addr = inet_addr(args->sgi_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<std::string, uint64_t>::const_iterator iter = ip_to_imsi.find(inet_ntoa(ue_addr)); std::map<std::string, uint64_t>::const_iterator iter = ip_to_imsi.find(inet_ntoa(ue_addr));
if (iter != ip_to_imsi.end()) { if (iter != ip_to_imsi.end()) {

@ -22,6 +22,7 @@
#include "srsepc/hdr/spgw/gtpu.h" #include "srsepc/hdr/spgw/gtpu.h"
#include "srsepc/hdr/mme/mme_gtpc.h" #include "srsepc/hdr/mme/mme_gtpc.h"
#include "srsran/common/string_helpers.h" #include "srsran/common/string_helpers.h"
#include "srsran/common/network_utils.h"
#include "srsran/upper/gtpu.h" #include "srsran/upper/gtpu.h"
#include <algorithm> #include <algorithm>
#include <arpa/inet.h> #include <arpa/inet.h>
@ -140,9 +141,11 @@ int spgw::gtpu::init_sgi(spgw_args_t* args)
// Set IP of the interface // Set IP of the interface
struct sockaddr_in* addr = (struct sockaddr_in*)&ifr.ifr_addr; struct sockaddr_in* addr = (struct sockaddr_in*)&ifr.ifr_addr;
addr->sin_family = AF_INET; if (not srsran::net_utils::set_sockaddr(addr, args->sgi_if_addr.c_str(), 0)) {
addr->sin_addr.s_addr = inet_addr(args->sgi_if_addr.c_str()); m_logger.error("Invalid sgi_if_addr: %s", args->sgi_if_addr.c_str());
addr->sin_port = 0; 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) { if (ioctl(sgi_sock, SIOCSIFADDR, &ifr) < 0) {
m_logger.error( m_logger.error(
@ -152,8 +155,11 @@ int spgw::gtpu::init_sgi(spgw_args_t* args)
return SRSRAN_ERROR_CANT_START; return SRSRAN_ERROR_CANT_START;
} }
ifr.ifr_netmask.sa_family = AF_INET; ifr.ifr_netmask.sa_family = AF_INET;
((struct sockaddr_in*)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr("255.255.255.0"); 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) { if (ioctl(sgi_sock, SIOCSIFNETMASK, &ifr) < 0) {
m_logger.error("Failed to set TUN interface Netmask. Error: %s", strerror(errno)); m_logger.error("Failed to set TUN interface Netmask. Error: %s", strerror(errno));
close(m_sgi); close(m_sgi);
@ -179,7 +185,11 @@ int spgw::gtpu::init_s1u(spgw_args_t* args)
// Bind the socket // Bind the socket
m_s1u_addr.sin_family = AF_INET; 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); m_s1u_addr.sin_port = htons(GTPU_RX_PORT);
if (bind(m_s1u, (struct sockaddr*)&m_s1u_addr, sizeof(struct sockaddr_in))) { if (bind(m_s1u, (struct sockaddr*)&m_s1u_addr, sizeof(struct sockaddr_in))) {

@ -491,8 +491,8 @@ public:
// Compute synch metrics and report it to the PHY state // Compute synch metrics and report it to the PHY state
sync_metrics_t new_sync_metrics = {}; sync_metrics_t new_sync_metrics = {};
new_sync_metrics.cfo = new_meas.cfo_hz; new_sync_metrics.cfo = new_meas.cfo_hz + ul_ext_cfo_hz;
set_sync_metrics(sync_metrics); set_sync_metrics(new_sync_metrics);
// Convert to CSI channel measurement and report new NZP-CSI-RS measurement to the PHY state // Convert to CSI channel measurement and report new NZP-CSI-RS measurement to the PHY state
srsran_csi_channel_measurements_t measurements = {}; srsran_csi_channel_measurements_t measurements = {};
@ -508,11 +508,10 @@ public:
trs_measurements_mutex.lock(); 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.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.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. // 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); 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.nof_re++;
trs_measurements_mutex.unlock(); trs_measurements_mutex.unlock();

@ -65,6 +65,8 @@ public:
srsran::phy_cfg_mbsfn_t mbsfn_config = {}; srsran::phy_cfg_mbsfn_t mbsfn_config = {};
std::atomic<bool> cell_is_selecting = {false};
// Secondary serving cell states // Secondary serving cell states
scell::state cell_state; scell::state cell_state;
@ -305,7 +307,7 @@ private:
std::mutex mtch_mutex; std::mutex mtch_mutex;
std::condition_variable mtch_cvar; std::condition_variable mtch_cvar;
bool is_pending_tx_end = false; std::atomic<bool> is_pending_tx_end{false};
srsran::radio_interface_phy* radio_h = nullptr; srsran::radio_interface_phy* radio_h = nullptr;
srslog::basic_logger& logger; srslog::basic_logger& logger;

@ -158,8 +158,8 @@ private:
srsran::task_multiqueue::queue_handle stack_task_dispatch_queue; srsran::task_multiqueue::queue_handle stack_task_dispatch_queue;
// pointer to MAC PCAP object // pointer to MAC PCAP object
srsran::mac_pcap* pcap = nullptr; srsran::mac_pcap* pcap = nullptr;
bool is_first_ul_grant = false; std::atomic<bool> is_first_ul_grant{false};
std::mutex metrics_mutex = {}; std::mutex metrics_mutex = {};
mac_metrics_t metrics[SRSRAN_MAX_CARRIERS] = {}; mac_metrics_t metrics[SRSRAN_MAX_CARRIERS] = {};

@ -61,6 +61,8 @@ private:
srsran::timer_handler::unique_timer timer_periodic; srsran::timer_handler::unique_timer timer_periodic;
srsran::timer_handler::unique_timer timer_prohibit; srsran::timer_handler::unique_timer timer_prohibit;
std::mutex mutex;
}; };
} // namespace srsue } // namespace srsue

@ -109,9 +109,9 @@ private:
srsran::ul_harq_cfg_t harq_cfg = {}; srsran::ul_harq_cfg_t harq_cfg = {};
float average_retx = 0.0; std::atomic<float> average_retx{0};
uint64_t nof_pkts = 0; std::atomic<uint64_t> nof_pkts{0};
ra_proc* ra_procedure = nullptr; ra_proc* ra_procedure = nullptr;
uint8_t cc_idx = 0; uint8_t cc_idx = 0;
}; };

@ -243,7 +243,7 @@ private:
ue_bearer_manager bearers; // helper to manage mapping between EPS and radio bearers ue_bearer_manager bearers; // helper to manage mapping between EPS and radio bearers
// Metrics helper // Metrics helper
uint32_t ul_dropped_sdus = 0; std::atomic<uint32_t> ul_dropped_sdus{0};
}; };
} // namespace srsue } // namespace srsue

@ -43,7 +43,7 @@
#include <sys/mman.h> #include <sys/mman.h>
#include <unistd.h> #include <unistd.h>
extern bool simulate_rlf; extern std::atomic<bool> simulate_rlf;
using namespace std; using namespace std;
using namespace srsue; using namespace srsue;
@ -648,7 +648,7 @@ static void* input_loop(void*)
metrics_screen->toggle_print(do_metrics); metrics_screen->toggle_print(do_metrics);
} }
} else if (key == "rlf") { } else if (key == "rlf") {
simulate_rlf = true; simulate_rlf.store(true, std::memory_order_relaxed);
cout << "Sending Radio Link Failure" << endl; cout << "Sending Radio Link Failure" << endl;
} else if (key == "q") { } else if (key == "q") {
// let the signal handler do the job // let the signal handler do the job

@ -289,7 +289,12 @@ bool cc_worker::work_dl_regular()
// Decode PDSCH // Decode PDSCH
decode_pdsch(ack_resource, &dl_action, dl_ack); 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); phy->stack->tb_decoded(cc_idx, mac_grant, dl_ack);
} }

@ -184,20 +184,22 @@ void cc_worker::decode_pdcch_dl()
if (logger.debug.enabled()) { if (logger.debug.enabled()) {
for (uint32_t i = 0; i < ue_dl.pdcch_info_count; i++) { 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]; 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; " logger.debug(
"evm=%f; nof_bits=%d; crc=%s;", "PDCCH: dci=%s, %s-rnti=%x, crst_id=%d, ss_type=%s, ncce=%d, al=%d, EPRE=%+.2f, RSRP=%+.2f, corr=%.3f; "
srsran_dci_format_nr_string(info->dci_ctx.format), "evm=%f; nof_bits=%d; crc=%s;",
info->dci_ctx.rnti, srsran_dci_format_nr_string(info->dci_ctx.format),
info->dci_ctx.coreset_id, srsran_rnti_type_str_short(info->dci_ctx.rnti_type),
info->dci_ctx.ss_type, info->dci_ctx.rnti,
info->dci_ctx.location.ncce, info->dci_ctx.coreset_id,
info->dci_ctx.location.L, srsran_ss_type_str(info->dci_ctx.ss_type),
info->measure.epre_dBfs, info->dci_ctx.location.ncce,
info->measure.rsrp_dBfs, info->dci_ctx.location.L,
info->measure.norm_corr, info->measure.epre_dBfs,
info->result.evm, info->measure.rsrp_dBfs,
info->nof_bits, info->measure.norm_corr,
info->result.crc ? "OK" : "KO"); 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 // 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; return true;
} }
@ -494,10 +496,11 @@ bool cc_worker::work_dl()
// Compensate CFO from TRS measurements // Compensate CFO from TRS measurements
if (std::isnormal(phy.args.enable_worker_cfo)) { 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) { for (cf_t* b : rx_buffer) {
if (b != nullptr and ue_ul.ifft.sf_sz != 0) { 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); bool has_ul_ack = phy.get_pending_ack(ul_slot_cfg.idx, pdsch_ack);
// Check if it is a UL slot, if not skip // 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 // No NR signal shall be transmitted
srsran_vec_cf_zero(tx_buffer[0], ue_ul.ifft.sf_sz); srsran_vec_cf_zero(tx_buffer[0], ue_ul.ifft.sf_sz);

@ -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)) { if (prach_buffer->is_ready_to_send(tti, phy_state.cfg.carrier.pci)) {
uint32_t nof_prach_sf = 0; uint32_t nof_prach_sf = 0;
float prach_target_power = 0.0f; 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); worker->set_prach(prach_ptr, prach_target_power);
} }

@ -315,6 +315,10 @@ bool phy::cell_select(phy_cell_t cell)
if (sfsync.cell_select_init(cell)) { if (sfsync.cell_select_init(cell)) {
// Update PCI before starting the background command to make sure PRACH gets the updated value // Update PCI before starting the background command to make sure PRACH gets the updated value
selected_cell.id = cell.pci; 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]() { cmd_worker_cell.add_cmd([this, cell]() {
// Wait SYNC transitions to IDLE // Wait SYNC transitions to IDLE
sfsync.wait_idle(); sfsync.wait_idle();
@ -329,6 +333,10 @@ bool phy::cell_select(phy_cell_t cell)
selected_cell = sync_cell; selected_cell = sync_cell;
} }
stack->cell_select_complete(ret); stack->cell_select_complete(ret);
// Indicate workers that cell selection has finished
common.cell_is_selecting = false;
}); });
return true; return true;
} else { } else {

@ -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()); Debug("SYNC: Worker %d synchronized", lte_worker->get_id());
// Collect and provide metrics from last successful sync // Collect and provide metrics from last successful sync
metrics.sfo = sfo; metrics.sfo = sfo;
metrics.cfo = cfo; metrics.cfo = cfo;
metrics.ta_us = worker_com->ta.get_usec(); 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++) { for (uint32_t i = 0; i < worker_com->args->nof_lte_carriers; i++) {
worker_com->set_sync_metrics(i, metrics); 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 // 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. // 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. // 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); worker_com->semaphore.push(nr_worker);

@ -155,7 +155,10 @@ void mac::reconfiguration(const uint32_t& cc_idx, const bool& enable)
// Implement Section 5.9 // Implement Section 5.9
void mac::reset() void mac::reset()
{ {
bzero(&metrics, sizeof(mac_metrics_t)); {
std::lock_guard<std::mutex> lock(metrics_mutex);
bzero(&metrics, sizeof(mac_metrics_t));
}
Info("Resetting MAC"); Info("Resetting MAC");
@ -210,6 +213,7 @@ void mac::run_tti(const uint32_t tti)
ra_procedure.update_rar_window(ra_window); ra_procedure.update_rar_window(ra_window);
// Count TTI for metrics // Count TTI for metrics
std::lock_guard<std::mutex> lock(metrics_mutex);
for (uint32_t i = 0; i < SRSRAN_MAX_CARRIERS; i++) { for (uint32_t i = 0; i < SRSRAN_MAX_CARRIERS; i++) {
metrics[i].nof_tti++; 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); pcap->write_dl_mch(mch_payload_buffer, len, true, phy_h->get_current_tti(), 0);
} }
std::lock_guard<std::mutex> lock(metrics_mutex);
metrics[0].rx_brate += len * 8; metrics[0].rx_brate += len * 8;
} else { } else {
std::lock_guard<std::mutex> lock(metrics_mutex);
metrics[0].rx_errors++; metrics[0].rx_errors++;
} }
std::lock_guard<std::mutex> lock(metrics_mutex);
metrics[0].rx_pkts++; metrics[0].rx_pkts++;
} }

@ -122,6 +122,8 @@ void bsr_proc::timer_expired(uint32_t timer_id)
uint32_t bsr_proc::get_buffer_state() uint32_t bsr_proc::get_buffer_state()
{ {
std::lock_guard<std::mutex> lock(mutex);
uint32_t buffer = 0; uint32_t buffer = 0;
for (int i = 0; i < NOF_LCG; i++) { for (int i = 0; i < NOF_LCG; i++) {
buffer += get_buffer_state_lcg(i); buffer += get_buffer_state_lcg(i);

@ -50,6 +50,7 @@ void phr_proc::init(phy_interface_mac_lte* phy_h_, srsran::ext_task_sched_handle
void phr_proc::reset() void phr_proc::reset()
{ {
std::lock_guard<std::mutex> lock(mutex);
timer_periodic.stop(); timer_periodic.stop();
timer_prohibit.stop(); timer_prohibit.stop();
phr_is_triggered = false; phr_is_triggered = false;
@ -57,6 +58,8 @@ void phr_proc::reset()
void phr_proc::set_config(srsran::phr_cfg_t& cfg) void phr_proc::set_config(srsran::phr_cfg_t& cfg)
{ {
std::lock_guard<std::mutex> lock(mutex);
phr_cfg = cfg; phr_cfg = cfg;
// First stop timers. If enabled==false or value is Inf, won't be re-started // 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() void phr_proc::start_periodic_timer()
{ {
std::lock_guard<std::mutex> lock(mutex);
if (phr_cfg.enabled && phr_cfg.periodic_timer > 0) { if (phr_cfg.enabled && phr_cfg.periodic_timer > 0) {
timer_periodic.run(); timer_periodic.run();
} }
@ -107,6 +111,7 @@ void phr_proc::start_periodic_timer()
/* Trigger PHR when timers exires */ /* Trigger PHR when timers exires */
void phr_proc::timer_expired(uint32_t timer_id) void phr_proc::timer_expired(uint32_t timer_id)
{ {
std::lock_guard<std::mutex> lock(mutex);
if (!phr_cfg.enabled) { if (!phr_cfg.enabled) {
Warning("PHR: %s timer triggered but PHR has been disabled", Warning("PHR: %s timer triggered but PHR has been disabled",
timer_id == timer_periodic.id() ? "Periodic" : "Prohibit"); timer_id == timer_periodic.id() ? "Periodic" : "Prohibit");
@ -128,6 +133,8 @@ void phr_proc::timer_expired(uint32_t timer_id)
void phr_proc::step() void phr_proc::step()
{ {
std::lock_guard<std::mutex> lock(mutex);
if (phr_cfg.enabled && initiated) { if (phr_cfg.enabled && initiated) {
if (pathloss_changed() && timer_prohibit.is_expired()) { if (pathloss_changed() && timer_prohibit.is_expired()) {
Info("PHR: Triggered by pathloss difference. cur_pathloss_db=%d", last_pathloss_db); 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) bool phr_proc::generate_phr_on_ul_grant(float* phr)
{ {
std::lock_guard<std::mutex> lock(mutex);
if (phr_is_triggered) { if (phr_is_triggered) {
if (phr) { if (phr) {
*phr = phy_h->get_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() bool phr_proc::is_extended()
{ {
std::lock_guard<std::mutex> lock(mutex);
return phr_cfg.extended; return phr_cfg.extended;
} }
} // namespace srsue } // namespace srsue

@ -112,7 +112,7 @@ int ul_harq_entity::get_current_tbs(uint32_t pid)
float ul_harq_entity::get_average_retx() 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")) 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) mac_interface_phy_lte::tb_action_ul_t* action)
{ {
// Compute average number of retransmissions per packet considering previous packet // 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++); harq_entity->average_retx.store(SRSRAN_VEC_CMA((float)current_tx_nb,
cur_grant = grant; harq_entity->average_retx.load(std::memory_order_relaxed),
harq_feedback = false; harq_entity->nof_pkts++),
is_grant_configured = true; std::memory_order_relaxed);
current_tx_nb = 0; cur_grant = grant;
current_irv = 0; 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()); action->is_rar = grant.is_rar || (grant.rnti == harq_entity->rntis->get_temp_rnti());

@ -187,6 +187,7 @@ void mux_nr::generate_bsr_mac_ce(const srsran::bsr_format_nr_t& format)
break; break;
case srsran::LONG_BSR: case srsran::LONG_BSR:
add_bsr_ce = lbsr_ce; add_bsr_ce = lbsr_ce;
break;
default: default:
logger.error("MUX can only be instructred to generate short or long BSRs."); logger.error("MUX can only be instructred to generate short or long BSRs.");
} }

@ -41,7 +41,7 @@
#include <numeric> #include <numeric>
#include <string.h> #include <string.h>
bool simulate_rlf = false; std::atomic<bool> simulate_rlf{false};
using namespace srsran; using namespace srsran;
using namespace asn1::rrc; using namespace asn1::rrc;
@ -212,9 +212,9 @@ void rrc::run_tti()
return; return;
} }
if (simulate_rlf) { if (simulate_rlf.load(std::memory_order_relaxed)) {
radio_link_failure_process(); radio_link_failure_process();
simulate_rlf = false; simulate_rlf.store(false, std::memory_order_relaxed);
} }
// Process pending PHY measurements in IDLE/CONNECTED // 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 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()) { if (drbs.find(drb_id) != drbs.end()) {
asn1::rrc::drb_to_add_mod_s drb_cnfg = drbs[drb_id]; asn1::rrc::drb_to_add_mod_s drb_cnfg = drbs[drb_id];
if (drb_cnfg.lc_ch_id_present) { if (drb_cnfg.lc_ch_id_present) {

@ -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) { if (recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common_present) {
srsran_tdd_config_nr_t tdd; srsran_duplex_config_nr_t duplex;
if (make_phy_tdd_cfg(recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common, &tdd) == true) { if (make_phy_tdd_cfg(recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common, &duplex) == true) {
phy_cfg.tdd = tdd; phy_cfg.duplex = duplex;
} else { } else {
logger.warning("Warning while building tdd structure"); logger.warning("Warning while building duplex structure");
return false; return false;
} }
} else { } else {

@ -120,7 +120,12 @@ bool ue_stack_nr::switch_on()
{ {
// statically setup TUN (will be done through RRC later) // statically setup TUN (will be done through RRC later)
char* err_str = nullptr; 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"); printf("Error configuring TUN interface\n");
} }
return true; return true;

@ -62,8 +62,11 @@ int gw::init(const gw_args_t& args_, stack_interface_gw* stack_)
return SRSRAN_ERROR; return SRSRAN_ERROR;
} }
mbsfn_sock_addr.sin_family = AF_INET; mbsfn_sock_addr.sin_family = AF_INET;
mbsfn_sock_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 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; return SRSRAN_SUCCESS;
} }
@ -462,8 +465,13 @@ int gw::setup_if_addr4(uint32_t ip_addr, char* err_str)
close(tun_fd); close(tun_fd);
return SRSRAN_ERROR_CANT_START; return SRSRAN_ERROR_CANT_START;
} }
ifr.ifr_netmask.sa_family = AF_INET; 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()); 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)) { if (0 > ioctl(sock, SIOCSIFNETMASK, &ifr)) {
err_str = strerror(errno); err_str = strerror(errno);
logger.debug("Failed to set socket netmask: %s", err_str); logger.debug("Failed to set socket netmask: %s", err_str);

@ -52,7 +52,12 @@ int gw_test()
char* err_str = nullptr; char* err_str = nullptr;
int rtn = 0; 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) { if (rtn != SRSRAN_SUCCESS) {
srslog::fetch_basic_logger("TEST", false) srslog::fetch_basic_logger("TEST", false)

@ -29,6 +29,7 @@
#include "srsran/common/epoll_helper.h" #include "srsran/common/epoll_helper.h"
#include "srsran/common/standard_streams.h" #include "srsran/common/standard_streams.h"
#include "srsran/common/network_utils.h"
#include "srsran/srslog/srslog.h" #include "srsran/srslog/srslog.h"
#include "ttcn3_common.h" #include "ttcn3_common.h"
#include <arpa/inet.h> #include <arpa/inet.h>
@ -188,10 +189,10 @@ public:
// Port bind // Port bind
struct sockaddr_in bind_addr = {}; struct sockaddr_in bind_addr = {};
bind_addr.sin_family = AF_INET; if (not srsran::net_utils::set_sockaddr(&bind_addr, net_ip.c_str(), net_port)) {
inet_pton(AF_INET, net_ip.c_str(), &(bind_addr.sin_addr)); srsran::console("Invalid net_ip: %s\n", net_ip.c_str());
bind_addr.sin_port = htons(net_port); return SRSRAN_ERROR;
}
int one = 1; int one = 1;
setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
ret = bind(sock_fd, (struct sockaddr*)&bind_addr, sizeof(bind_addr)); ret = bind(sock_fd, (struct sockaddr*)&bind_addr, sizeof(bind_addr));

@ -37,15 +37,18 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB)
${Boost_LIBRARIES} ${Boost_LIBRARIES}
${ATOMIC_LIBS}) ${ATOMIC_LIBS})
# For each supported bandwidth
foreach (NR_PHY_TEST_BW "10MHz" "20MHz") 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) set(NR_PHY_TEST_DURATION_MS 20)
# DL flooding only
foreach (NR_PHY_TEST_PDSCH "default" "ts38101/5.2-1") 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 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},tdd=${NR_PHY_TEST_TDD},pdsch=${NR_PHY_TEST_PDSCH} --reference=carrier=${NR_PHY_TEST_BW},duplex=${NR_PHY_TEST_DUPLEX},pdsch=${NR_PHY_TEST_PDSCH}
--duration=${NR_PHY_TEST_DURATION_MS} --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.start=0 # Start at RB 0
--gnb.stack.pdsch.length=52 # Full 10 MHz BW --gnb.stack.pdsch.length=52 # Full 10 MHz BW
--gnb.stack.pdsch.mcs=27 # Maximum MCS --gnb.stack.pdsch.mcs=27 # Maximum MCS
@ -55,11 +58,12 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB)
) )
endforeach () endforeach ()
add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_TDD}_ul_only nr_phy_test # UL flooding
--reference=carrier=${NR_PHY_TEST_BW},tdd=${NR_PHY_TEST_TDD} 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} --duration=${NR_PHY_TEST_DURATION_MS}
--gnb.stack.pdsch.slots=6 # No PDSCH --gnb.stack.pdsch.slots=none
--gnb.stack.pusch.slots=6,7,8,9 # All possible UL slots --gnb.stack.pusch.slots=all
--gnb.stack.pusch.start=0 # Start at RB 0 --gnb.stack.pusch.start=0 # Start at RB 0
--gnb.stack.pusch.length=52 # Full 10 MHz BW --gnb.stack.pusch.length=52 # Full 10 MHz BW
--gnb.stack.pusch.mcs=28 # Maximum MCS --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} --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 # DL and UL flooding
--reference=carrier=${NR_PHY_TEST_BW},tdd=${NR_PHY_TEST_TDD} 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} --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.start=0 # Start at RB 0
--gnb.stack.pdsch.length=52 # Full 10 MHz BW --gnb.stack.pdsch.length=52 # Full 10 MHz BW
--gnb.stack.pdsch.mcs=28 # Maximum MCS --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.start=0 # Start at RB 0
--gnb.stack.pusch.length=52 # Full 10 MHz BW --gnb.stack.pusch.length=52 # Full 10 MHz BW
--gnb.stack.pusch.mcs=28 # Maximum MCS --gnb.stack.pusch.mcs=28 # Maximum MCS

@ -369,10 +369,22 @@ public:
ul.mcs = args.pusch.mcs; ul.mcs = args.pusch.mcs;
if (args.pdsch.slots != "none" and not args.pdsch.slots.empty()) { 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()) { 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 // Select DCI locations
@ -414,7 +426,11 @@ public:
// Setup DL Data to ACK timing // Setup DL Data to ACK timing
for (uint32_t i = 0; i < SRSRAN_NOF_SF_X_FRAME; i++) { 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 // 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 // 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; return SRSRAN_SUCCESS;
} }
@ -460,7 +476,7 @@ public:
} }
// Check if the UL slot is valid, if not skip UL scheduling // 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; return SRSRAN_SUCCESS;
} }

Loading…
Cancel
Save