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_tdd_cfg(const asn1::rrc_nr::tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common,
srsran_tdd_config_nr_t* srsran_tdd_config_nr);
srsran_duplex_config_nr_t* srsran_duplex_config_nr);
bool make_phy_harq_ack_cfg(const asn1::rrc_nr::phys_cell_group_cfg_s& phys_cell_group_cfg,
srsran_harq_ack_cfg_hl_t* srsran_ue_dl_nr_harq_ack_cfg);
bool make_phy_coreset_cfg(const asn1::rrc_nr::ctrl_res_set_s& ctrl_res_set, srsran_coreset_t* srsran_coreset);

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

@ -44,7 +44,7 @@ struct phy_cfg_nr_t {
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 pusch = {};
srsran_pucch_nr_hl_cfg_t pucch = {};

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

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

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

@ -129,67 +129,6 @@ public:
virtual void notify_pdcp_integrity_error(uint16_t rnti, uint32_t lcid) = 0;
};
// RRC interfaces for NSA operation
/// X2AP inspired interface to allow EUTRA RRC to call NR RRC
class rrc_nr_interface_rrc
{
public:
struct sgnb_addition_req_params_t {
uint32_t eps_bearer_id;
// add configuration check
// E-RAB Parameters, Tunnel address (IP address, TEID)
// QCI, security, etc
};
/// Request addition of NR carrier for UE
virtual int sgnb_addition_request(uint16_t eutra_rnti, const sgnb_addition_req_params_t& params) = 0;
/// Provide information whether the requested configuration was applied successfully by the UE
virtual int sgnb_reconfiguration_complete(uint16_t eutra_rnti, asn1::dyn_octstring reconfig_response) = 0;
};
/// X2AP inspired interface for response from NR RRC to EUTRA RRC
class rrc_eutra_interface_rrc_nr
{
public:
/**
* @brief List of parameters included in the SgNB addition Ack message
* @param nr_secondary_cell_group_cfg_r15 Encoded part of the RRC Reconfiguration
* @param nr_radio_bearer_cfg1_r15 Encoded part of the RRC Reconfiguration
* @param eps_bearer_id ID of the transfered bearer
*/
struct sgnb_addition_ack_params_t {
uint16_t nr_rnti = SRSRAN_INVALID_RNTI; // RNTI that was assigned to the UE
asn1::dyn_octstring nr_secondary_cell_group_cfg_r15;
asn1::dyn_octstring nr_radio_bearer_cfg1_r15;
uint32_t eps_bearer_id = 0; // (list of) successfully transfered EPS bearers
};
/**
* @brief Signal successful addition of UE
*
* @param eutra_rnti The RNTI that the EUTRA RRC used to request the SgNB addition
* @param params Parameter list
*/
virtual void sgnb_addition_ack(uint16_t eutra_rnti, sgnb_addition_ack_params_t params) = 0;
/**
* @brief Signal unsuccessful SgNB addition
*
* @param eutra_rnti The RNTI that the EUTRA RRC used to request the SgNB addition
*/
virtual void sgnb_addition_reject(uint16_t eutra_rnti) = 0;
/**
* @brief Signal completion of SgNB addition after UE (with new NR identity) has attached
*
* @param eutra_rnti The RNTI that the EUTRA RRC used to request the SgNB addition
* @param nr_rnti The RNTI that has been assigned to the UE on the SgNB
*/
virtual void sgnb_addition_complete(uint16_t eutra_rnti, uint16_t nr_rnti) = 0;
};
} // namespace srsenb
#endif // SRSRAN_ENB_RRC_INTERFACES_H

@ -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;
float trs_epre_ema_alpha = 0.1f; ///< EPRE measurement exponential average alpha
float trs_rsrp_ema_alpha = 0.1f; ///< RSRP measurement exponential average alpha
float trs_sinr_ema_alpha = 0.1f; ///< SINR measurement exponential average alpha
float trs_cfo_ema_alpha = 0.1f; ///< RSRP measurement exponential average alpha
bool enable_worker_cfo = true; ///< Enable/Disable open loop CFO correction at the workers

@ -137,4 +137,6 @@ typedef struct SRSRAN_API {
uint32_t count; ///< Number of resources in the set
} srsran_csi_rs_zp_set_t;
SRSRAN_API bool srsran_csi_rs_resource_mapping_is_valid(const srsran_csi_rs_resource_mapping_t *res);
#endif // SRSRAN_CSI_RS_CFG_H

@ -467,6 +467,17 @@ typedef struct SRSRAN_API {
srsran_tdd_pattern_t pattern2;
} srsran_tdd_config_nr_t;
/**
* @brief Describes duplex configuration
*/
typedef struct SRSRAN_API {
srsran_duplex_mode_t mode;
union {
srsran_tdd_config_nr_t tdd; ///< TDD configuration
// ... add here other mode parameters
};
} srsran_duplex_config_nr_t;
/**
* @brief Describes a measurement based on NZP-CSI-RS or SSB-CSI
* @note Used for tracking RSRP, SNR, CFO, SFO, and so on
@ -501,6 +512,13 @@ SRSRAN_API const char* srsran_rnti_type_str(srsran_rnti_type_t rnti_type);
*/
SRSRAN_API const char* srsran_rnti_type_str_short(srsran_rnti_type_t rnti_type);
/**
* @brief Get the Search Space Type string for a given type
* @param ss_type The given Search Space Type
* @return The string describing the SS Type
*/
SRSRAN_API const char* srsran_ss_type_str(srsran_search_space_type_t ss_type);
/**
* @brief Get the RNTI type name for NR
* @param rnti_type RNTI type name
@ -595,21 +613,21 @@ SRSRAN_API float srsran_symbol_distance_s(uint32_t l0, uint32_t l1, srsran_subca
/**
* @brief Decides whether a given slot is configured as Downlink
* @param cfg Provides TDD configuration
* @param cfg Provides the carrier duplex configuration
* @param numerology Provides BWP numerology
* @param slot_idx Slot index in the frame for the given numerology
* @return true if the provided slot index is configured for Downlink
*/
SRSRAN_API bool srsran_tdd_nr_is_dl(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx);
SRSRAN_API bool srsran_duplex_nr_is_dl(const srsran_duplex_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx);
/**
* @brief Decides whether a given slot is configured as Uplink
* @param cfg Provides TDD configuration
* @param cfg Provides the carrier duplex configuration
* @param numerology Provides BWP numerology
* @param slot_idx Slot index in the frame for the given numerology
* @return true if the provided slot index is configured for Uplink
*/
SRSRAN_API bool srsran_tdd_nr_is_ul(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx);
SRSRAN_API bool srsran_duplex_nr_is_ul(const srsran_duplex_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx);
SRSRAN_API int srsran_carrier_to_cell(const srsran_carrier_nr_t* carrier, srsran_cell_t* cell);

@ -76,6 +76,8 @@ SRSRAN_API int srsran_gnb_dl_pdsch_put(srsran_gnb_dl_t* q,
const srsran_sch_cfg_nr_t* cfg,
uint8_t* data[SRSRAN_MAX_TB]);
SRSRAN_API float srsran_gnb_dl_get_maximum_signal_power_dBfs(uint32_t nof_prb);
SRSRAN_API int
srsran_gnb_dl_pdsch_info(const srsran_gnb_dl_t* q, const srsran_sch_cfg_nr_t* cfg, char* str, uint32_t str_len);

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

@ -280,21 +280,21 @@ bool make_phy_rach_cfg(const rach_cfg_common_s& asn1_type, srsran_prach_cfg_t* p
};
bool make_phy_tdd_cfg(const tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common,
srsran_tdd_config_nr_t* in_srsran_tdd_config_nr)
srsran_duplex_config_nr_t* in_srsran_duplex_config_nr)
{
srsran_tdd_config_nr_t srsran_tdd_config_nr = {};
srsran_duplex_config_nr_t srsran_duplex_config_nr = {};
switch (tdd_ul_dl_cfg_common.pattern1.dl_ul_tx_periodicity) {
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms1:
srsran_tdd_config_nr.pattern1.period_ms = 1;
srsran_duplex_config_nr.tdd.pattern1.period_ms = 1;
break;
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms2:
srsran_tdd_config_nr.pattern1.period_ms = 2;
srsran_duplex_config_nr.tdd.pattern1.period_ms = 2;
break;
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms5:
srsran_tdd_config_nr.pattern1.period_ms = 5;
srsran_duplex_config_nr.tdd.pattern1.period_ms = 5;
break;
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms10:
srsran_tdd_config_nr.pattern1.period_ms = 10;
srsran_duplex_config_nr.tdd.pattern1.period_ms = 10;
break;
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms1p25:
@ -306,12 +306,12 @@ bool make_phy_tdd_cfg(const tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common,
tdd_ul_dl_cfg_common.pattern1.dl_ul_tx_periodicity.to_string());
return false;
}
srsran_tdd_config_nr.pattern1.nof_dl_slots = tdd_ul_dl_cfg_common.pattern1.nrof_dl_slots;
srsran_tdd_config_nr.pattern1.nof_dl_symbols = tdd_ul_dl_cfg_common.pattern1.nrof_dl_symbols;
srsran_tdd_config_nr.pattern1.nof_ul_slots = tdd_ul_dl_cfg_common.pattern1.nrof_ul_slots;
srsran_tdd_config_nr.pattern1.nof_ul_symbols = tdd_ul_dl_cfg_common.pattern1.nrof_ul_symbols;
srsran_duplex_config_nr.tdd.pattern1.nof_dl_slots = tdd_ul_dl_cfg_common.pattern1.nrof_dl_slots;
srsran_duplex_config_nr.tdd.pattern1.nof_dl_symbols = tdd_ul_dl_cfg_common.pattern1.nrof_dl_symbols;
srsran_duplex_config_nr.tdd.pattern1.nof_ul_slots = tdd_ul_dl_cfg_common.pattern1.nrof_ul_slots;
srsran_duplex_config_nr.tdd.pattern1.nof_ul_symbols = tdd_ul_dl_cfg_common.pattern1.nrof_ul_symbols;
// Copy and return struct
*in_srsran_tdd_config_nr = srsran_tdd_config_nr;
*in_srsran_duplex_config_nr = srsran_duplex_config_nr;
if (not tdd_ul_dl_cfg_common.pattern2_present) {
return true;
@ -319,16 +319,16 @@ bool make_phy_tdd_cfg(const tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common,
switch (tdd_ul_dl_cfg_common.pattern2.dl_ul_tx_periodicity) {
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms1:
srsran_tdd_config_nr.pattern2.period_ms = 1;
srsran_duplex_config_nr.tdd.pattern2.period_ms = 1;
break;
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms2:
srsran_tdd_config_nr.pattern2.period_ms = 2;
srsran_duplex_config_nr.tdd.pattern2.period_ms = 2;
break;
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms5:
srsran_tdd_config_nr.pattern2.period_ms = 5;
srsran_duplex_config_nr.tdd.pattern2.period_ms = 5;
break;
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms10:
srsran_tdd_config_nr.pattern2.period_ms = 10;
srsran_duplex_config_nr.tdd.pattern2.period_ms = 10;
break;
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms1p25:
@ -341,12 +341,12 @@ bool make_phy_tdd_cfg(const tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common,
return false;
}
srsran_tdd_config_nr.pattern2.nof_dl_slots = tdd_ul_dl_cfg_common.pattern2.nrof_dl_slots;
srsran_tdd_config_nr.pattern2.nof_dl_symbols = tdd_ul_dl_cfg_common.pattern2.nrof_dl_symbols;
srsran_tdd_config_nr.pattern2.nof_ul_slots = tdd_ul_dl_cfg_common.pattern2.nrof_ul_slots;
srsran_tdd_config_nr.pattern2.nof_ul_symbols = tdd_ul_dl_cfg_common.pattern2.nrof_ul_symbols;
srsran_duplex_config_nr.tdd.pattern2.nof_dl_slots = tdd_ul_dl_cfg_common.pattern2.nrof_dl_slots;
srsran_duplex_config_nr.tdd.pattern2.nof_dl_symbols = tdd_ul_dl_cfg_common.pattern2.nrof_dl_symbols;
srsran_duplex_config_nr.tdd.pattern2.nof_ul_slots = tdd_ul_dl_cfg_common.pattern2.nrof_ul_slots;
srsran_duplex_config_nr.tdd.pattern2.nof_ul_symbols = tdd_ul_dl_cfg_common.pattern2.nrof_ul_symbols;
// Copy and return struct
*in_srsran_tdd_config_nr = srsran_tdd_config_nr;
*in_srsran_duplex_config_nr = srsran_duplex_config_nr;
return true;
}
@ -1079,6 +1079,15 @@ bool make_phy_zp_csi_rs_resource(const asn1::rrc_nr::zp_csi_rs_res_s& zp_csi_rs_
}
zp_csi_rs_resource.resource_mapping.freq_band.nof_rb = zp_csi_rs_res.res_map.freq_band.nrof_rbs;
zp_csi_rs_resource.resource_mapping.freq_band.start_rb = zp_csi_rs_res.res_map.freq_band.start_rb;
// Validate CSI-RS resource mapping
if (not srsran_csi_rs_resource_mapping_is_valid(&zp_csi_rs_resource.resource_mapping)) {
asn1::json_writer json_writer;
zp_csi_rs_res.res_map.to_json(json_writer);
asn1::log_error("Resource mapping is invalid or not implemented: %s", json_writer.to_string());
return false;
}
if (zp_csi_rs_res.periodicity_and_offset_present) {
switch (zp_csi_rs_res.periodicity_and_offset.type()) {
case csi_res_periodicity_and_offset_c::types_opts::options::slots4:
@ -1237,6 +1246,14 @@ bool make_phy_nzp_csi_rs_resource(const asn1::rrc_nr::nzp_csi_rs_res_s& asn1_nzp
csi_rs_nzp_resource.resource_mapping.freq_band.nof_rb = asn1_nzp_csi_rs_res.res_map.freq_band.nrof_rbs;
csi_rs_nzp_resource.resource_mapping.freq_band.start_rb = asn1_nzp_csi_rs_res.res_map.freq_band.start_rb;
// Validate CSI-RS resource mapping
if (not srsran_csi_rs_resource_mapping_is_valid(&csi_rs_nzp_resource.resource_mapping)) {
asn1::json_writer json_writer;
asn1_nzp_csi_rs_res.res_map.to_json(json_writer);
asn1::log_error("Resource mapping is invalid or not implemented: %s", json_writer.to_string());
return false;
}
csi_rs_nzp_resource.power_control_offset = asn1_nzp_csi_rs_res.pwr_ctrl_offset;
if (asn1_nzp_csi_rs_res.pwr_ctrl_offset_ss_present) {
csi_rs_nzp_resource.power_control_offset_ss = asn1_nzp_csi_rs_res.pwr_ctrl_offset_ss.to_number();

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

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

@ -53,13 +53,13 @@ phy_cfg_nr_default_t::reference_cfg_t::reference_cfg_t(const std::string& args)
}
}
srsran_assert(carrier != R_CARRIER_COUNT, "Invalid carrier reference configuration '%s'", param.back().c_str());
} else if (param.front() == "tdd") {
for (tdd = R_TDD_CUSTOM_6_4; tdd < R_TDD_COUNT; tdd = inc(tdd)) {
if (R_TDD_STRING[tdd] == param.back()) {
} else if (param.front() == "duplex") {
for (duplex = R_DUPLEX_FDD; duplex < R_DUPLEX_COUNT; duplex = inc(duplex)) {
if (R_DUPLEX_STRING[duplex] == param.back()) {
break;
}
}
srsran_assert(tdd != R_TDD_COUNT, "Invalid TDD reference configuration '%s'", param.back().c_str());
srsran_assert(duplex != R_DUPLEX_COUNT, "Invalid duplex reference configuration '%s'", param.back().c_str());
} else if (param.front() == "pdsch") {
for (pdsch = R_PDSCH_DEFAULT; pdsch < R_PDSCH_COUNT; pdsch = inc(pdsch)) {
if (R_PDSCH_STRING[pdsch] == param.back()) {
@ -95,8 +95,18 @@ void phy_cfg_nr_default_t::make_carrier_custom_20MHz(srsran_carrier_nr_t& carrie
carrier.scs = srsran_subcarrier_spacing_15kHz;
}
void phy_cfg_nr_default_t::make_tdd_custom_6_4(srsran_tdd_config_nr_t& tdd)
void phy_cfg_nr_default_t::make_tdd_custom_6_4(srsran_duplex_config_nr_t& conf)
{
// Set the duplex mode to TDD
conf.mode = SRSRAN_DUPLEX_MODE_TDD;
// Select TDD config
srsran_tdd_config_nr_t& tdd = conf.tdd;
// Initialise pattern
tdd = {};
// Enable pattern 1
tdd.pattern1.period_ms = 10;
tdd.pattern1.nof_dl_slots = 6;
tdd.pattern1.nof_dl_symbols = 0;
@ -107,8 +117,17 @@ void phy_cfg_nr_default_t::make_tdd_custom_6_4(srsran_tdd_config_nr_t& tdd)
tdd.pattern2.period_ms = 0;
}
void phy_cfg_nr_default_t::make_tdd_fr1_15_1(srsran_tdd_config_nr_t& tdd)
{
void phy_cfg_nr_default_t::make_tdd_fr1_15_1(srsran_duplex_config_nr_t& conf)
{ // Set the duplex mode to TDD
conf.mode = SRSRAN_DUPLEX_MODE_TDD;
// Select TDD config
srsran_tdd_config_nr_t& tdd = conf.tdd;
// Initialise pattern
tdd = {};
// Enable pattern 1
tdd.pattern1.period_ms = 5;
tdd.pattern1.nof_dl_slots = 3;
tdd.pattern1.nof_dl_symbols = 10;
@ -330,8 +349,11 @@ void phy_cfg_nr_default_t::make_pucch_custom_one(srsran_pucch_nr_hl_cfg_t& pucch
void phy_cfg_nr_default_t::make_harq_auto(srsran_harq_ack_cfg_hl_t& harq,
const srsran_carrier_nr_t& carrier,
const srsran_tdd_config_nr_t& tdd_cfg)
const srsran_duplex_config_nr_t& duplex_cfg)
{
if (duplex_cfg.mode == SRSRAN_DUPLEX_MODE_TDD) {
const srsran_tdd_config_nr_t& tdd_cfg = duplex_cfg.tdd;
// Generate as many entries as DL slots
harq.nof_dl_data_to_ul_ack = SRSRAN_MIN(tdd_cfg.pattern1.nof_dl_slots, SRSRAN_MAX_NOF_DL_DATA_TO_UL);
if (tdd_cfg.pattern1.nof_dl_symbols > 0) {
@ -347,7 +369,7 @@ void phy_cfg_nr_default_t::make_harq_auto(srsran_harq_ack_cfg_hl_t& harq,
}
// After that try if n+4 is UL slot
if (srsran_tdd_nr_is_ul(&tdd_cfg, carrier.scs, n + 4)) {
if (srsran_duplex_nr_is_ul(&duplex_cfg, carrier.scs, n + 4)) {
harq.dl_data_to_ul_ack[n] = 4;
continue;
}
@ -355,6 +377,10 @@ void phy_cfg_nr_default_t::make_harq_auto(srsran_harq_ack_cfg_hl_t& harq,
// Otherwise set delay to the first UL slot of the next TDD period
harq.dl_data_to_ul_ack[n] = (tdd_cfg.pattern1.period_ms + tdd_cfg.pattern1.nof_dl_slots) - n;
}
} else {
harq.dl_data_to_ul_ack[0] = 4;
harq.nof_dl_data_to_ul_ack = 1;
}
// Zero the rest
for (uint32_t i = harq.nof_dl_data_to_ul_ack; i < SRSRAN_MAX_NOF_DL_DATA_TO_UL; i++) {
@ -386,14 +412,17 @@ phy_cfg_nr_default_t::phy_cfg_nr_default_t(const reference_cfg_t& reference_cfg)
srsran_assertion_failure("Invalid carrier reference");
}
switch (reference_cfg.tdd) {
case reference_cfg_t::R_TDD_CUSTOM_6_4:
make_tdd_custom_6_4(tdd);
switch (reference_cfg.duplex) {
case reference_cfg_t::R_DUPLEX_FDD:
duplex.mode = SRSRAN_DUPLEX_MODE_FDD;
break;
case reference_cfg_t::R_DUPLEX_TDD_CUSTOM_6_4:
make_tdd_custom_6_4(duplex);
break;
case reference_cfg_t::R_TDD_FR1_15_1:
make_tdd_fr1_15_1(tdd);
case reference_cfg_t::R_DUPLEX_TDD_FR1_15_1:
make_tdd_fr1_15_1(duplex);
break;
case reference_cfg_t::R_TDD_COUNT:
case reference_cfg_t::R_DUPLEX_COUNT:
srsran_assertion_failure("Invalid TDD reference");
}
@ -428,7 +457,7 @@ phy_cfg_nr_default_t::phy_cfg_nr_default_t(const reference_cfg_t& reference_cfg)
switch (reference_cfg.harq) {
case reference_cfg_t::R_HARQ_AUTO:
make_harq_auto(harq_ack, carrier, tdd);
make_harq_auto(harq_ack, carrier, duplex);
break;
}

@ -63,7 +63,7 @@ bool pdcp_entity_lte::configure(const pdcp_config_t& cnfg_)
if (active) {
// Already configured
if (cnfg_ != cfg) {
logger.error("Bearer reconfiguration not supported. LCID=%d.", rrc->get_rb_name(lcid));
logger.error("Bearer reconfiguration not supported. LCID=%s.", rrc->get_rb_name(lcid));
return false;
}
return true;

@ -55,7 +55,7 @@ bool pdcp_entity_nr::configure(const pdcp_config_t& cnfg_)
if (active) {
// Already configured
if (cnfg_ != cfg) {
logger.error("Bearer reconfiguration not supported. LCID=%d.", rrc->get_rb_name(lcid));
logger.error("Bearer reconfiguration not supported. LCID=%s.", rrc->get_rb_name(lcid));
return false;
}
return true;

@ -98,8 +98,7 @@ static int csi_rs_location_get_k_list(const srsran_csi_rs_resource_mapping_t* re
}
// Row 2
if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->nof_ports == 1 &&
resource->cdm == srsran_csi_rs_cdm_nocdm) {
if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->cdm == srsran_csi_rs_cdm_nocdm) {
if (resource->density == srsran_csi_rs_resource_mapping_density_one ||
resource->density == srsran_csi_rs_resource_mapping_density_dot5_even ||
resource->density == srsran_csi_rs_resource_mapping_density_dot5_odd) {
@ -151,8 +150,7 @@ static int csi_rs_location_get_l_list(const srsran_csi_rs_resource_mapping_t* re
}
// Row 2
if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->nof_ports == 1 &&
resource->cdm == srsran_csi_rs_cdm_nocdm) {
if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->cdm == srsran_csi_rs_cdm_nocdm) {
if (resource->density == srsran_csi_rs_resource_mapping_density_one ||
resource->density == srsran_csi_rs_resource_mapping_density_dot5_even ||
resource->density == srsran_csi_rs_resource_mapping_density_dot5_odd) {
@ -206,24 +204,14 @@ bool srsran_csi_rs_send(const srsran_csi_rs_period_and_offset_t* periodicity, co
static int csi_rs_nof_cdm_groups(const srsran_csi_rs_resource_mapping_t* resource)
{
// Row 1
if (resource->row == srsran_csi_rs_resource_mapping_row_1 && resource->nof_ports == 1 &&
resource->density == srsran_csi_rs_resource_mapping_density_three && resource->cdm == srsran_csi_rs_cdm_nocdm) {
return 1;
}
// Row 1
if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->nof_ports == 1 &&
resource->cdm == srsran_csi_rs_cdm_nocdm) {
if (resource->density == srsran_csi_rs_resource_mapping_density_one ||
resource->density == srsran_csi_rs_resource_mapping_density_dot5_even ||
resource->density == srsran_csi_rs_resource_mapping_density_dot5_odd) {
return 1;
}
}
// Row 2
if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->nof_ports == 1 &&
resource->cdm == srsran_csi_rs_cdm_nocdm) {
if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->cdm == srsran_csi_rs_cdm_nocdm) {
if (resource->density == srsran_csi_rs_resource_mapping_density_one ||
resource->density == srsran_csi_rs_resource_mapping_density_dot5_even ||
resource->density == srsran_csi_rs_resource_mapping_density_dot5_odd) {
@ -241,6 +229,29 @@ static int csi_rs_nof_cdm_groups(const srsran_csi_rs_resource_mapping_t* resourc
return SRSRAN_ERROR;
}
bool srsran_csi_rs_resource_mapping_is_valid(const srsran_csi_rs_resource_mapping_t* res)
{
if (res == NULL) {
return false;
}
if (csi_rs_nof_cdm_groups(res) < 1) {
return false;
}
uint32_t l_list[CSI_RS_MAX_SYMBOLS_SLOT] = {};
if (csi_rs_location_get_l_list(res, 0, l_list) < SRSRAN_SUCCESS) {
return false;
}
uint32_t k_list[CSI_RS_MAX_SUBC_PRB] = {};
if (csi_rs_location_get_k_list(res, 0, k_list) < SRSRAN_SUCCESS) {
return false;
}
return true;
}
uint32_t csi_rs_count(srsran_csi_rs_density_t density, uint32_t nprb)
{
switch (density) {
@ -705,7 +716,7 @@ int srsran_csi_rs_nzp_measure_trs(const srsran_carrier_nr_t* carrier,
float cfo_max = 0.0f;
for (uint32_t i = 1; i < count; i++) {
float time_diff = srsran_symbol_distance_s(measurements[i - 1].l0, measurements[i].l0, carrier->scs);
float phase_diff = cargf(measurements[i - 1].corr * conjf(measurements[i].corr));
float phase_diff = cargf(measurements[i].corr * conjf(measurements[i - 1].corr));
float cfo_max_temp = 0.0f;
// Avoid zero division

@ -72,6 +72,31 @@ const char* srsran_rnti_type_str_short(srsran_rnti_type_t rnti_type)
return "unknown";
}
const char* srsran_ss_type_str(srsran_search_space_type_t ss_type)
{
switch (ss_type) {
case srsran_search_space_type_common_0:
return "common0";
case srsran_search_space_type_common_0A:
return "common0A";
case srsran_search_space_type_common_1:
return "common1";
case srsran_search_space_type_common_2:
return "common2";
case srsran_search_space_type_common_3:
return "common3";
case srsran_search_space_type_ue:
return "ue";
case srsran_search_space_type_rar:
return "rar";
case srsran_search_space_type_cg:
return "cg";
default:; // Do nothing
break;
}
return "unknown";
}
const char* srsran_dci_format_nr_string(srsran_dci_format_nr_t format)
{
switch (format) {
@ -267,13 +292,8 @@ float srsran_symbol_distance_s(uint32_t l0, uint32_t l1, srsran_subcarrier_spaci
return srsran_symbol_offset_s(l1, scs) - srsran_symbol_offset_s(l0, scs);
}
bool srsran_tdd_nr_is_dl(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx)
static bool tdd_nr_is_dl(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx)
{
// Protect NULL pointer access
if (cfg == NULL) {
return false;
}
// Prevent zero division
if (cfg->pattern1.period_ms == 0 && cfg->pattern2.period_ms == 0) {
return false;
@ -296,13 +316,24 @@ bool srsran_tdd_nr_is_dl(const srsran_tdd_config_nr_t* cfg, uint32_t numerology,
(slot_idx_period == pattern->nof_dl_slots && pattern->nof_dl_symbols != 0));
}
bool srsran_tdd_nr_is_ul(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx)
bool srsran_duplex_nr_is_dl(const srsran_duplex_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx)
{
// Protect NULL pointer access
if (cfg == NULL) {
return false;
}
// In case of TDD
if (cfg->mode == SRSRAN_DUPLEX_MODE_TDD) {
return tdd_nr_is_dl(&cfg->tdd, numerology, slot_idx);
}
return true;
}
static bool tdd_nr_is_ul(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx)
{
// Prevent zero division
if (cfg->pattern1.period_ms == 0 && cfg->pattern2.period_ms == 0) {
return false;
@ -327,6 +358,21 @@ bool srsran_tdd_nr_is_ul(const srsran_tdd_config_nr_t* cfg, uint32_t numerology,
return (slot_idx_period > start_ul || (slot_idx_period == start_ul && pattern->nof_ul_symbols != 0));
}
bool srsran_duplex_nr_is_ul(const srsran_duplex_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx)
{
// Protect NULL pointer access
if (cfg == NULL) {
return false;
}
// In case of TDD
if (cfg->mode == SRSRAN_DUPLEX_MODE_TDD) {
return tdd_nr_is_ul(&cfg->tdd, numerology, slot_idx);
}
return true;
}
int srsran_carrier_to_cell(const srsran_carrier_nr_t* carrier, srsran_cell_t* cell)
{
// Protect memory access

@ -59,7 +59,21 @@ __attribute__((constructor)) static void srsran_dft_load()
#ifdef FFTW_WISDOM_FILE
char full_path[256];
get_fftw_wisdom_file(full_path, sizeof(full_path));
fftwf_import_wisdom_from_filename(full_path);
// lockf needs a file descriptor open for writing, so this must be r+
FILE* fd = fopen(full_path, "r+");
if (fd == NULL) {
return;
}
if (lockf(fileno(fd), F_LOCK, 0) == -1) {
perror("lockf()");
return;
}
fftwf_import_wisdom_from_file(fd);
if (lockf(fileno(fd), F_ULOCK, 0) == -1) {
perror("u-lockf()");
return;
}
fclose(fd);
#else
printf("Warning: FFTW Wisdom file not defined\n");
#endif
@ -71,7 +85,20 @@ __attribute__((destructor)) static void srsran_dft_exit()
#ifdef FFTW_WISDOM_FILE
char full_path[256];
get_fftw_wisdom_file(full_path, sizeof(full_path));
fftwf_export_wisdom_to_filename(full_path);
FILE* fd = fopen(full_path, "w");
if (fd == NULL) {
return;
}
if (lockf(fileno(fd), F_LOCK, 0) == -1) {
perror("lockf()");
return;
}
fftwf_export_wisdom_to_file(fd);
if (lockf(fileno(fd), F_ULOCK, 0) == -1) {
perror("u-lockf()");
return;
}
fclose(fd);
#endif
fftwf_cleanup();
}

@ -22,6 +22,11 @@
#include "srsran/phy/gnb/gnb_dl.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)
{
if (q->max_prb < new_nof_prb) {
@ -171,11 +176,21 @@ void srsran_gnb_dl_gen_signal(srsran_gnb_dl_t* q)
return;
}
float norm_factor = gnb_dl_get_norm_factor(q->pdcch.carrier.nof_prb);
for (uint32_t i = 0; i < q->nof_tx_antennas; i++) {
srsran_ofdm_tx_sf(&q->fft[i]);
srsran_vec_sc_prod_cfc(q->fft[i].cfg.out_buffer, norm_factor, q->fft[i].cfg.out_buffer, (uint32_t)q->fft[i].sf_sz);
}
}
float srsran_gnb_dl_get_maximum_signal_power_dBfs(uint32_t nof_prb)
{
return srsran_convert_amplitude_to_dB(gnb_dl_get_norm_factor(nof_prb)) +
srsran_convert_power_to_dB((float)nof_prb * SRSRAN_NRE) + 3.0f;
}
int srsran_gnb_dl_base_zero(srsran_gnb_dl_t* q)
{
if (q == NULL) {

@ -39,7 +39,7 @@ int srsran_netsink_init(srsran_netsink_t* q, const char* address, uint16_t port,
q->sockfd = socket(AF_INET, type == SRSRAN_NETSINK_TCP ? SOCK_STREAM : SOCK_DGRAM, 0);
if (q->sockfd < 0) {
perror("socket");
return -1;
return SRSRAN_ERROR;
}
int enable = 1;
@ -53,12 +53,15 @@ int srsran_netsink_init(srsran_netsink_t* q, const char* address, uint16_t port,
#endif
q->servaddr.sin_family = AF_INET;
q->servaddr.sin_addr.s_addr = inet_addr(address);
if (inet_pton(q->servaddr.sin_family, address, &q->servaddr.sin_addr) != 1) {
perror("inet_pton");
return SRSRAN_ERROR;
}
q->servaddr.sin_port = htons(port);
q->connected = false;
q->type = type;
return 0;
return SRSRAN_SUCCESS;
}
void srsran_netsink_free(srsran_netsink_t* q)
@ -73,9 +76,9 @@ int srsran_netsink_set_nonblocking(srsran_netsink_t* q)
{
if (fcntl(q->sockfd, F_SETFL, O_NONBLOCK)) {
perror("fcntl");
return -1;
return SRSRAN_ERROR;
}
return 0;
return SRSRAN_SUCCESS;
}
int srsran_netsink_write(srsran_netsink_t* q, void* buffer, int nof_bytes)
@ -83,11 +86,11 @@ int srsran_netsink_write(srsran_netsink_t* q, void* buffer, int nof_bytes)
if (!q->connected) {
if (connect(q->sockfd, &q->servaddr, sizeof(q->servaddr)) < 0) {
if (errno == ECONNREFUSED || errno == EINPROGRESS) {
return 0;
return SRSRAN_SUCCESS;
} else {
perror("connect");
exit(-1);
return -1;
return SRSRAN_ERROR;
}
} else {
q->connected = true;
@ -102,10 +105,10 @@ int srsran_netsink_write(srsran_netsink_t* q, void* buffer, int nof_bytes)
q->sockfd = socket(AF_INET, q->type == SRSRAN_NETSINK_TCP ? SOCK_STREAM : SOCK_DGRAM, 0);
if (q->sockfd < 0) {
perror("socket");
return -1;
return SRSRAN_ERROR;
}
q->connected = false;
return 0;
return SRSRAN_SUCCESS;
}
}
}

@ -39,7 +39,7 @@ int srsran_netsource_init(srsran_netsource_t* q, const char* address, uint16_t p
if (q->sockfd < 0) {
perror("socket");
return -1;
return SRSRAN_ERROR;
}
// Make sockets reusable
@ -55,16 +55,19 @@ int srsran_netsource_init(srsran_netsource_t* q, const char* address, uint16_t p
q->type = type;
q->servaddr.sin_family = AF_INET;
q->servaddr.sin_addr.s_addr = inet_addr(address);
if (inet_pton(q->servaddr.sin_family, address, &q->servaddr.sin_addr) != 1) {
perror("inet_pton");
return SRSRAN_ERROR;
}
q->servaddr.sin_port = htons(port);
if (bind(q->sockfd, (struct sockaddr*)&q->servaddr, sizeof(struct sockaddr_in))) {
perror("bind");
return -1;
return SRSRAN_ERROR;
}
q->connfd = 0;
return 0;
return SRSRAN_SUCCESS;
}
void srsran_netsource_free(srsran_netsource_t* q)
@ -82,9 +85,9 @@ int srsran_netsource_read(srsran_netsource_t* q, void* buffer, int nbytes)
if (n == -1) {
if (errno == EAGAIN) {
return 0;
return SRSRAN_SUCCESS;
} else {
return -1;
return SRSRAN_ERROR;
}
} else {
return n;
@ -97,7 +100,7 @@ int srsran_netsource_read(srsran_netsource_t* q, void* buffer, int nbytes)
q->connfd = accept(q->sockfd, (struct sockaddr*)&q->cliaddr, &clilen);
if (q->connfd < 0) {
perror("accept");
return -1;
return SRSRAN_ERROR;
}
}
int n = read(q->connfd, buffer, nbytes);
@ -105,7 +108,7 @@ int srsran_netsource_read(srsran_netsource_t* q, void* buffer, int nbytes)
printf("Connection closed\n");
close(q->connfd);
q->connfd = 0;
return 0;
return SRSRAN_SUCCESS;
}
if (n == -1) {
perror("read");
@ -136,7 +139,7 @@ int srsran_netsource_set_nonblocking(srsran_netsource_t* q)
perror("fcntl");
return -1;
}
return 0;
return SRSRAN_SUCCESS;
}
int srsran_netsource_set_timeout(srsran_netsource_t* q, uint32_t microseconds)
@ -146,7 +149,7 @@ int srsran_netsource_set_timeout(srsran_netsource_t* q, uint32_t microseconds)
t.tv_usec = microseconds;
if (setsockopt(q->sockfd, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(struct timeval))) {
perror("setsockopt");
return -1;
return SRSRAN_ERROR;
}
return 0;
return SRSRAN_SUCCESS;
}

@ -186,7 +186,7 @@ int srsran_ra_dl_nr_time(const srsran_sch_hl_cfg_nr_t* cfg,
srsran_ra_dl_nr_time_default_A(m, cfg->typeA_pos, grant);
}
} else {
ERROR("Unhandled case %s, ss_type=%d", srsran_rnti_type_str(rnti_type), ss_type);
ERROR("Unhandled case %s, ss_type=%s", srsran_rnti_type_str(rnti_type), srsran_ss_type_str(ss_type));
}
// Validate S and L parameters
@ -349,4 +349,3 @@ uint32_t srsran_ra_nr_type1_riv(uint32_t N_prb, uint32_t start_rb, uint32_t leng
{
return srsran_sliv_from_s_and_l(N_prb, start_rb, length_rb);
}

@ -706,7 +706,7 @@ ssb_measure(srsran_ssb_t* q, const cf_t ssb_grid[SRSRAN_SSB_NOF_RE], uint32_t N_
// Compute CFO in Hz
float distance_s = srsran_symbol_distance_s(SRSRAN_PSS_NR_SYMBOL_IDX, SRSRAN_SSS_NR_SYMBOL_IDX, q->cfg.scs);
float cfo_hz_max = 1.0f / distance_s;
float cfo_hz = cargf(corr_pss * conjf(corr_sss)) / (2.0f * M_PI) * cfo_hz_max;
float cfo_hz = cargf(corr_sss * conjf(corr_pss)) / (2.0f * M_PI) * cfo_hz_max;
// Compute average RSRP
float rsrp_pss = SRSRAN_CSQABS(corr_pss);

@ -80,7 +80,7 @@ static void run_channel()
}
// CFO
srsran_vec_apply_cfo(buffer, -cfo_hz / srate_hz, buffer, sf_len);
srsran_vec_apply_cfo(buffer, cfo_hz / srate_hz, buffer, sf_len);
// AWGN
srsran_channel_awgn_run_c(&awgn, buffer, buffer, sf_len);

@ -123,11 +123,12 @@ static int work_ue_dl(srsran_ue_dl_nr_t* ue_dl, srsran_slot_cfg_t* slot)
// Print PDCCH blind search candidates
for (uint32_t i = 0; i < ue_dl->pdcch_info_count; i++) {
const srsran_ue_dl_nr_pdcch_info_t* info = &ue_dl->pdcch_info[i];
INFO("PDCCH: rnti=0x%x, crst_id=%d, ss_type=%d, ncce=%d, al=%d, EPRE=%+.2f, RSRP=%+.2f, corr=%.3f; "
INFO("PDCCH: %s-rnti=0x%x, crst_id=%d, ss_type=%s, ncce=%d, al=%d, EPRE=%+.2f, RSRP=%+.2f, corr=%.3f; "
"nof_bits=%d; crc=%s;",
srsran_rnti_type_str_short(info->dci_ctx.rnti_type),
info->dci_ctx.rnti,
info->dci_ctx.coreset_id,
info->dci_ctx.ss_type,
srsran_ss_type_str(info->dci_ctx.ss_type),
info->dci_ctx.location.ncce,
info->dci_ctx.location.L,
info->measure.epre_dBfs,

@ -937,31 +937,44 @@ int srsran_ue_sync_run_find_gnss_mode(srsran_ue_sync_t* q,
INFO("Calibration samples received start at %ld + %f", q->last_timestamp.full_secs, q->last_timestamp.frac_secs);
// round to nearest second
srsran_timestamp_t ts_next_rx;
srsran_timestamp_t ts_next_rx, ts_next_rx_tmp, ts_tmp;
srsran_timestamp_copy(&ts_next_rx, &q->last_timestamp);
ts_next_rx.full_secs++;
ts_next_rx.frac_secs = 0.0;
INFO("Next desired recv at %ld + %f", ts_next_rx.full_secs, ts_next_rx.frac_secs);
srsran_timestamp_copy(&ts_next_rx_tmp, &ts_next_rx);
INFO("Next desired recv at %ld + %f\n", ts_next_rx_tmp.full_secs, ts_next_rx_tmp.frac_secs);
// get difference in time between second rx and now
srsran_timestamp_sub(&ts_next_rx, q->last_timestamp.full_secs, q->last_timestamp.frac_secs);
srsran_timestamp_sub(&ts_next_rx, 0, 0.001); ///< account for samples that have already been rx'ed
srsran_timestamp_sub(&ts_next_rx_tmp, q->last_timestamp.full_secs, q->last_timestamp.frac_secs);
srsran_timestamp_sub(&ts_next_rx_tmp, 0, 0.001); ///< account for samples that have already been rx'ed
uint64_t align_len = srsran_timestamp_uint64(&ts_next_rx, q->sf_len * 1000);
uint64_t align_len = srsran_timestamp_uint64(&ts_next_rx_tmp, q->sf_len * 1000);
DEBUG("Difference between first recv is %ld + %f, realigning %" PRIu64 " samples",
ts_next_rx.full_secs,
ts_next_rx.frac_secs,
DEBUG("Difference between first recv is %ld + %f, realigning %" PRIu64 " samples\n",
ts_next_rx_tmp.full_secs,
ts_next_rx_tmp.frac_secs,
align_len);
// receive align_len samples into dummy_buffer, make sure to not exceed buffer len
uint32_t sample_count = 0;
while (sample_count < align_len) {
uint32_t actual_rx_len = SRSRAN_MIN(align_len, DUMMY_BUFFER_NUM_SAMPLES);
actual_rx_len = SRSRAN_MIN(align_len - sample_count, actual_rx_len);
while (align_len > q->sf_len) {
uint32_t actual_rx_len = SRSRAN_MIN(align_len, q->sf_len);
q->recv_callback(q->stream, dummy_offset_buffer, actual_rx_len, &q->last_timestamp);
sample_count += actual_rx_len;
srsran_timestamp_copy(&ts_tmp, &ts_next_rx);
srsran_timestamp_sub(&ts_tmp, q->last_timestamp.full_secs, q->last_timestamp.frac_secs);
srsran_timestamp_sub(&ts_tmp, 0, 0.001); ///< account for samples that have already been rx'ed
align_len = srsran_timestamp_uint64(&ts_tmp, q->sf_len * 1000);
if (align_len > q->sf_len * 1000) {
ts_next_rx.full_secs++;
ts_next_rx.frac_secs = 0.0;
srsran_timestamp_copy(&ts_tmp, &ts_next_rx);
srsran_timestamp_sub(&ts_tmp, q->last_timestamp.full_secs, q->last_timestamp.frac_secs);
srsran_timestamp_sub(&ts_tmp, 0, 0.001); ///< account for samples that have already been rx'ed
align_len = srsran_timestamp_uint64(&ts_tmp, q->sf_len * 1000);
}
}
DEBUG("Received %d samples during alignment", sample_count);
@ -1026,39 +1039,22 @@ int srsran_ue_sync_set_tti_from_timestamp(srsran_ue_sync_t* q, srsran_timestamp_
time_t t_cur = rx_timestamp->full_secs;
DEBUG("t_cur=%ld", t_cur);
// time_t of reference UTC time on 1. Jan 1900 at 0:00
// If we put this date in https://www.epochconverter.com it returns a negative number
time_t t_ref = {0};
#if 0
struct tm t = {0};
t.tm_year = 1900; // year-1900
t.tm_mday = 1; // first of January
// t.tm_isdst = 0; // Is DST on? 1 = yes, 0 = no, -1 = unknown
t_ref = mktime(&t);
#endif
DEBUG("t_ref=%ld", t_ref);
// 3GPP Reference UTC time is 1. Jan 1900 at 0:00
// If we put this date in https://www.epochconverter.com it returns a negative number (-2208988800)
// as epoch time starts at 1. Jan 1970 at 0:00
uint64_t epoch_offset_3gpp = 2208988800;
static const uint32_t MSECS_PER_SEC = 1000;
DEBUG("diff=%f", difftime(t_cur, t_ref));
double time_diff_secs = difftime(t_cur, t_ref);
if (time_diff_secs < 0) {
fprintf(stderr, "Time diff between Rx timestamp and reference UTC is negative. Is the timestamp correct?\n");
return SRSRAN_ERROR;
}
DEBUG("time diff in s %f", time_diff_secs);
uint64_t time_3gpp_secs = t_cur + epoch_offset_3gpp;
// convert to ms and add fractional part
double time_diff_msecs = time_diff_secs * MSECS_PER_SEC + rx_timestamp->frac_secs;
DEBUG("time diff in ms %f", time_diff_msecs);
uint64_t time_3gpp_msecs = (time_3gpp_secs + rx_timestamp->frac_secs) * MSECS_PER_SEC;
DEBUG("rx time with 3gpp base in ms %lu\n", time_3gpp_msecs);
// calculate SFN and SF index according to TS 36.331 Sec. 5.10.14
q->frame_number = ((uint32_t)floor(0.1 * (time_diff_msecs - q->sfn_offset))) % 1024;
q->sf_idx = ((uint32_t)floor(time_diff_msecs - q->sfn_offset)) % 10;
q->frame_number = (uint32_t)(((uint64_t)floor(0.1 * (time_3gpp_msecs - q->sfn_offset))) % 1024);
q->sf_idx = (uint32_t)(((uint64_t)floor(time_3gpp_msecs - q->sfn_offset)) % 10);
return SRSRAN_SUCCESS;
}

@ -110,7 +110,7 @@ void srsran_ue_ul_nr_set_freq_offset(srsran_ue_ul_nr_t* q, float freq_offset_hz)
return;
}
q->freq_offset_hz = freq_offset_hz;
q->freq_offset_hz = -freq_offset_hz;
}
int srsran_ue_ul_nr_encode_pusch(srsran_ue_ul_nr_t* q,

@ -212,13 +212,19 @@ uint32_t rlc_am_lte::get_bearer()
rlc_bearer_metrics_t rlc_am_lte::get_metrics()
{
// update values that aren't calculated on the fly
metrics.rx_latency_ms = rx.get_sdu_rx_latency_ms();
metrics.rx_buffered_bytes = rx.get_rx_buffered_bytes();
uint32_t latency = rx.get_sdu_rx_latency_ms();
uint32_t buffered_bytes = rx.get_rx_buffered_bytes();
std::lock_guard<std::mutex> lock(metrics_mutex);
metrics.rx_latency_ms = latency;
metrics.rx_buffered_bytes = buffered_bytes;
return metrics;
}
void rlc_am_lte::reset_metrics()
{
std::lock_guard<std::mutex> lock(metrics_mutex);
metrics = {};
}
@ -229,6 +235,7 @@ void rlc_am_lte::reset_metrics()
void rlc_am_lte::write_sdu(unique_byte_buffer_t sdu)
{
if (tx.write_sdu(std::move(sdu)) == SRSRAN_SUCCESS) {
std::lock_guard<std::mutex> lock(metrics_mutex);
metrics.num_tx_sdus++;
}
}
@ -236,6 +243,8 @@ void rlc_am_lte::write_sdu(unique_byte_buffer_t sdu)
void rlc_am_lte::discard_sdu(uint32_t discard_sn)
{
tx.discard_sdu(discard_sn);
std::lock_guard<std::mutex> lock(metrics_mutex);
metrics.num_lost_sdus++;
}
@ -261,14 +270,19 @@ uint32_t rlc_am_lte::get_buffer_state()
uint32_t rlc_am_lte::read_pdu(uint8_t* payload, uint32_t nof_bytes)
{
uint32_t read_bytes = tx.read_pdu(payload, nof_bytes);
std::lock_guard<std::mutex> lock(metrics_mutex);
metrics.num_tx_pdus++;
metrics.num_tx_pdu_bytes += read_bytes;
return read_bytes;
}
void rlc_am_lte::write_pdu(uint8_t* payload, uint32_t nof_bytes)
{
rx.write_pdu(payload, nof_bytes);
std::lock_guard<std::mutex> lock(metrics_mutex);
metrics.num_rx_pdus++;
metrics.num_rx_pdu_bytes += nof_bytes;
}
@ -416,6 +430,8 @@ void rlc_am_lte::rlc_am_lte_tx::check_sn_reached_max_retx(uint32_t sn)
pdcp_sns.push_back(segment.pdcp_sn());
}
parent->pdcp->notify_failure(parent->lcid, pdcp_sns);
std::lock_guard<std::mutex> lock(parent->metrics_mutex);
parent->metrics.num_lost_pdus++;
}
}
@ -1767,7 +1783,10 @@ void rlc_am_lte::rlc_am_lte_rx::reassemble_rx_sdus()
std::chrono::high_resolution_clock::now() - rx_sdu->get_timestamp())
.count());
parent->pdcp->write_pdu(parent->lcid, std::move(rx_sdu));
{
std::lock_guard<std::mutex> lock(parent->metrics_mutex);
parent->metrics.num_rx_sdus++;
}
rx_sdu = srsran::make_byte_buffer();
if (rx_sdu == nullptr) {
@ -1817,7 +1836,10 @@ void rlc_am_lte::rlc_am_lte_rx::reassemble_rx_sdus()
std::chrono::high_resolution_clock::now() - rx_sdu->get_timestamp())
.count());
parent->pdcp->write_pdu(parent->lcid, std::move(rx_sdu));
{
std::lock_guard<std::mutex> lock(parent->metrics_mutex);
parent->metrics.num_rx_sdus++;
}
rx_sdu = srsran::make_byte_buffer();
if (rx_sdu == NULL) {

@ -97,15 +97,15 @@ int make_phy_tdd_cfg_test()
tdd_ul_dl_cfg_common.pattern1.nrof_ul_slots = 2;
tdd_ul_dl_cfg_common.pattern1.nrof_ul_symbols = 4;
srsran_tdd_config_nr_t srsran_tdd_config_nr;
TESTASSERT(make_phy_tdd_cfg(tdd_ul_dl_cfg_common, &srsran_tdd_config_nr) == true);
TESTASSERT(srsran_tdd_config_nr.pattern1.period_ms == 10);
TESTASSERT(srsran_tdd_config_nr.pattern1.nof_dl_slots == 7);
TESTASSERT(srsran_tdd_config_nr.pattern1.nof_dl_symbols == 6);
TESTASSERT(srsran_tdd_config_nr.pattern1.nof_ul_slots == 2);
TESTASSERT(srsran_tdd_config_nr.pattern1.nof_ul_symbols == 4);
TESTASSERT(srsran_tdd_config_nr.pattern2.period_ms == 0);
srsran_duplex_config_nr_t srsran_duplex_config_nr;
TESTASSERT(make_phy_tdd_cfg(tdd_ul_dl_cfg_common, &srsran_duplex_config_nr) == true);
TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.period_ms == 10);
TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.nof_dl_slots == 7);
TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.nof_dl_symbols == 6);
TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.nof_ul_slots == 2);
TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.nof_ul_symbols == 4);
TESTASSERT(srsran_duplex_config_nr.tdd.pattern2.period_ms == 0);
return SRSRAN_SUCCESS;
}

@ -294,7 +294,7 @@ int test_radio_bearer_config()
return SRSRAN_SUCCESS;
}
int test_cell_group_config()
int test_cell_group_config_tdd()
{
uint8_t cell_group_config_raw[] = "\x5c\x40\xb1\xc0\x33\xc8\x53\xe0\x12\x0f\x05\x38\x0f\x80\x41\x15"
"\x07\xad\x40\x00\xba\x14\xe6\x37\xd1\xa4\xd3\xa0\x01\x34\x9a\x5f"
@ -914,6 +914,615 @@ int test_cell_group_config()
return SRSRAN_SUCCESS;
}
int test_cell_group_config_fdd()
{
uint8_t cell_group_config_raw[] = "\x5c\x40\xb1\xc0\x7d\x48\x3a\x04\xc0\x3e\x01\x04\x54\x1e\xb5\x80"
"\x02\xe8\x53\xb8\x9f\x46\x85\x60\xa4\x00\x40\xab\x41\x00\x00\x00"
"\xcd\x8d\xb2\x44\xa2\x01\xff\x00\x00\x00\x00\x01\x1b\x82\x21\x00"
"\x01\x24\x04\x00\xd0\x14\x6c\x00\x10\x28\x9d\xc0\x00\x00\x33\x71"
"\xb6\x48\x90\x04\x00\x08\x2e\x25\x18\xf0\x02\x4a\x31\x06\xe1\x8d"
"\xb8\x44\x70\x01\x08\x4c\x23\x06\xdd\x40\x01\x01\xc0\x24\xb8\x19"
"\x50\x00\x2f\xf0\x00\x00\x00\x00\x10\x6e\x11\x04\x00\x01\x10\x24"
"\xa0\x04\x19\x04\x00\x00\x40\xd3\x02\x02\x8a\x14\x00\x1c\x90\x30"
"\x00\x02\x66\xaa\xc9\x08\x38\x00\x20\x81\x84\x0a\x18\x39\x38\x81"
"\x22\x85\x8c\x1a\x38\x79\x10\x00\x00\x85\x00\x00\x80\x0a\x50\x00"
"\x10\x00\xc5\x00\x01\x80\x08\x50\x10\x20\x00\xa5\x01\x02\x80\x0c"
"\x50\x10\x30\x00\x85\x02\x03\x80\x0a\x50\x20\x40\xcd\x04\x01\x23"
"\x34\x12\x05\x0c\xd0\x50\x16\x33\x41\x60\x60\xcd\x06\x01\xa3\x34"
"\x1a\x07\x0c\xd0\x70\x1e\x01\x41\x00\x80\x00\xc5\x02\x08\x80\x50"
"\x4a\x04\x84\x30\x28\x42\x01\x22\x80\x14\x92\x1e\x2e\xe0\x0c\x10"
"\xe0\x00\x00\x01\xff\xd2\x94\x98\xc6\x37\x28\x16\x00\x00\x21\x97"
"\x00\x00\x00\x00\x00\x00\x06\x2f\x00\xfa\x08\x48\xad\x54\x50\x04"
"\x70\x01\x80\x00\x82\x00\x0e\x21\x7d\x24\x08\x07\x01\x01\x08\x40"
"\x00\xe2\x17\xd1\xcb\x00\xe0\x40\x22\x08\x00\x1c\x42\xfa\x39\x60"
"\x1c\x0c\x04\x21\x00\x03\x88\x5f\x47\x30\x03\x82\x00\x88\x20\x00"
"\x71\x0b\xe8\xe6\x00\x04\x00\x00\x00\x41\x0c\x04\x08\x0c\x10\x0e"
"\x0d\x00\x00\xe4\x81\x00\x00\x00\x20\x04\x00\x08\x06\x00\x08\x09"
"\x00\x22\x00\xa4\x00\x00\x23\x85\x01\x13\x1c";
asn1::SRSASN_CODE err;
cbit_ref bref(&cell_group_config_raw[0], sizeof(cell_group_config_raw));
cell_group_cfg_s cell_group_cfg;
TESTASSERT(cell_group_cfg.unpack(bref) == SRSASN_SUCCESS);
TESTASSERT(test_pack_unpack_consistency(cell_group_cfg) == SRSASN_SUCCESS);
TESTASSERT(cell_group_cfg.sp_cell_cfg_present == true);
TESTASSERT(cell_group_cfg.sp_cell_cfg.serv_cell_idx_present == true);
TESTASSERT(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded_present == true);
TESTASSERT(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp_present == true);
TESTASSERT(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded.first_active_dl_bwp_id_present == true);
TESTASSERT(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg_present == true);
TESTASSERT(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded.pdcch_serving_cell_cfg_present == true);
TESTASSERT(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded.pdsch_serving_cell_cfg_present == true);
TESTASSERT(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg_present == true);
TESTASSERT(cell_group_cfg.sp_cell_cfg.recfg_with_sync_present == true);
TESTASSERT(cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common_present == true);
TESTASSERT(cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.pci_present == true);
TESTASSERT(cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.pci == 500);
TESTASSERT(cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common_present == true);
TESTASSERT(cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common_present == true);
TESTASSERT(cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp_present == true);
TESTASSERT(
cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common_present ==
true);
TESTASSERT(
cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common.type() ==
asn1::rrc_nr::setup_release_c<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()
{
auto& asn1_logger = srslog::fetch_basic_logger("ASN1", false);
@ -935,7 +1544,8 @@ int main()
TESTASSERT(test_ue_mrdc_capabilities() == SRSRAN_SUCCESS);
TESTASSERT(test_ue_rrc_reconfiguration() == SRSRAN_SUCCESS);
TESTASSERT(test_radio_bearer_config() == SRSRAN_SUCCESS);
TESTASSERT(test_cell_group_config() == SRSRAN_SUCCESS);
TESTASSERT(test_cell_group_config_tdd() == SRSRAN_SUCCESS);
TESTASSERT(test_cell_group_config_fdd() == SRSRAN_SUCCESS);
srslog::flush();

@ -171,6 +171,10 @@ enable = false
# pusch_max_mcs: Optional PUSCH MCS limit
# min_nof_ctrl_symbols: Minimum number of control symbols
# max_nof_ctrl_symbols: Maximum number of control symbols
# pucch_multiplex_enable: Allow PUCCH HARQ to collide with PUSCH and other PUCCH
# pucch_harq_max_rb: Maximum number of RB to be used for PUCCH on the edges of the grid.
# If defined and greater than 0, the scheduler will avoid DL PDCCH allocations if
# PUCCH HARQ falls outside this region
# target_bler: Target BLER (in decimal) to achieve via adaptive link
# max_delta_dl_cqi: Maximum shift in CQI for adaptive DL link
# max_delta_ul_snr: Maximum shift in UL SNR for adaptive UL link
@ -196,6 +200,7 @@ enable = false
#min_nof_ctrl_symbols = 1
#max_nof_ctrl_symbols = 3
#pucch_multiplex_enable = false
#pucch_harq_max_rb = 0
#target_bler = 0.05
#max_delta_dl_cqi = 5
#max_delta_ul_snr = 5

@ -33,12 +33,14 @@
#include <string>
#include "phy/phy.h"
#include "x2_adapter.h"
#include "srsran/radio/radio.h"
#include "srsenb/hdr/phy/enb_phy_base.h"
#include "srsenb/hdr/stack/enb_stack_base.h"
#include "srsenb/hdr/stack/rrc/rrc_config.h"
#include "srsenb/hdr/stack/rrc/rrc_config_nr.h"
#include "srsenb/hdr/stack/mac/sched_interface.h"
#include "srsran/common/bcd_helpers.h"
@ -48,6 +50,7 @@
#include "srsran/common/security.h"
#include "srsran/interfaces/enb_command_interface.h"
#include "srsran/interfaces/enb_metrics_interface.h"
#include "srsran/interfaces/enb_time_interface.h"
#include "srsran/interfaces/ue_interfaces.h"
#include "srsran/srslog/srslog.h"
#include "srsran/system/sys_metrics_processor.h"
@ -126,7 +129,7 @@ struct rrc_cfg_t;
Main eNB class
*******************************************************************************/
class enb : public enb_metrics_interface, enb_command_interface
class enb : public enb_metrics_interface, enb_command_interface, enb_time_interface
{
public:
enb(srslog::sink& log_sink);
@ -149,6 +152,8 @@ public:
void toggle_padding() override;
void tti_clock() override;
private:
const static int ENB_POOL_SIZE = 1024 * 10;
@ -162,9 +167,12 @@ private:
phy_cfg_t phy_cfg = {};
rrc_cfg_t rrc_cfg = {};
rrc_nr_cfg_t rrc_nr_cfg = {};
// 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<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_ul_sched(uint32_t tti, ul_sched_list_t& ul_sched_res) override { return 0; }
void set_sched_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs) override {}
void tti_clock() override {}
};
srsran::phy_common_interface& common;

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

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

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

@ -28,9 +28,7 @@
#define SRSRAN_ENB_STACK_LTE_H
#include "mac/mac.h"
#include "mac/nr/mac_nr.h"
#include "rrc/rrc.h"
#include "rrc/rrc_nr.h"
#include "s1ap/s1ap.h"
#include "srsran/common/task_scheduler.h"
#include "upper/gtpu.h"
@ -49,7 +47,7 @@ class gtpu_pdcp_adapter;
class enb_stack_lte final : public enb_stack_base,
public stack_interface_phy_lte,
public stack_interface_phy_nr,
public rrc_eutra_interface_rrc_nr,
public srsran::thread
{
public:
@ -57,12 +55,7 @@ public:
~enb_stack_lte() final;
// eNB stack base interface
int init(const stack_args_t& args_,
const rrc_cfg_t& rrc_cfg_,
phy_interface_stack_lte* phy_,
phy_interface_stack_nr* phy_nr_);
int init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_, phy_interface_stack_lte* phy_);
int init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_);
int init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_, phy_interface_stack_lte* phy_, x2_interface* x2_);
void stop() final;
std::string get_type() final;
bool get_metrics(stack_metrics_t* metrics) final;
@ -124,25 +117,16 @@ public:
void toggle_padding() override { mac.toggle_padding(); }
void tti_clock() override;
// mac_interface_phy_nr
int slot_indication(const srsran_slot_cfg_t& slot_cfg) override { return mac_nr.slot_indication(slot_cfg); }
int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, srsenb::mac_interface_phy_nr::dl_sched_t& dl_sched) override
// rrc_eutra_interface_rrc_nr
void sgnb_addition_ack(uint16_t eutra_rnti, sgnb_addition_ack_params_t params) final
{
return mac_nr.get_dl_sched(slot_cfg, dl_sched);
rrc.sgnb_addition_ack(eutra_rnti, params);
}
int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, srsenb::mac_interface_phy_nr::ul_sched_t& ul_sched) override
void sgnb_addition_reject(uint16_t eutra_rnti) final { rrc.sgnb_addition_reject(eutra_rnti); }
void sgnb_addition_complete(uint16_t eutra_rnti, uint16_t nr_rnti) final
{
return mac_nr.get_ul_sched(slot_cfg, ul_sched);
rrc.sgnb_addition_complete(eutra_rnti, nr_rnti);
}
int pucch_info(const srsran_slot_cfg_t& slot_cfg, const pucch_info_t& pucch_info) override
{
return mac_nr.pucch_info(slot_cfg, pucch_info);
}
int pusch_info(const srsran_slot_cfg_t& slot_cfg, pusch_info_t& pusch_info) override
{
return mac_nr.pusch_info(slot_cfg, pusch_info);
}
void rach_detected(const rach_info_t& rach_info) override { mac_nr.rach_detected(rach_info); }
private:
static const int STACK_MAIN_THREAD_PRIO = 4;
@ -164,10 +148,6 @@ private:
srslog::basic_logger& s1ap_logger;
srslog::basic_logger& gtpu_logger;
srslog::basic_logger& stack_logger;
srslog::basic_logger& rrc_nr_logger;
srslog::basic_logger& mac_nr_logger;
srslog::basic_logger& rlc_nr_logger;
srslog::basic_logger& pdcp_nr_logger;
// PCAP and trace option
srsran::mac_pcap mac_pcap;
@ -189,15 +169,8 @@ private:
srsenb::gtpu gtpu;
srsenb::s1ap s1ap;
// NR components for NSA mode
srsenb::mac_nr mac_nr;
srsenb::rlc rlc_nr;
srsenb::pdcp pdcp_nr;
srsenb::rrc_nr rrc_nr;
// RAT-specific interfaces
phy_interface_stack_lte* phy = nullptr;
phy_interface_stack_nr* phy_nr = nullptr;
// state
std::atomic<bool> started{false};

@ -27,16 +27,15 @@
#ifndef SRSRAN_GNB_STACK_NR_H
#define SRSRAN_GNB_STACK_NR_H
#include "s1ap/s1ap.h"
#include "srsenb/hdr/stack/mac/nr/mac_nr.h"
#include "srsenb/hdr/stack/rrc/rrc_nr.h"
#include "srsenb/hdr/stack/upper/pdcp_nr.h"
#include "srsenb/hdr/stack/upper/rlc_nr.h"
#include "upper/gtpu.h"
#include "upper/pdcp.h"
#include "upper/rlc.h"
#include "upper/sdap.h"
#include "enb_stack_base.h"
#include "srsenb/hdr/enb.h"
#include "srsran/interfaces/gnb_interfaces.h"
// This is needed for GW
@ -49,14 +48,18 @@ class gnb_stack_nr final : public srsenb::enb_stack_base,
public stack_interface_phy_nr,
public stack_interface_mac,
public srsue::stack_interface_gw,
public rrc_nr_interface_rrc,
public pdcp_interface_gtpu, // for user-plane over X2
public srsran::thread
{
public:
explicit gnb_stack_nr();
explicit gnb_stack_nr(srslog::sink& log_sink);
~gnb_stack_nr() final;
int init(const srsenb::stack_args_t& args_, const rrc_nr_cfg_t& rrc_cfg_, phy_interface_stack_nr* phy_);
int init(const srsenb::stack_args_t& args_, const rrc_nr_cfg_t& rrc_cfg_);
int init(const srsenb::stack_args_t& args_,
const rrc_nr_cfg_t& rrc_cfg_,
phy_interface_stack_nr* phy_,
x2_interface* x2_);
// eNB stack base interface
void stop() final;
@ -71,12 +74,12 @@ public:
void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) override;
bool has_active_radio_bearer(uint32_t eps_bearer_id) override;
bool switch_on();
void run_tti(uint32_t tti);
void tti_clock() override;
// MAC interface to trigger processing of received PDUs
void process_pdus() final;
void toggle_padding() override { srsran::console("padding not available for NR\n"); }
void toggle_padding() override {}
int slot_indication(const srsran_slot_cfg_t& slot_cfg) override;
int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) override;
@ -85,15 +88,40 @@ public:
int pusch_info(const srsran_slot_cfg_t& slot_cfg, pusch_info_t& pusch_info) override;
void rach_detected(const rach_info_t& rach_info) override;
// X2 interface
// control plane, i.e. rrc_nr_interface_rrc
int sgnb_addition_request(uint16_t eutra_rnti, const sgnb_addition_req_params_t& params) final
{
return rrc.sgnb_addition_request(eutra_rnti, params);
};
int sgnb_reconfiguration_complete(uint16_t eutra_rnti, asn1::dyn_octstring reconfig_response) final
{
return rrc.sgnb_reconfiguration_complete(eutra_rnti, reconfig_response);
};
// X2 data interface
void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu, int pdcp_sn = -1) final
{
pdcp.write_sdu(rnti, lcid, std::move(sdu), pdcp_sn);
}
std::map<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:
void run_thread() final;
void run_tti_impl(uint32_t tti);
void tti_clock_impl();
// args
srsenb::stack_args_t args = {};
phy_interface_stack_nr* phy = nullptr;
srslog::basic_logger& rrc_logger;
srslog::basic_logger& mac_logger;
srslog::basic_logger& rlc_logger;
srslog::basic_logger& pdcp_logger;
srslog::basic_logger& stack_logger;
// task scheduling
static const int STACK_MAIN_THREAD_PRIO = 4;
@ -101,18 +129,14 @@ private:
srsran::task_multiqueue::queue_handle sync_task_queue, ue_task_queue, gw_task_queue, mac_task_queue;
// derived
std::unique_ptr<mac_nr> m_mac;
std::unique_ptr<rlc_nr> m_rlc;
std::unique_ptr<pdcp_nr> m_pdcp;
std::unique_ptr<sdap> m_sdap;
std::unique_ptr<rrc_nr> m_rrc;
std::unique_ptr<srsue::gw> m_gw;
// std::unique_ptr<ngap> m_ngap;
// std::unique_ptr<srsenb::gtpu> m_gtpu;
srsenb::mac_nr mac;
srsenb::rlc rlc;
srsenb::pdcp pdcp;
srsenb::rrc_nr rrc;
// std::unique_ptr<sdap> m_sdap;
// state
bool running = false;
uint32_t current_tti = 10240;
std::atomic<bool> running = {false};
};
} // namespace srsenb

@ -69,7 +69,7 @@ public:
struct cell_cfg_t {
srsran_carrier_nr_t carrier = {};
srsran_tdd_config_nr_t tdd = {};
srsran_duplex_config_nr_t duplex = {};
srsran::phy_cfg_nr_t::ssb_cfg_t ssb = {};
srsran::bounded_vector<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;
bool adaptive_aggr_level = false;
bool pucch_mux_enabled = false;
int pucch_harq_max_rb = 0;
float target_bler = 0.05;
float max_delta_dl_cqi = 5;
float max_delta_ul_snr = 5;

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

@ -201,7 +201,7 @@ private:
srsran::mac_pcap_net* pcap_net = nullptr;
uint64_t conres_id = 0;
uint16_t rnti = 0;
uint32_t last_tti = 0;
std::atomic<uint32_t> last_tti{0};
uint32_t nof_failures = 0;
std::atomic<bool> active_state{true};

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

@ -36,6 +36,7 @@
#include "srsran/interfaces/enb_pdcp_interfaces.h"
#include "srsran/interfaces/enb_rlc_interfaces.h"
#include "srsran/interfaces/enb_rrc_interfaces.h"
#include "srsran/interfaces/enb_x2_interfaces.h"
#include "srsran/interfaces/gnb_interfaces.h"
#include "srsran/interfaces/gnb_mac_interfaces.h"
#include "srsran/interfaces/gnb_ngap_interfaces.h"
@ -126,7 +127,9 @@ public:
uint16_t rnti = SRSRAN_INVALID_RNTI;
int pack_rrc_reconfiguraiton(asn1::dyn_octstring& packed_rrc_reconfig);
int pack_secondary_cell_group_config(asn1::dyn_octstring& packed_secondary_cell_config);
int pack_secondary_cell_group_config_common(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack);
int pack_secondary_cell_group_config_fdd(asn1::dyn_octstring& packed_secondary_cell_config);
int pack_secondary_cell_group_config_tdd(asn1::dyn_octstring& packed_secondary_cell_config);
int pack_nr_radio_bearer_config(asn1::dyn_octstring& packed_nr_bearer_config);
int add_drb();

@ -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,10 +12,10 @@
// t_reordering = 35;
// t_status_prohibit = 0;
// };
// };
// enb_specific = {
// dl_max_retx_thresh = 32;
// };
// };
// }
// srb2_config = {
@ -30,10 +30,10 @@
// t_reordering = 35;
// t_status_prohibit = 0;
// };
// };
// enb_specific = {
// dl_max_retx_thresh = 32;
// };
// };
// }
qci_config = (

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

@ -756,7 +756,9 @@ int parse_rr(all_args_t* args_, rrc_cfg_t* rrc_cfg_)
cell_cnfg.add_field(new rr_sections::cell_list_section(args_, rrc_cfg_));
// NR RRC and cell config section
bool nr_cell_cnfg_present = false;
parser::section nr_cell_cnfg("nr_cell_list");
nr_cell_cnfg.set_optional(&nr_cell_cnfg_present);
nr_cell_cnfg.add_field(new rr_sections::nr_cell_list_section(args_, rrc_cfg_));
// Run parser with two sections
@ -1203,12 +1205,9 @@ int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_
// auto-detect UL frequency
if (cfg.ul_earfcn == 0) {
// derive UL ARFCN from given DL ARFCN
uint16_t nr_band = band_helper.get_band_from_dl_freq_Hz(phy_cell_cfg.dl_freq_hz);
srsran_duplex_mode_t nr_duplex = band_helper.get_duplex_mode(nr_band);
if (nr_duplex == SRSRAN_DUPLEX_MODE_TDD) {
cfg.ul_earfcn = cfg.dl_earfcn;
} else {
ERROR("Can't derive UL ARFCN from DL ARFCN");
cfg.ul_earfcn = band_helper.get_ul_arfcn_from_dl_arfcn(cfg.dl_earfcn);
if (cfg.ul_earfcn == 0) {
ERROR("Can't derive UL ARFCN from DL ARFCN %d", cfg.dl_earfcn);
return SRSRAN_ERROR;
}
}

@ -75,8 +75,6 @@ void parse_args(all_args_t* args, int argc, char* argv[])
// Command line or config file options
bpo::options_description common("Configuration options");
common.add_options()
("enb.stack", bpo::value<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.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")
@ -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.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_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.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")

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

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

@ -22,8 +22,8 @@
#include "srsenb/hdr/stack/enb_stack_lte.h"
#include "srsenb/hdr/common/rnti_pool.h"
#include "srsenb/hdr/enb.h"
#include "srsenb/hdr/stack/rrc/rrc_config_nr.h"
#include "srsran/interfaces/enb_metrics_interface.h"
#include "srsran/interfaces/enb_x2_interfaces.h"
#include "srsran/rlc/bearer_mem_pool.h"
#include "srsran/srslog/event_trace.h"
@ -36,10 +36,10 @@ class gtpu_pdcp_adapter final : public gtpu_interface_pdcp, public pdcp_interfac
public:
gtpu_pdcp_adapter(srslog::basic_logger& logger_,
pdcp* pdcp_lte,
pdcp* pdcp_nr,
pdcp_interface_gtpu* pdcp_x2,
gtpu* gtpu_,
enb_bearer_manager& bearers_) :
logger(logger_), pdcp_obj(pdcp_lte), pdcp_nr_obj(pdcp_nr), gtpu_obj(gtpu_), bearers(&bearers_)
logger(logger_), pdcp_obj(pdcp_lte), pdcp_x2_obj(pdcp_x2), gtpu_obj(gtpu_), bearers(&bearers_)
{}
/// Converts LCID to EPS-BearerID and sends corresponding PDU to GTPU
@ -59,7 +59,7 @@ public:
if (bearer.rat == srsran_rat_t::lte) {
pdcp_obj->write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn);
} else if (bearer.rat == srsran_rat_t::nr) {
pdcp_nr_obj->write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn);
pdcp_x2_obj->write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn);
} else {
logger.warning("Can't deliver SDU for EPS bearer %d. Dropping it.", eps_bearer_id);
}
@ -71,7 +71,7 @@ public:
if (bearer.rat == srsran_rat_t::lte) {
return pdcp_obj->get_buffered_pdus(rnti, bearer.lcid);
} else if (bearer.rat == srsran_rat_t::nr) {
return pdcp_nr_obj->get_buffered_pdus(rnti, bearer.lcid);
return pdcp_x2_obj->get_buffered_pdus(rnti, bearer.lcid);
}
logger.error("Bearer rnti=0x%x, eps-BearerID=%d not found", rnti, eps_bearer_id);
return {};
@ -81,34 +81,26 @@ private:
srslog::basic_logger& logger;
gtpu* gtpu_obj = nullptr;
pdcp* pdcp_obj = nullptr;
pdcp* pdcp_nr_obj = nullptr;
pdcp_interface_gtpu* pdcp_x2_obj = nullptr;
enb_bearer_manager* bearers = nullptr;
};
enb_stack_lte::enb_stack_lte(srslog::sink& log_sink) :
thread("STACK"),
mac_logger(srslog::fetch_basic_logger("MAC", log_sink)),
mac_nr_logger(srslog::fetch_basic_logger("MAC-NR", log_sink)),
rlc_logger(srslog::fetch_basic_logger("RLC", log_sink, false)),
rlc_nr_logger(srslog::fetch_basic_logger("RLC-NR", log_sink, false)),
pdcp_logger(srslog::fetch_basic_logger("PDCP", log_sink, false)),
pdcp_nr_logger(srslog::fetch_basic_logger("PDCP-NR", log_sink, false)),
rrc_logger(srslog::fetch_basic_logger("RRC", log_sink, false)),
rrc_nr_logger(srslog::fetch_basic_logger("RRC-NR", log_sink, false)),
s1ap_logger(srslog::fetch_basic_logger("S1AP", log_sink, false)),
gtpu_logger(srslog::fetch_basic_logger("GTPU", log_sink, false)),
stack_logger(srslog::fetch_basic_logger("STCK", log_sink, false)),
task_sched(512, 128),
pdcp(&task_sched, pdcp_logger),
pdcp_nr(&task_sched, pdcp_nr_logger),
mac(&task_sched, mac_logger),
mac_nr(&task_sched),
rlc(rlc_logger),
rlc_nr(rlc_nr_logger),
gtpu(&task_sched, gtpu_logger, &rx_sockets),
s1ap(&task_sched, s1ap_logger, &rx_sockets),
rrc(&task_sched, bearers),
rrc_nr(&task_sched),
mac_pcap(),
pending_stack_metrics(64)
{
@ -131,30 +123,11 @@ std::string enb_stack_lte::get_type()
int enb_stack_lte::init(const stack_args_t& args_,
const rrc_cfg_t& rrc_cfg_,
phy_interface_stack_lte* phy_,
phy_interface_stack_nr* phy_nr_)
{
phy_nr = phy_nr_;
if (init(args_, rrc_cfg_, phy_)) {
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_, phy_interface_stack_lte* phy_)
{
phy = phy_;
if (init(args_, rrc_cfg_)) {
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_)
x2_interface* x2_)
{
args = args_;
rrc_cfg = rrc_cfg_;
phy = phy_;
// Init RNTI and bearer memory pools
reserve_rnti_memblocks(args.mac.nof_prealloc_ues);
@ -163,25 +136,17 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_)
// setup logging for each layer
mac_logger.set_level(srslog::str_to_basic_level(args.log.mac_level));
mac_nr_logger.set_level(srslog::str_to_basic_level(args.log.mac_level));
rlc_logger.set_level(srslog::str_to_basic_level(args.log.rlc_level));
rlc_nr_logger.set_level(srslog::str_to_basic_level(args.log.rlc_level));
pdcp_logger.set_level(srslog::str_to_basic_level(args.log.pdcp_level));
pdcp_nr_logger.set_level(srslog::str_to_basic_level(args.log.pdcp_level));
rrc_logger.set_level(srslog::str_to_basic_level(args.log.rrc_level));
rrc_nr_logger.set_level(srslog::str_to_basic_level(args.log.rrc_level));
gtpu_logger.set_level(srslog::str_to_basic_level(args.log.gtpu_level));
s1ap_logger.set_level(srslog::str_to_basic_level(args.log.s1ap_level));
stack_logger.set_level(srslog::str_to_basic_level(args.log.stack_level));
mac_logger.set_hex_dump_max_size(args.log.mac_hex_limit);
mac_nr_logger.set_hex_dump_max_size(args.log.mac_hex_limit);
rlc_logger.set_hex_dump_max_size(args.log.rlc_hex_limit);
rlc_nr_logger.set_hex_dump_max_size(args.log.rlc_hex_limit);
pdcp_logger.set_hex_dump_max_size(args.log.pdcp_hex_limit);
pdcp_nr_logger.set_hex_dump_max_size(args.log.pdcp_hex_limit);
rrc_logger.set_hex_dump_max_size(args.log.rrc_hex_limit);
rrc_nr_logger.set_hex_dump_max_size(args.log.rrc_hex_limit);
gtpu_logger.set_hex_dump_max_size(args.log.gtpu_hex_limit);
s1ap_logger.set_hex_dump_max_size(args.log.s1ap_hex_limit);
stack_logger.set_hex_dump_max_size(args.log.stack_hex_limit);
@ -209,7 +174,7 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_)
sync_task_queue = task_sched.make_task_queue(args.sync_queue_size);
// setup bearer managers
gtpu_adapter.reset(new gtpu_pdcp_adapter(stack_logger, &pdcp, &pdcp_nr, &gtpu, bearers));
gtpu_adapter.reset(new gtpu_pdcp_adapter(stack_logger, &pdcp, x2_, &gtpu, bearers));
// Init all LTE layers
if (!mac.init(args.mac, rrc_cfg.cell_list, phy, &rlc, &rrc)) {
@ -218,7 +183,7 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_)
}
rlc.init(&pdcp, &rrc, &mac, task_sched.get_timer_handler());
pdcp.init(&rlc, &rrc, gtpu_adapter.get());
if (rrc.init(rrc_cfg, phy, &mac, &rlc, &pdcp, &s1ap, &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");
return SRSRAN_ERROR;
}
@ -227,25 +192,6 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_)
return SRSRAN_ERROR;
}
// NR layers
mac_nr_args_t mac_args = {};
mac_args.fixed_dl_mcs = 28;
mac_args.fixed_ul_mcs = 10;
mac_args.pcap = args.mac_pcap;
mac_args.pcap.filename = "/tmp/enb_mac_nr.pcap";
if (mac_nr.init(mac_args, phy_nr, nullptr, &rlc_nr, &rrc_nr) != SRSRAN_SUCCESS) {
stack_logger.error("Couldn't initialize MAC-NR");
return SRSRAN_ERROR;
}
rrc_nr_cfg_t rrc_cfg_nr = {};
if (rrc_nr.init(rrc_cfg_nr, phy_nr, &mac_nr, &rlc_nr, &pdcp_nr, nullptr, nullptr, &rrc) != SRSRAN_SUCCESS) {
stack_logger.error("Couldn't initialize RRC-NR");
return SRSRAN_ERROR;
}
rlc_nr.init(&pdcp_nr, &rrc_nr, &mac_nr, task_sched.get_timer_handler());
pdcp_nr.init(&rlc_nr, &rrc_nr, gtpu_adapter.get());
gtpu_args_t gtpu_args;
gtpu_args.embms_enable = args.embms.enable;
gtpu_args.embms_m1u_multiaddr = args.embms.m1u_multiaddr;

@ -20,21 +20,25 @@
*/
#include "srsenb/hdr/stack/gnb_stack_nr.h"
#include "srsran/common/standard_streams.h"
#include "srsran/srsran.h"
#include <srsran/interfaces/enb_metrics_interface.h>
namespace srsenb {
gnb_stack_nr::gnb_stack_nr() : task_sched{512, 128}, thread("gNB"), rlc_logger(srslog::fetch_basic_logger("RLC-NR"))
gnb_stack_nr::gnb_stack_nr(srslog::sink& log_sink) :
task_sched{512, 128},
thread("gNB"),
mac_logger(srslog::fetch_basic_logger("MAC-NR", log_sink)),
rlc_logger(srslog::fetch_basic_logger("RLC-NR", log_sink, false)),
pdcp_logger(srslog::fetch_basic_logger("PDCP-NR", log_sink, false)),
rrc_logger(srslog::fetch_basic_logger("RRC-NR", log_sink, false)),
stack_logger(srslog::fetch_basic_logger("STCK-NR", log_sink, false)),
mac(&task_sched),
rrc(&task_sched),
pdcp(&task_sched, pdcp_logger),
rlc(rlc_logger)
{
m_mac.reset(new mac_nr(&task_sched));
m_rlc.reset(new rlc_nr("RLC-NR"));
m_pdcp.reset(new pdcp_nr(&task_sched, "PDCP-NR"));
m_rrc.reset(new rrc_nr(&task_sched));
m_sdap.reset(new sdap());
m_gw.reset(new srsue::gw(srslog::fetch_basic_logger("GW")));
// m_gtpu.reset(new srsenb::gtpu());
ue_task_queue = task_sched.make_task_queue();
sync_task_queue = task_sched.make_task_queue();
gw_task_queue = task_sched.make_task_queue();
@ -51,46 +55,48 @@ std::string gnb_stack_nr::get_type()
return "nr";
}
int gnb_stack_nr::init(const srsenb::stack_args_t& args_, const rrc_nr_cfg_t& rrc_cfg_, phy_interface_stack_nr* phy_)
int gnb_stack_nr::init(const srsenb::stack_args_t& args_,
const rrc_nr_cfg_t& rrc_cfg_,
phy_interface_stack_nr* phy_,
x2_interface* x2_)
{
args = args_;
// rrc_cfg = rrc_cfg_;
phy = phy_;
if (init(args_, rrc_cfg_)) {
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
int gnb_stack_nr::init(const srsenb::stack_args_t& args_, const rrc_nr_cfg_t& rrc_cfg_)
{
args = args_;
// setup logging
mac_logger.set_level(srslog::str_to_basic_level(args.log.mac_level));
rlc_logger.set_level(srslog::str_to_basic_level(args.log.rlc_level));
pdcp_logger.set_level(srslog::str_to_basic_level(args.log.pdcp_level));
rrc_logger.set_level(srslog::str_to_basic_level(args.log.rrc_level));
stack_logger.set_level(srslog::str_to_basic_level(args.log.stack_level));
// verify configuration correctness
// gtpu_log.init("GTPU", logger);
// gtpu_log.set_level(args.log.gtpu_level);
// gtpu_log.set_hex_limit(args.log.gtpu_hex_limit);
mac_logger.set_hex_dump_max_size(args.log.mac_hex_limit);
rlc_logger.set_hex_dump_max_size(args.log.rlc_hex_limit);
pdcp_logger.set_hex_dump_max_size(args.log.pdcp_hex_limit);
rrc_logger.set_hex_dump_max_size(args.log.rrc_hex_limit);
stack_logger.set_hex_dump_max_size(args.log.stack_hex_limit);
// Init all layers
mac_nr_args_t mac_args = {};
mac_args.fixed_dl_mcs = 28;
mac_args.fixed_ul_mcs = 10;
mac_args.pcap = args.mac_pcap;
m_mac->init(mac_args, phy, this, nullptr, m_rrc.get());
rlc_logger.set_level(srslog::str_to_basic_level(args.log.rlc_level));
rlc_logger.set_hex_dump_max_size(args.log.rlc_hex_limit);
m_rlc->init(m_pdcp.get(), m_rrc.get(), m_mac.get(), task_sched.get_timer_handler());
pdcp_nr_args_t pdcp_args = {};
pdcp_args.log_level = args.log.pdcp_level;
pdcp_args.log_hex_limit = args.log.pdcp_hex_limit;
m_pdcp->init(pdcp_args, m_rlc.get(), m_rrc.get(), m_sdap.get());
m_rrc->init(rrc_cfg_, phy, m_mac.get(), nullptr, nullptr, nullptr, nullptr, nullptr);
mac_args.pcap.filename = "/tmp/enb_mac_nr.pcap";
if (mac.init(mac_args, phy, nullptr, &rlc, &rrc) != SRSRAN_SUCCESS) {
stack_logger.error("Couldn't initialize MAC-NR");
return SRSRAN_ERROR;
}
m_sdap->init(m_pdcp.get(), nullptr, m_gw.get());
rlc.init(&pdcp, &rrc, &mac, task_sched.get_timer_handler());
pdcp.init(&rlc, &rrc, nullptr);
srsue::gw_args_t gw_args = {};
m_gw->init(gw_args, this);
if (rrc.init(rrc_cfg_, phy, &mac, &rlc, &pdcp, nullptr, nullptr, x2_) != SRSRAN_SUCCESS) {
stack_logger.error("Couldn't initialize RRC");
return SRSRAN_ERROR;
}
// TODO: add NGAP
// TODO: add SDAP, NGAP
// m_gtpu->init(args.s1ap.gtp_bind_addr, args.s1ap.mme_addr,
// args.expert.m1u_multiaddr, args.expert.m1u_if_addr, nullptr, &gtpu_log,
// args.expert.enable_mbsfn);
@ -105,11 +111,9 @@ int gnb_stack_nr::init(const srsenb::stack_args_t& args_, const rrc_nr_cfg_t& rr
void gnb_stack_nr::stop()
{
if (running) {
m_gw->stop();
// m_gtpu->stop();
m_rrc->stop();
m_pdcp->stop();
m_mac->stop();
rrc.stop();
pdcp.stop();
mac.stop();
srsran::get_background_workers().stop();
running = false;
@ -129,13 +133,12 @@ void gnb_stack_nr::run_thread()
}
}
void gnb_stack_nr::run_tti(uint32_t tti)
void gnb_stack_nr::tti_clock()
{
current_tti = tti;
sync_task_queue.push([this, tti]() { run_tti_impl(tti); });
sync_task_queue.push([this]() { tti_clock_impl(); });
}
void gnb_stack_nr::run_tti_impl(uint32_t tti)
void gnb_stack_nr::tti_clock_impl()
{
// m_ngap->run_tti();
task_sched.tic();
@ -153,8 +156,8 @@ void gnb_stack_nr::process_pdus()
bool gnb_stack_nr::get_metrics(srsenb::stack_metrics_t* metrics)
{
m_mac->get_metrics(metrics->mac);
m_rrc->get_metrics(metrics->rrc);
mac.get_metrics(metrics->mac);
rrc.get_metrics(metrics->rrc);
return true;
}
@ -170,25 +173,28 @@ bool gnb_stack_nr::has_active_radio_bearer(uint32_t eps_bearer_id)
}
int gnb_stack_nr::slot_indication(const srsran_slot_cfg_t& slot_cfg)
{
return m_mac->slot_indication(slot_cfg);
return mac.slot_indication(slot_cfg);
}
int gnb_stack_nr::get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched)
{
return m_mac->get_dl_sched(slot_cfg, dl_sched);
return mac.get_dl_sched(slot_cfg, dl_sched);
}
int gnb_stack_nr::get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched)
{
return m_mac->get_ul_sched(slot_cfg, ul_sched);
return mac.get_ul_sched(slot_cfg, ul_sched);
}
int gnb_stack_nr::pucch_info(const srsran_slot_cfg_t& slot_cfg, const mac_interface_phy_nr::pucch_info_t& pucch_info)
{
return m_mac->pucch_info(slot_cfg, pucch_info);
return mac.pucch_info(slot_cfg, pucch_info);
}
int gnb_stack_nr::pusch_info(const srsran_slot_cfg_t& slot_cfg, mac_interface_phy_nr::pusch_info_t& pusch_info)
{
return m_mac->pusch_info(slot_cfg, pusch_info);
return mac.pusch_info(slot_cfg, pusch_info);
}
void gnb_stack_nr::rach_detected(const rach_info_t& rach_info) {}
void gnb_stack_nr::rach_detected(const rach_info_t& rach_info)
{
mac.rach_detected(rach_info);
}
} // namespace srsenb

@ -46,8 +46,8 @@ bwp_params::bwp_params(const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_, ui
uint32_t nof_slots = SRSRAN_NSLOTS_PER_FRAME_NR(cfg.numerology_idx);
for (size_t sl = 0; sl < nof_slots; ++sl) {
slot_cfg sl_cfg{};
sl_cfg.is_dl = srsran_tdd_nr_is_dl(&cell_cfg.tdd, cfg.numerology_idx, sl);
sl_cfg.is_ul = srsran_tdd_nr_is_ul(&cell_cfg.tdd, cfg.numerology_idx, sl);
sl_cfg.is_dl = srsran_duplex_nr_is_dl(&cell_cfg.duplex, cfg.numerology_idx, sl);
sl_cfg.is_ul = srsran_duplex_nr_is_ul(&cell_cfg.duplex, cfg.numerology_idx, sl);
slots.push_back(sl_cfg);
}

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

@ -89,8 +89,15 @@ void sf_grid_t::init(const sched_cell_params_t& cell_params_)
pucch_mask.resize(cc_cfg->nof_prb());
pucch_nrb = (cc_cfg->cfg.nrb_pucch > 0) ? (uint32_t)cc_cfg->cfg.nrb_pucch : 0;
srsran_pucch_cfg_t pucch_cfg = cell_params_.pucch_cfg_common;
pucch_cfg.n_pucch = cc_cfg->nof_cce_table[SRSRAN_NOF_CFI - 1] - 1 + cc_cfg->cfg.n1pucch_an;
pucch_nrb = std::max(pucch_nrb, srsran_pucch_m(&pucch_cfg, cc_cfg->cfg.cell.cp) / 2 + 1);
uint32_t harq_pucch = 0;
if (cc_cfg->sched_cfg->pucch_harq_max_rb > 0) {
harq_pucch = cc_cfg->sched_cfg->pucch_harq_max_rb;
} else {
pucch_cfg.n_pucch =
cc_cfg->nof_cce_table[cell_params_.sched_cfg->max_nof_ctrl_symbols - 1] - 1 + cc_cfg->cfg.n1pucch_an;
harq_pucch = srsran_pucch_m(&pucch_cfg, cc_cfg->cfg.cell.cp) / 2 + 1;
}
pucch_nrb = std::max(pucch_nrb, harq_pucch);
if (pucch_nrb > 0) {
pucch_mask.fill(0, pucch_nrb);
pucch_mask.fill(cc_cfg->nof_prb() - pucch_nrb, cc_cfg->nof_prb());

@ -190,6 +190,15 @@ bool sf_cch_allocator::alloc_dfs_node(const alloc_record& record, uint32_t start
// PUCCH allocation would collide with other PUCCH/PUSCH grants. Try another CCE position
continue;
}
int low_rb = node.pucch_n_prb < (int)cc_cfg->cfg.cell.nof_prb / 2
? node.pucch_n_prb
: cc_cfg->cfg.cell.nof_prb - node.pucch_n_prb - 1;
if (cc_cfg->sched_cfg->pucch_harq_max_rb > 0 && low_rb >= cc_cfg->sched_cfg->pucch_harq_max_rb) {
// PUCCH allocation would fall outside the maximum allowed PUCCH HARQ region. Try another CCE position
logger.info("Skipping PDCCH allocation for CCE=%d due to PUCCH HARQ falling outside region\n",
node.dci_pos.ncce);
continue;
}
}
node.current_mask.reset();

@ -501,10 +501,8 @@ void rrc_nr::ue::send_dl_ccch(dl_ccch_msg_s* dl_ccch_msg)
}
// Helper for the RRC Reconfiguration sender to pack hard-coded config
int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_secondary_cell_config)
int rrc_nr::ue::pack_secondary_cell_group_config_common(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack)
{
auto& cell_group_cfg_pack = cell_group_cfg;
// RLC for DRB1 (with fixed LCID)
cell_group_cfg_pack.rlc_bearer_to_add_mod_list_present = true;
cell_group_cfg_pack.rlc_bearer_to_add_mod_list.resize(1);
@ -644,7 +642,6 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec
pdsch_cfg_dedicated.setup().p_zp_csi_rs_res_set.setup().zp_csi_rs_res_id_list.resize(1);
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.first_active_dl_bwp_id_present = true;
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.first_active_dl_bwp_id = 1;
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg_present = true;
// UL config dedicated
@ -666,19 +663,10 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec
sr_res1.sched_request_id = 0;
sr_res1.periodicity_and_offset_present = true;
sr_res1.periodicity_and_offset.set_sl40();
sr_res1.periodicity_and_offset.sl40() = 7;
sr_res1.res_present = true;
sr_res1.res = 2; // PUCCH resource for SR
// DL data
ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack_present = true;
ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack.resize(6);
ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[0] = 6;
ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[1] = 5;
ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[2] = 4;
ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[3] = 4;
ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[4] = 4;
ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[5] = 4;
// PUCCH Resource for format 1
srsran_pucch_nr_resource_t resource_small = {};
@ -764,8 +752,8 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec
beta_offset_semi_static.beta_offset_ack_idx3_present = true;
beta_offset_semi_static.beta_offset_ack_idx3 = 9;
beta_offset_semi_static.beta_offset_csi_part1_idx1_present = true;
beta_offset_semi_static.beta_offset_csi_part1_idx2_present = true;
beta_offset_semi_static.beta_offset_csi_part1_idx1 = 6;
beta_offset_semi_static.beta_offset_csi_part1_idx2_present = true;
beta_offset_semi_static.beta_offset_csi_part1_idx2 = 6;
beta_offset_semi_static.beta_offset_csi_part2_idx1_present = true;
beta_offset_semi_static.beta_offset_csi_part2_idx1 = 6;
@ -805,10 +793,8 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec
nzp_csi_res.res_map.freq_band.nrof_rbs = 52;
nzp_csi_res.pwr_ctrl_offset = 0;
// Skip pwr_ctrl_offset_ss_present
nzp_csi_res.scrambling_id = 0;
nzp_csi_res.periodicity_and_offset_present = true;
nzp_csi_res.periodicity_and_offset.set_slots80();
nzp_csi_res.periodicity_and_offset.slots80() = 0;
// optional
nzp_csi_res.qcl_info_periodic_csi_rs_present = true;
nzp_csi_res.qcl_info_periodic_csi_rs = 0;
@ -819,9 +805,7 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list.resize(1);
auto& nzp_csi_res_set =
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list[0];
nzp_csi_res_set.nzp_csi_res_set_id = 0;
nzp_csi_res_set.nzp_csi_rs_res.resize(1);
nzp_csi_res_set.nzp_csi_rs_res[0] = 0;
// Skip TRS info
// CSI report config
@ -835,7 +819,6 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec
csi_report.csi_im_res_for_interference = 1;
csi_report.report_cfg_type.set_periodic();
csi_report.report_cfg_type.periodic().report_slot_cfg.set_slots80();
csi_report.report_cfg_type.periodic().report_slot_cfg.slots80() = 8;
csi_report.report_cfg_type.periodic().pucch_csi_res_list.resize(1);
csi_report.report_cfg_type.periodic().pucch_csi_res_list[0].ul_bw_part_id = 0;
csi_report.report_cfg_type.periodic().pucch_csi_res_list[0].pucch_res = 0; // was 17 in orig PCAP
@ -857,11 +840,11 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec
// Reconfig with Sync
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync_present = true;
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.new_ue_id = rnti;
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.smtc.release();
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.t304 = recfg_with_sync_s::t304_opts::ms1000;
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common_present = true;
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ss_pbch_block_pwr = 0;
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.n_timing_advance_offset =
asn1::rrc_nr::serving_cell_cfg_common_s::n_timing_advance_offset_opts::n0;
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dmrs_type_a_position =
asn1::rrc_nr::serving_cell_cfg_common_s::dmrs_type_a_position_opts::pos2;
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.pci_present = true;
@ -875,13 +858,7 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl_present = true;
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl
.absolute_freq_ssb_present = true;
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.absolute_freq_ssb =
634176; // TODO: calculate from actual DL ARFCN
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.freq_band_list
.push_back(78);
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.absolute_freq_point_a =
633928; // TODO: calculate from actual DL ARFCN
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl
.scs_specific_carrier_list.resize(1);
@ -905,7 +882,6 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec
auto& pdcch_cfg_common =
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp.pdcch_cfg_common;
pdcch_cfg_common.set_setup();
pdcch_cfg_common.setup().ext = false;
pdcch_cfg_common.setup().common_ctrl_res_set_present = true;
pdcch_cfg_common.setup().common_ctrl_res_set.ctrl_res_set_id = 1;
pdcch_cfg_common.setup().common_ctrl_res_set.freq_domain_res.from_number(
@ -982,7 +958,6 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common;
rach_cfg_common_pack.set_setup();
rach_cfg_common_pack.setup().rach_cfg_generic.prach_cfg_idx = 0;
rach_cfg_common_pack.setup().rach_cfg_generic.msg1_fdm = rach_cfg_generic_s::msg1_fdm_opts::one;
rach_cfg_common_pack.setup().rach_cfg_generic.msg1_freq_start = 1;
rach_cfg_common_pack.setup().rach_cfg_generic.zero_correlation_zone_cfg = 0;
@ -1033,12 +1008,181 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec
// SSB config (optional)
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_positions_in_burst_present = true;
auto& ssb_pos_in_burst = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_positions_in_burst;
ssb_pos_in_burst.set_medium_bitmap().from_number(0b10000000);
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_periodicity_serving_cell_present = true;
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_periodicity_serving_cell =
serving_cell_cfg_common_s::ssb_periodicity_serving_cell_opts::ms20;
// TDD UL-DL config
return SRSRAN_SUCCESS;
}
// Helper for the RRC Reconfiguration sender to pack hard-coded config
int rrc_nr::ue::pack_secondary_cell_group_config_fdd(asn1::dyn_octstring& packed_secondary_cell_config)
{
auto& cell_group_cfg_pack = cell_group_cfg;
pack_secondary_cell_group_config_common(cell_group_cfg);
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.first_active_dl_bwp_id = 0;
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg_present = true;
// UL config dedicated
auto& ul_config = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg;
// SR resources
auto& sr_res1 = ul_config.init_ul_bwp.pucch_cfg.setup().sched_request_res_to_add_mod_list[0];
sr_res1.periodicity_and_offset.sl40() = 4;
sr_res1.res_present = true;
sr_res1.res = 16; // PUCCH resource for SR
// DL data
ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack_present = true;
ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack.resize(1);
ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[0] = 4;
// nzp-CSI-RS Resource
auto& nzp_csi_res =
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list[0];
nzp_csi_res.scrambling_id = 500;
nzp_csi_res.periodicity_and_offset_present = true;
nzp_csi_res.periodicity_and_offset.set_slots80();
nzp_csi_res.periodicity_and_offset.slots80() = 1;
// nzp-CSI-RS ResourceSet
auto& nzp_csi_res_set =
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list[0];
nzp_csi_res_set.nzp_csi_res_set_id = 1;
nzp_csi_res_set.nzp_csi_rs_res[0] = 1;
// CSI report config
auto& csi_report =
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().csi_report_cfg_to_add_mod_list[0];
csi_report.report_cfg_type.periodic().report_slot_cfg.slots80() = 5;
// Reconfig with Sync
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common_present = true;
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ss_pbch_block_pwr = -36;
// DL config
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common_present = true;
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.absolute_freq_ssb =
176210; // TODO: calculate from actual DL ARFCN
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.freq_band_list
.push_back(5);
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.absolute_freq_point_a =
175364; // TODO: calculate from actual DL ARFCN
// RACH config
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common_present =
true;
auto& rach_cfg_common_pack =
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common;
rach_cfg_common_pack.set_setup();
rach_cfg_common_pack.setup().rach_cfg_generic.prach_cfg_idx = 16;
// SSB config (optional)
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_positions_in_burst_present = true;
auto& ssb_pos_in_burst = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_positions_in_burst;
ssb_pos_in_burst.set_short_bitmap().from_number(0b1000);
// make sufficiant space
packed_secondary_cell_config.resize(256);
asn1::bit_ref bref_pack(packed_secondary_cell_config.data(), packed_secondary_cell_config.size());
if (cell_group_cfg_pack.pack(bref_pack) != asn1::SRSASN_SUCCESS) {
parent->logger.error("Failed to pack NR secondary cell config");
return SRSRAN_ERROR;
}
packed_secondary_cell_config.resize(bref_pack.distance_bytes());
return SRSRAN_SUCCESS;
}
// Helper for the RRC Reconfiguration sender to pack hard-coded config
int rrc_nr::ue::pack_secondary_cell_group_config_tdd(asn1::dyn_octstring& packed_secondary_cell_config)
{
auto& cell_group_cfg_pack = cell_group_cfg;
pack_secondary_cell_group_config_common(cell_group_cfg);
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.first_active_dl_bwp_id = 1;
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg_present = true;
// UL config dedicated
auto& ul_config = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg;
// SR resources
auto& sr_res1 = ul_config.init_ul_bwp.pucch_cfg.setup().sched_request_res_to_add_mod_list[0];
// SR resources
sr_res1.periodicity_and_offset.sl40() = 7;
sr_res1.res_present = true;
sr_res1.res = 2; // PUCCH resource for SR
// DL data
ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack_present = true;
ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack.resize(6);
ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[0] = 6;
ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[1] = 5;
ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[2] = 4;
ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[3] = 4;
ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[4] = 4;
ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[5] = 4;
// nzp-CSI-RS Resource
auto& nzp_csi_res =
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list[0];
nzp_csi_res.scrambling_id = 0;
nzp_csi_res.periodicity_and_offset_present = true;
nzp_csi_res.periodicity_and_offset.set_slots80();
nzp_csi_res.periodicity_and_offset.slots80() = 0;
// nzp-CSI-RS ResourceSet
auto& nzp_csi_res_set =
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list[0];
nzp_csi_res_set.nzp_csi_res_set_id = 0;
nzp_csi_res_set.nzp_csi_rs_res[0] = 0;
// Skip TRS info
// CSI report config
auto& csi_report =
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().csi_report_cfg_to_add_mod_list[0];
csi_report.report_cfg_type.periodic().report_slot_cfg.slots80() = 8;
// Reconfig with Sync
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.smtc.release();
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common_present = true;
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ss_pbch_block_pwr = 0;
// DL config
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common_present = true;
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.absolute_freq_ssb =
634176; // TODO: calculate from actual DL ARFCN
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.freq_band_list
.push_back(78);
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.absolute_freq_point_a =
633928; // TODO: calculate from actual DL ARFCN
auto& pdcch_cfg_common =
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp.pdcch_cfg_common;
pdcch_cfg_common.set_setup();
pdcch_cfg_common.setup().ext = false;
// RACH config
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common_present =
true;
auto& rach_cfg_common_pack =
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common;
rach_cfg_common_pack.set_setup();
rach_cfg_common_pack.setup().rach_cfg_generic.prach_cfg_idx = 0;
// SSB config (optional)
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_positions_in_burst_present = true;
auto& ssb_pos_in_burst = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_positions_in_burst;
ssb_pos_in_burst.set_medium_bitmap().from_number(0b10000000);
// // TDD UL-DL config
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common_present = true;
auto& tdd_config = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common;
tdd_config.ref_subcarrier_spacing = subcarrier_spacing_e::khz15;
@ -1069,8 +1213,8 @@ int rrc_nr::ue::pack_rrc_reconfiguraiton(asn1::dyn_octstring& packed_rrc_reconfi
// add secondary cell group config
recfg_ies.secondary_cell_group_present = true;
if (pack_secondary_cell_group_config(recfg_ies.secondary_cell_group) == SRSRAN_ERROR) {
parent->logger.error("Failed to pack RRC Reconfiguration");
if (pack_secondary_cell_group_config_tdd(recfg_ies.secondary_cell_group) == SRSRAN_ERROR) {
parent->logger.error("Failed to pack TDD RRC Reconfiguration");
return SRSRAN_ERROR;
}

@ -349,6 +349,7 @@ void rrc::ue::parse_ul_dcch(uint32_t lcid, srsran::unique_byte_buffer_t pdu)
case ul_dcch_msg_type_c::c1_c_::types::rrc_conn_reest_complete:
save_ul_message(std::move(original_pdu));
handle_rrc_con_reest_complete(&ul_dcch_msg.msg.c1().rrc_conn_reest_complete(), std::move(pdu));
set_activity_timeout(UE_INACTIVITY_TIMEOUT);
set_activity();
break;
case ul_dcch_msg_type_c::c1_c_::types::ul_info_transfer:

@ -61,7 +61,10 @@ asn1::bounded_bitstring<1, 160, true, true> addr_to_asn1(const char* addr_str)
{
asn1::bounded_bitstring<1, 160, true, true> transport_layer_addr(32);
uint8_t addr[4];
inet_pton(AF_INET, addr_str, addr);
if (inet_pton(AF_INET, addr_str, addr) != 1) {
srsran::console("Invalid addr_str: %s\n", addr_str);
perror("inet_pton");
}
for (uint32_t j = 0; j < 4; ++j) {
transport_layer_addr.data()[j] = addr[3 - j];
}
@ -1735,9 +1738,17 @@ void s1ap::ue::get_erab_addr(uint16_t erab_id, transp_addr_t& transp_addr, asn1:
transp_addr.resize(32);
uint8_t addr[4];
if (!s1ap_ptr->args.gtp_advertise_addr.empty()) {
inet_pton(AF_INET, s1ap_ptr->args.gtp_advertise_addr.c_str(), addr);
if (inet_pton(AF_INET, s1ap_ptr->args.gtp_advertise_addr.c_str(), addr) != 1) {
logger.error("Invalid gtp_advertise_addr: %s", s1ap_ptr->args.gtp_advertise_addr.c_str());
srsran::console("Invalid gtp_advertise_addr: %s\n", s1ap_ptr->args.gtp_advertise_addr.c_str());
perror("inet_pton");
}
} else {
inet_pton(AF_INET, s1ap_ptr->args.gtp_bind_addr.c_str(), addr);
if (inet_pton(AF_INET, s1ap_ptr->args.gtp_bind_addr.c_str(), addr) != 1) {
logger.error("Invalid gtp_bind_addr: %s", s1ap_ptr->args.gtp_bind_addr.c_str());
srsran::console("Invalid gtp_bind_addr: %s\n", s1ap_ptr->args.gtp_bind_addr.c_str());
perror("inet_pton");
}
}
for (uint32_t j = 0; j < 4; ++j) {
transp_addr.data()[j] = addr[3 - j];

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

@ -27,7 +27,7 @@ target_link_libraries(sched_nr_test
srsran_common
${CMAKE_THREAD_LIBS_INIT}
${Boost_LIBRARIES})
add_test(sched_nr_test sched_nr_test)
add_nr_test(sched_nr_test sched_nr_test)
add_executable(sched_nr_prb_test sched_nr_prb_test.cc)
target_link_libraries(sched_nr_prb_test
@ -35,8 +35,8 @@ target_link_libraries(sched_nr_prb_test
srsran_common
${CMAKE_THREAD_LIBS_INIT}
${Boost_LIBRARIES})
add_test(sched_nr_prb_test sched_nr_prb_test)
add_nr_test(sched_nr_prb_test sched_nr_prb_test)
add_executable(sched_nr_rar_test sched_nr_rar_test.cc)
target_link_libraries(sched_nr_rar_test srsgnb_mac sched_nr_test_suite srsran_common)
add_test(sched_nr_rar_test sched_nr_rar_test)
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{};
cell_cfg.carrier = phy_cfg.carrier;
cell_cfg.tdd = phy_cfg.tdd;
cell_cfg.duplex = phy_cfg.duplex;
cell_cfg.bwps.resize(1);
cell_cfg.bwps[0].pdcch = phy_cfg.pdcch;

@ -120,7 +120,7 @@ void sched_nr_cfg_serialized_test()
sched_nr_cc_output_res_t out{slot_tx, cc, &dl_res, &ul_res};
sched_tester.update(out);
tasks.finish_cc(slot_rx, dl_res, ul_res);
TESTASSERT(not srsran_tdd_nr_is_dl(&cells_cfg[cc].tdd, 0, (slot_tx).slot_idx()) or
TESTASSERT(not srsran_duplex_nr_is_dl(&cells_cfg[cc].duplex, 0, (slot_tx).slot_idx()) or
dl_res.dl_sched.pdcch_dl.size() == 1);
}
}

@ -719,7 +719,7 @@ public:
return SRSRAN_SUCCESS;
}
void set_sched_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs) override { notify_set_sched_dl_tti_mask(); }
void tti_clock() override { notify_tti_clock(); }
void tti_clock() { notify_tti_clock(); }
int run_tti(bool enable_assert)
{
std::lock_guard<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;
class phy_test_bench
class phy_test_bench : public srsenb::enb_time_interface
{
public:
struct args_t {
@ -1337,7 +1337,7 @@ public:
stack->set_active_cell_list(args.ue_cell_list);
/// Initiate eNb PHY with the given RNTI
if (enb_phy->init(phy_args, phy_cfg, radio.get(), stack.get()) < 0) {
if (enb_phy->init(phy_args, phy_cfg, radio.get(), stack.get(), this) < 0) {
return SRSRAN_ERROR;
}
enb_phy->set_config(args.rnti, phy_rrc_cfg);
@ -1359,7 +1359,7 @@ public:
enb_phy->stop();
}
~phy_test_bench() = default;
virtual ~phy_test_bench() = default;
int run_tti()
{
@ -1431,6 +1431,11 @@ public:
return ret;
}
void tti_clock() final
{
// nothing to do
}
};
typedef std::unique_ptr<phy_test_bench> unique_phy_test_bench;

@ -21,6 +21,7 @@
#include "srsepc/hdr/mbms-gw/mbms-gw.h"
#include "srsran/common/standard_streams.h"
#include "srsran/common/network_utils.h"
#include "srsran/upper/gtpu.h"
#include <algorithm>
#include <fcntl.h>
@ -161,9 +162,12 @@ int mbms_gw::init_sgi_mb_if(mbms_gw_args_t* args)
// Set IP of the interface
struct sockaddr_in* addr = (struct sockaddr_in*)&ifr.ifr_addr;
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = inet_addr(args->sgi_mb_if_addr.c_str());
addr->sin_port = 0;
if (not srsran::net_utils::set_sockaddr(addr, args->sgi_mb_if_addr.c_str(), 0)) {
m_logger.error("Invalid sgi_mb_if_addr: %s", args->sgi_mb_if_addr.c_str());
srsran::console("Invalid sgi_mb_if_addr: %s\n", args->sgi_mb_if_addr.c_str());
return SRSRAN_ERROR_CANT_START;
}
if (ioctl(sgi_mb_sock, SIOCSIFADDR, &ifr) < 0) {
m_logger.error(
@ -174,7 +178,12 @@ int mbms_gw::init_sgi_mb_if(mbms_gw_args_t* args)
}
ifr.ifr_netmask.sa_family = AF_INET;
((struct sockaddr_in*)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr(args->sgi_mb_if_mask.c_str());
if (inet_pton(ifr.ifr_netmask.sa_family, args->sgi_mb_if_mask.c_str(), &((struct sockaddr_in*)&ifr.ifr_netmask)->sin_addr.s_addr ) != 1) {
m_logger.error("Invalid sgi_mb_if_mask: %s", args->sgi_mb_if_mask.c_str());
srsran::console("Invalid sgi_mb_if_mask: %s\n", args->sgi_mb_if_mask.c_str());
perror("inet_pton");
return SRSRAN_ERROR_CANT_START;
}
if (ioctl(sgi_mb_sock, SIOCSIFNETMASK, &ifr) < 0) {
m_logger.error("Failed to set TUN interface Netmask. Error: %s", strerror(errno));
close(m_sgi_mb_if);
@ -210,7 +219,12 @@ int mbms_gw::init_m1_u(mbms_gw_args_t* args)
/* Set local interface for outbound multicast packets*/
/* The IP must be associated with a local multicast capable interface */
struct in_addr local_if;
local_if.s_addr = inet_addr(args->m1u_multi_if.c_str());
if (inet_pton(AF_INET, args->m1u_multi_if.c_str(), &local_if.s_addr) != 1) {
m_logger.error("Invalid m1u_multi_if: %s", args->m1u_multi_if.c_str());
srsran::console("Invalid m1u_multi_if: %s\n", args->m1u_multi_if.c_str());
perror("inet_pton");
return SRSRAN_ERROR_CANT_START;
}
if (setsockopt(m_m1u, IPPROTO_IP, IP_MULTICAST_IF, (char*)&local_if, sizeof(struct in_addr)) < 0) {
m_logger.error("Error %s setting multicast interface %s.", strerror(errno), args->m1u_multi_if.c_str());
return SRSRAN_ERROR_CANT_START;
@ -227,7 +241,12 @@ int mbms_gw::init_m1_u(mbms_gw_args_t* args)
bzero(&m_m1u_multi_addr, sizeof(m_m1u_multi_addr));
m_m1u_multi_addr.sin_family = AF_INET;
m_m1u_multi_addr.sin_port = htons(GTPU_RX_PORT + 1);
m_m1u_multi_addr.sin_addr.s_addr = inet_addr(args->m1u_multi_addr.c_str());
if (inet_pton(m_m1u_multi_addr.sin_family, args->m1u_multi_addr.c_str(), &m_m1u_multi_addr.sin_addr.s_addr) != 1) {
m_logger.error("Invalid m1u_multi_addr: %s", args->m1u_multi_addr.c_str());
srsran::console("Invalid m1u_multi_addr: %s\n", args->m1u_multi_addr.c_str());
perror("inet_pton");
return SRSRAN_ERROR_CANT_START;
}
m_logger.info("Initialized M1-U");
return SRSRAN_SUCCESS;

@ -1547,7 +1547,12 @@ bool nas::pack_attach_accept(srsran::byte_buffer_t* nas_buffer)
act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].len = 4;
struct sockaddr_in dns_addr;
inet_pton(AF_INET, m_dns.c_str(), &(dns_addr.sin_addr));
if (inet_pton(AF_INET, m_dns.c_str(), &(dns_addr.sin_addr)) != 1) {
m_logger.error("Invalid m_dns: %s", m_dns.c_str());
srsran::console("Invalid m_dns: %s\n", m_dns.c_str());
perror("inet_pton");
return false;
}
memcpy(act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].contents, &dns_addr.sin_addr.s_addr, 4);
// Make sure all unused options are set to false

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

@ -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
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;
in_addr.s_addr = inet_addr(iter->first.c_str());
if (inet_pton(AF_INET, iter->first.c_str(), &in_addr.s_addr) != 1) {
perror("inet_pton");
return SRSRAN_ERROR;
}
if (!m_imsi_to_ip.insert(std::make_pair(iter->second, in_addr)).second) {
m_logger.error(
"SPGW: duplicate imsi %015" PRIu64 " for static ip address %s.", iter->second, iter->first.c_str());
@ -562,7 +565,13 @@ int spgw::gtpc::init_ue_ip(spgw_args_t* args, const std::map<std::string, uint64
// first address is allocated to the epc tun interface, start w/next addr
for (uint32_t n = 1; n < 254; ++n) {
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));
if (iter != ip_to_imsi.end()) {

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

@ -491,8 +491,8 @@ public:
// Compute synch metrics and report it to the PHY state
sync_metrics_t new_sync_metrics = {};
new_sync_metrics.cfo = new_meas.cfo_hz;
set_sync_metrics(sync_metrics);
new_sync_metrics.cfo = new_meas.cfo_hz + ul_ext_cfo_hz;
set_sync_metrics(new_sync_metrics);
// Convert to CSI channel measurement and report new NZP-CSI-RS measurement to the PHY state
srsran_csi_channel_measurements_t measurements = {};
@ -508,11 +508,10 @@ public:
trs_measurements_mutex.lock();
trs_measurements.rsrp_dB = SRSRAN_VEC_SAFE_EMA(new_meas.rsrp_dB, trs_measurements.rsrp_dB, args.trs_epre_ema_alpha);
trs_measurements.epre_dB = SRSRAN_VEC_SAFE_EMA(new_meas.epre_dB, trs_measurements.epre_dB, args.trs_rsrp_ema_alpha);
trs_measurements.snr_dB = SRSRAN_VEC_SAFE_EMA(new_meas.snr_dB, trs_measurements.snr_dB, args.trs_sinr_ema_alpha);
// Consider CFO measurement invalid if the SNR is negative. In this case, set CFO to 0.
if (trs_measurements.snr_dB > 0.0f) {
if (new_meas.snr_dB > 0.0f) {
trs_measurements.cfo_hz = SRSRAN_VEC_SAFE_EMA(new_meas.cfo_hz, trs_measurements.cfo_hz, args.trs_cfo_ema_alpha);
} else {
trs_measurements.cfo_hz = 0.0f;
}
trs_measurements.nof_re++;
trs_measurements_mutex.unlock();

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

@ -159,7 +159,7 @@ private:
// pointer to MAC PCAP object
srsran::mac_pcap* pcap = nullptr;
bool is_first_ul_grant = false;
std::atomic<bool> is_first_ul_grant{false};
std::mutex metrics_mutex = {};
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_prohibit;
std::mutex mutex;
};
} // namespace srsue

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

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

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

@ -289,7 +289,12 @@ bool cc_worker::work_dl_regular()
// Decode PDSCH
decode_pdsch(ack_resource, &dl_action, dl_ack);
// Informs Stack about the decoding status
// Informs Stack about the decoding status, send NACK if cell is in process of re-selection
if (phy->cell_is_selecting) {
for (uint32_t i = 0; i < SRSRAN_MAX_CODEWORDS; i++) {
dl_ack[i] = false;
}
}
phy->stack->tb_decoded(cc_idx, mac_grant, dl_ack);
}

@ -184,12 +184,14 @@ void cc_worker::decode_pdcch_dl()
if (logger.debug.enabled()) {
for (uint32_t i = 0; i < ue_dl.pdcch_info_count; i++) {
const srsran_ue_dl_nr_pdcch_info_t* info = &ue_dl.pdcch_info[i];
logger.debug("PDCCH: dci=%s, rnti=%x, crst_id=%d, ss_type=%d, ncce=%d, al=%d, EPRE=%+.2f, RSRP=%+.2f, corr=%.3f; "
logger.debug(
"PDCCH: dci=%s, %s-rnti=%x, crst_id=%d, ss_type=%s, ncce=%d, al=%d, EPRE=%+.2f, RSRP=%+.2f, corr=%.3f; "
"evm=%f; nof_bits=%d; crc=%s;",
srsran_dci_format_nr_string(info->dci_ctx.format),
srsran_rnti_type_str_short(info->dci_ctx.rnti_type),
info->dci_ctx.rnti,
info->dci_ctx.coreset_id,
info->dci_ctx.ss_type,
srsran_ss_type_str(info->dci_ctx.ss_type),
info->dci_ctx.location.ncce,
info->dci_ctx.location.L,
info->measure.epre_dBfs,
@ -482,7 +484,7 @@ bool cc_worker::work_dl()
}
// Check if it is a DL slot, if not skip
if (!srsran_tdd_nr_is_dl(&phy.cfg.tdd, 0, dl_slot_cfg.idx)) {
if (!srsran_duplex_nr_is_dl(&phy.cfg.duplex, 0, dl_slot_cfg.idx)) {
return true;
}
@ -495,9 +497,10 @@ bool cc_worker::work_dl()
// Compensate CFO from TRS measurements
if (std::isnormal(phy.args.enable_worker_cfo)) {
float dl_cfo_hz = phy.get_dl_cfo();
float dl_cfo_norm = -dl_cfo_hz / (1000.0f * ue_ul.ifft.sf_sz);
for (cf_t* b : rx_buffer) {
if (b != nullptr and ue_ul.ifft.sf_sz != 0) {
srsran_vec_apply_cfo(b, dl_cfo_hz / (1000.0f * ue_ul.ifft.sf_sz), b, ue_ul.ifft.sf_sz);
srsran_vec_apply_cfo(b, dl_cfo_norm, b, ue_ul.ifft.sf_sz);
}
}
}
@ -529,7 +532,7 @@ bool cc_worker::work_ul()
bool has_ul_ack = phy.get_pending_ack(ul_slot_cfg.idx, pdsch_ack);
// Check if it is a UL slot, if not skip
if (!srsran_tdd_nr_is_ul(&phy.cfg.tdd, 0, ul_slot_cfg.idx)) {
if (!srsran_duplex_nr_is_ul(&phy.cfg.duplex, 0, ul_slot_cfg.idx)) {
// No NR signal shall be transmitted
srsran_vec_cf_zero(tx_buffer[0], ue_ul.ifft.sf_sz);

@ -88,7 +88,7 @@ sf_worker* worker_pool::wait_worker(uint32_t tti)
if (prach_buffer->is_ready_to_send(tti, phy_state.cfg.carrier.pci)) {
uint32_t nof_prach_sf = 0;
float prach_target_power = 0.0f;
cf_t* prach_ptr = prach_buffer->generate(-phy_state.get_ul_cfo() / 15000, &nof_prach_sf, &prach_target_power);
cf_t* prach_ptr = prach_buffer->generate(phy_state.get_ul_cfo() / 15000, &nof_prach_sf, &prach_target_power);
worker->set_prach(prach_ptr, prach_target_power);
}

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

@ -504,6 +504,8 @@ void sync::run_camping_in_sync_state(lte::sf_worker* lte_worker,
metrics.sfo = sfo;
metrics.cfo = cfo;
metrics.ta_us = worker_com->ta.get_usec();
metrics.distance_km = worker_com->ta.get_km();
metrics.speed_kmph = worker_com->ta.get_speed_kmph(tti);
for (uint32_t i = 0; i < worker_com->args->nof_lte_carriers; i++) {
worker_com->set_sync_metrics(i, metrics);
}
@ -552,7 +554,7 @@ void sync::run_camping_in_sync_state(lte::sf_worker* lte_worker,
// As UE sync compensates CFO externally based on LTE signal and the NR carrier may estimate the CFO from the LTE
// signal. It is necessary setting an NR external CFO offset to compensate it.
nr_worker_pool->set_ul_ext_cfo(-srsran_ue_sync_get_cfo(&ue_sync));
nr_worker_pool->set_ul_ext_cfo(srsran_ue_sync_get_cfo(&ue_sync));
// NR worker needs to be launched first, phy_common::worker_end expects first the NR worker and the LTE worker.
worker_com->semaphore.push(nr_worker);

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

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

@ -112,7 +112,7 @@ int ul_harq_entity::get_current_tbs(uint32_t pid)
float ul_harq_entity::get_average_retx()
{
return average_retx;
return average_retx.load(std::memory_order_relaxed);
}
ul_harq_entity::ul_harq_process::ul_harq_process() : logger(srslog::fetch_basic_logger("MAC"))
@ -357,7 +357,10 @@ void ul_harq_entity::ul_harq_process::generate_new_tx(mac_interface_phy_lte::mac
mac_interface_phy_lte::tb_action_ul_t* action)
{
// Compute average number of retransmissions per packet considering previous packet
harq_entity->average_retx = SRSRAN_VEC_CMA((float)current_tx_nb, harq_entity->average_retx, harq_entity->nof_pkts++);
harq_entity->average_retx.store(SRSRAN_VEC_CMA((float)current_tx_nb,
harq_entity->average_retx.load(std::memory_order_relaxed),
harq_entity->nof_pkts++),
std::memory_order_relaxed);
cur_grant = grant;
harq_feedback = false;
is_grant_configured = true;

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

@ -41,7 +41,7 @@
#include <numeric>
#include <string.h>
bool simulate_rlf = false;
std::atomic<bool> simulate_rlf{false};
using namespace srsran;
using namespace asn1::rrc;
@ -212,9 +212,9 @@ void rrc::run_tti()
return;
}
if (simulate_rlf) {
if (simulate_rlf.load(std::memory_order_relaxed)) {
radio_link_failure_process();
simulate_rlf = false;
simulate_rlf.store(false, std::memory_order_relaxed);
}
// Process pending PHY measurements in IDLE/CONNECTED

@ -1202,11 +1202,11 @@ bool rrc_nr::apply_sp_cell_cfg(const sp_cell_cfg_s& sp_cell_cfg)
}
if (recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common_present) {
srsran_tdd_config_nr_t tdd;
if (make_phy_tdd_cfg(recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common, &tdd) == true) {
phy_cfg.tdd = tdd;
srsran_duplex_config_nr_t duplex;
if (make_phy_tdd_cfg(recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common, &duplex) == true) {
phy_cfg.duplex = duplex;
} else {
logger.warning("Warning while building tdd structure");
logger.warning("Warning while building duplex structure");
return false;
}
} else {

@ -120,7 +120,12 @@ bool ue_stack_nr::switch_on()
{
// statically setup TUN (will be done through RRC later)
char* err_str = nullptr;
if (gw->setup_if_addr(5, LIBLTE_MME_PDN_TYPE_IPV4, htonl(inet_addr("192.168.1.3")), nullptr, err_str)) {
struct in_addr in_addr;
if (inet_pton(AF_INET, "192.168.1.3", &in_addr.s_addr) != 1) {
perror("inet_pton");
return false;
}
if (gw->setup_if_addr(5, LIBLTE_MME_PDN_TYPE_IPV4, htonl(in_addr.s_addr), nullptr, err_str)) {
printf("Error configuring TUN interface\n");
}
return true;

@ -63,7 +63,10 @@ int gw::init(const gw_args_t& args_, stack_interface_gw* stack_)
}
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;
}
@ -463,7 +466,12 @@ int gw::setup_if_addr4(uint32_t ip_addr, char* err_str)
return SRSRAN_ERROR_CANT_START;
}
ifr.ifr_netmask.sa_family = AF_INET;
((struct sockaddr_in*)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr(args.tun_dev_netmask.c_str());
if (inet_pton(ifr.ifr_netmask.sa_family, args.tun_dev_netmask.c_str(), &((struct sockaddr_in*)&ifr.ifr_netmask)->sin_addr.s_addr) != 1) {
logger.error("Invalid tun_dev_netmask: %s", args.tun_dev_netmask.c_str());
srsran::console("Invalid tun_dev_netmask: %s\n", args.tun_dev_netmask.c_str());
perror("inet_pton");
return SRSRAN_ERROR_CANT_START;
}
if (0 > ioctl(sock, SIOCSIFNETMASK, &ifr)) {
err_str = strerror(errno);
logger.debug("Failed to set socket netmask: %s", err_str);

@ -52,7 +52,12 @@ int gw_test()
char* err_str = nullptr;
int rtn = 0;
rtn = gw.setup_if_addr(eps_bearer_id, LIBLTE_MME_PDN_TYPE_IPV4, htonl(inet_addr("192.168.56.32")), nullptr, err_str);
struct in_addr in_addr;
if (inet_pton(AF_INET, "192.168.56.32", &in_addr.s_addr) != 1) {
perror("inet_pton");
return SRSRAN_ERROR;
}
rtn = gw.setup_if_addr(eps_bearer_id, LIBLTE_MME_PDN_TYPE_IPV4, htonl(in_addr.s_addr), nullptr, err_str);
if (rtn != SRSRAN_SUCCESS) {
srslog::fetch_basic_logger("TEST", false)

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

@ -37,15 +37,18 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB)
${Boost_LIBRARIES}
${ATOMIC_LIBS})
# For each supported bandwidth
foreach (NR_PHY_TEST_BW "10MHz" "20MHz")
foreach (NR_PHY_TEST_TDD "6D+4U" "FR1.15-1")
# For each supported frame structure
foreach (NR_PHY_TEST_DUPLEX "FDD" "6D+4U" "FR1.15-1")
set(NR_PHY_TEST_DURATION_MS 20)
# DL flooding only
foreach (NR_PHY_TEST_PDSCH "default" "ts38101/5.2-1")
add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_TDD}_dl_${NR_PHY_TEST_PDSCH} nr_phy_test
--reference=carrier=${NR_PHY_TEST_BW},tdd=${NR_PHY_TEST_TDD},pdsch=${NR_PHY_TEST_PDSCH}
add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_DUPLEX}_dl_${NR_PHY_TEST_PDSCH} nr_phy_test
--reference=carrier=${NR_PHY_TEST_BW},duplex=${NR_PHY_TEST_DUPLEX},pdsch=${NR_PHY_TEST_PDSCH}
--duration=${NR_PHY_TEST_DURATION_MS}
--gnb.stack.pdsch.slots=0,1,2,3,4,5 # All possible DL slots
--gnb.stack.pdsch.slots=all
--gnb.stack.pdsch.start=0 # Start at RB 0
--gnb.stack.pdsch.length=52 # Full 10 MHz BW
--gnb.stack.pdsch.mcs=27 # Maximum MCS
@ -55,11 +58,12 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB)
)
endforeach ()
add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_TDD}_ul_only nr_phy_test
--reference=carrier=${NR_PHY_TEST_BW},tdd=${NR_PHY_TEST_TDD}
# UL flooding
add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_DUPLEX}_ul_only nr_phy_test
--reference=carrier=${NR_PHY_TEST_BW},duplex=${NR_PHY_TEST_DUPLEX}
--duration=${NR_PHY_TEST_DURATION_MS}
--gnb.stack.pdsch.slots=6 # No PDSCH
--gnb.stack.pusch.slots=6,7,8,9 # All possible UL slots
--gnb.stack.pdsch.slots=none
--gnb.stack.pusch.slots=all
--gnb.stack.pusch.start=0 # Start at RB 0
--gnb.stack.pusch.length=52 # Full 10 MHz BW
--gnb.stack.pusch.mcs=28 # Maximum MCS
@ -67,14 +71,15 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB)
--ue.phy.nof_threads=${NR_PHY_TEST_UE_NOF_THREADS}
)
add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_TDD}_bidir nr_phy_test
--reference=carrier=${NR_PHY_TEST_BW},tdd=${NR_PHY_TEST_TDD}
# DL and UL flooding
add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_DUPLEX}_bidir nr_phy_test
--reference=carrier=${NR_PHY_TEST_BW},duplex=${NR_PHY_TEST_DUPLEX}
--duration=${NR_PHY_TEST_DURATION_MS}
--gnb.stack.pdsch.slots=0,1,2,3,4,5 # All possible DL slots
--gnb.stack.pdsch.slots=all
--gnb.stack.pdsch.start=0 # Start at RB 0
--gnb.stack.pdsch.length=52 # Full 10 MHz BW
--gnb.stack.pdsch.mcs=28 # Maximum MCS
--gnb.stack.pusch.slots=6,7,8,9 # All possible UL slots
--gnb.stack.pusch.slots=all
--gnb.stack.pusch.start=0 # Start at RB 0
--gnb.stack.pusch.length=52 # Full 10 MHz BW
--gnb.stack.pusch.mcs=28 # Maximum MCS

@ -369,11 +369,23 @@ public:
ul.mcs = args.pusch.mcs;
if (args.pdsch.slots != "none" and not args.pdsch.slots.empty()) {
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 == "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
for (uint32_t slot = 0; slot < SRSRAN_NOF_SF_X_FRAME; slot++) {
@ -414,7 +426,11 @@ public:
// Setup DL Data to ACK timing
for (uint32_t i = 0; i < SRSRAN_NOF_SF_X_FRAME; i++) {
dl_data_to_ul_ack[i] = args.phy_cfg.harq_ack.dl_data_to_ul_ack[i % args.phy_cfg.tdd.pattern1.period_ms];
if (args.phy_cfg.duplex.mode == SRSRAN_DUPLEX_MODE_TDD) {
dl_data_to_ul_ack[i] = args.phy_cfg.harq_ack.dl_data_to_ul_ack[i % args.phy_cfg.duplex.tdd.pattern1.period_ms];
} else {
dl_data_to_ul_ack[i] = args.phy_cfg.harq_ack.dl_data_to_ul_ack[i % args.phy_cfg.harq_ack.nof_dl_data_to_ul_ack];
}
}
// If reached this point the configuration is valid
@ -450,7 +466,7 @@ public:
}
// Check if it is TDD DL slot and PDSCH mask, if no PDSCH shall be scheduled, do not set any grant and skip
if (not srsran_tdd_nr_is_dl(&phy_cfg.tdd, phy_cfg.carrier.scs, slot_cfg.idx)) {
if (not srsran_duplex_nr_is_dl(&phy_cfg.duplex, phy_cfg.carrier.scs, slot_cfg.idx)) {
return SRSRAN_SUCCESS;
}
@ -460,7 +476,7 @@ public:
}
// Check if the UL slot is valid, if not skip UL scheduling
if (not srsran_tdd_nr_is_ul(&phy_cfg.tdd, phy_cfg.carrier.scs, TTI_TX(slot_cfg.idx))) {
if (not srsran_duplex_nr_is_ul(&phy_cfg.duplex, phy_cfg.carrier.scs, TTI_TX(slot_cfg.idx))) {
return SRSRAN_SUCCESS;
}

Loading…
Cancel
Save