Merge branch 'next' into agpl_next

# Conflicts:
#	srsenb/hdr/phy/nr/cc_worker.h
#	srsenb/hdr/phy/nr/sf_worker.h
#	srsenb/src/phy/nr/cc_worker.cc
#	srsenb/src/phy/nr/sf_worker.cc
#	test/phy/nr_phy_test.cc
master
Codebot 4 years ago committed by Your Name
commit 585e3c51c1

@ -129,7 +129,7 @@ bool make_mac_dl_harq_cfg_nr_t(const asn1::rrc_nr::pdsch_ser
/***************************
* RLC Config
**************************/
rlc_config_t make_rlc_config_t(const asn1::rrc_nr::rlc_cfg_c& asn1_type);
int make_rlc_config_t(const asn1::rrc_nr::rlc_cfg_c& asn1_type, rlc_config_t* rlc_config_out);
/***************************
* PDCP Config

@ -32,6 +32,7 @@ namespace srsran {
typedef struct {
std::string phy_level = "none";
std::string phy_lib_level = "none";
std::string id_preamble = "";
int phy_hex_limit = -1;
} phy_log_args_t;

@ -46,6 +46,8 @@ private:
std::deque<T> fifo; ///< Queue to keep order
public:
tti_semaphore() = default;
/**
* Waits for the first element of the queue match the element identifier provided.
*

@ -31,9 +31,9 @@
#include "srsenb/hdr/stack/s1ap/s1ap_metrics.h"
#include "srsran/common/metrics_hub.h"
#include "srsran/radio/radio_metrics.h"
#include "srsran/rlc/rlc_metrics.h"
#include "srsran/system/sys_metrics.h"
#include "srsran/upper/pdcp_metrics.h"
#include "srsran/upper/rlc_metrics.h"
#include "srsue/hdr/stack/upper/gw_metrics.h"
namespace srsenb {

@ -39,6 +39,8 @@ struct s1ap_args_t {
std::string s1c_bind_addr;
uint16_t s1c_bind_port;
std::string enb_name;
uint32_t ts1_reloc_prep_timeout;
uint32_t ts1_reloc_overall_timeout;
};
// S1AP interface for RRC

@ -219,29 +219,56 @@ public:
class mac_interface_phy_nr
{
public:
const static int MAX_GRANTS = 64;
/**
* DL grant structure per UE
*/
struct dl_sched_grant_t {
srsran_dci_dl_nr_t dci = {};
uint8_t* data[SRSRAN_MAX_TB] = {};
srsran_softbuffer_tx_t* softbuffer_tx[SRSRAN_MAX_TB] = {};
const static int MAX_SSB = 4;
const static int MAX_GRANTS = 64;
const static int MAX_NZP_CSI_RS = 4;
struct pdcch_dl_t {
srsran_dci_cfg_nr_t dci_cfg = {};
srsran_dci_dl_nr_t dci = {};
};
/**
* DL Scheduling result per cell/carrier
*/
typedef struct {
dl_sched_grant_t pdsch[MAX_GRANTS]; //< DL Grants
uint32_t nof_grants; //< Number of DL grants
} dl_sched_t;
/**
* List of DL scheduling results, one entry per cell/carrier
*/
typedef std::vector<dl_sched_t> dl_sched_list_t;
struct pdcch_ul_t {
srsran_dci_cfg_nr_t dci_cfg = {};
srsran_dci_ul_nr_t dci = {};
};
struct pdsch_t {
srsran_sch_cfg_nr_t sch = {}; ///< PDSCH configuration
std::array<uint8_t*, SRSRAN_MAX_TB> data = {}; ///< Data pointer
};
struct ssb_t {
srsran_pbch_msg_nr_t pbch_msg = {};
};
struct dl_sched_t {
srsran::bounded_vector<ssb_t, MAX_SSB> ssb;
srsran::bounded_vector<pdcch_dl_t, MAX_GRANTS> pdcch_dl;
srsran::bounded_vector<pdcch_ul_t, MAX_GRANTS> pdcch_ul;
srsran::bounded_vector<pdsch_t, MAX_GRANTS> pdsch;
srsran::bounded_vector<srsran_csi_rs_nzp_resource_t, MAX_NZP_CSI_RS> nzp_csi_rs;
};
struct pusch_t {
srsran_sch_cfg_nr_t sch = {}; ///< PUSCH configuration
std::array<uint8_t*, SRSRAN_MAX_TB> data = {}; ///< Data pointer
std::array<srsran_softbuffer_tx_t*, SRSRAN_MAX_TB> softbuffer_tx = {}; ///< Tx Softbuffer
};
struct pucch_t {
srsran_uci_cfg_nr_t uci_cfg;
srsran_pucch_nr_resource_t resource;
};
struct ul_sched_t {
srsran::bounded_vector<pusch_t, MAX_GRANTS> pusch;
srsran::bounded_vector<pucch_t, MAX_GRANTS> pucch;
};
virtual int slot_indication(const srsran_slot_cfg_t& slot_cfg) = 0;
virtual int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) = 0;
virtual int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) = 0;
};
class stack_interface_phy_nr : public mac_interface_phy_nr, public srsran::stack_interface_phy_nr
@ -253,7 +280,6 @@ public:
srsran::unique_byte_buffer_t tb;
};
virtual int sf_indication(const uint32_t tti) = 0;
virtual int rx_data_indication(rx_data_ind_t& grant) = 0;
};

@ -119,8 +119,6 @@ struct rlc_um_nr_config_t {
***************************************************************************/
rlc_um_nr_sn_size_t sn_field_length; // Number of bits used for sequence number
uint32_t UM_Window_Size;
uint32_t mod; // Rx/Tx counter modulus
int32_t t_reassembly_ms; // Timer used by rx to detect PDU loss (ms)
};
@ -215,12 +213,8 @@ public:
cnfg.rlc_mode = rlc_mode_t::um;
if (sn_size == 6) {
cnfg.um_nr.sn_field_length = rlc_um_nr_sn_size_t::size6bits;
cnfg.um_nr.UM_Window_Size = 32;
cnfg.um_nr.mod = 64;
} else if (sn_size == 12) {
cnfg.um_nr.sn_field_length = rlc_um_nr_sn_size_t::size12bits;
cnfg.um_nr.UM_Window_Size = 2048;
cnfg.um_nr.mod = 4096;
} else {
return {};
}

@ -38,9 +38,9 @@ struct phy_cfg_nr_t {
* SSB configuration
*/
struct ssb_cfg_t {
uint32_t periodicity_ms;
std::array<bool, SRSRAN_SSB_NOF_CANDIDATES> position_in_burst;
srsran_subcarrier_spacing_t scs;
uint32_t periodicity_ms = 0;
std::array<bool, SRSRAN_SSB_NOF_CANDIDATES> position_in_burst = {};
srsran_subcarrier_spacing_t scs = srsran_subcarrier_spacing_30kHz;
};
srsran_tdd_config_nr_t tdd = {};

@ -64,7 +64,7 @@ public:
uint32_t max_nof_ctrl_symbols = 3;
int min_aggr_level = 0;
int max_aggr_level = 3;
bool adaptive_aggr_level = true;
bool adaptive_aggr_level = false;
bool pucch_mux_enabled = false;
float target_bler = 0.05;
float max_delta_dl_cqi = 5;

@ -30,14 +30,24 @@ namespace srsue {
class gw_interface_nas
{
public:
virtual int setup_if_addr(uint32_t eps_bearer_id,
uint32_t lcid,
uint8_t pdn_type,
uint32_t ip_addr,
uint8_t* ipv6_if_id,
char* err_str) = 0;
/**
* Informs GW about new EPS default bearer being created after attach accept
* along with the assigned IP address.
*/
virtual int
setup_if_addr(uint32_t eps_bearer_id, uint8_t pdn_type, uint32_t ip_addr, uint8_t* ipv6_if_id, char* err_str) = 0;
/**
* Inform GW about the deactivation of a EPS bearer, e.g. during
* detach
*/
virtual int deactivate_eps_bearer(const uint32_t eps_bearer_id) = 0;
/**
* Informs GW about new traffic flow templates and their associated EPS bearer ID
* All TFT are applied to a dedicated EPS bearer that has a linked default bearer
*/
virtual int apply_traffic_flow_template(const uint8_t& eps_bearer_id,
const uint8_t& lcid,
const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft) = 0;
typedef enum {
@ -59,7 +69,6 @@ class gw_interface_rrc
{
public:
virtual void add_mch_port(uint32_t lcid, uint32_t port) = 0;
virtual int update_lcid(uint32_t eps_bearer_id, uint32_t new_lcid) = 0;
virtual bool is_running() = 0;
};

@ -37,7 +37,10 @@ namespace srsue {
class stack_interface_rrc
{
public:
virtual srsran::tti_point get_current_tti() = 0;
virtual srsran::tti_point get_current_tti() = 0;
virtual void add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) = 0;
virtual void remove_eps_bearer(uint8_t eps_bearer_id) = 0;
virtual void reset_eps_bearers() = 0;
};
// Combined interface for PHY to access stack (MAC and RRC)

@ -34,7 +34,7 @@ public:
virtual void reestablish(uint32_t lcid) = 0;
virtual void reset() = 0;
virtual void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu, int sn = -1) = 0;
virtual void add_bearer(uint32_t lcid, srsran::pdcp_config_t cnfg) = 0;
virtual int add_bearer(uint32_t lcid, srsran::pdcp_config_t cnfg) = 0;
virtual void del_bearer(uint32_t lcid) = 0;
virtual void change_lcid(uint32_t old_lcid, uint32_t new_lcid) = 0;
virtual void config_security(uint32_t lcid, const srsran::as_security_config_t& sec_cfg) = 0;
@ -59,19 +59,23 @@ public:
virtual void notify_failure(uint32_t lcid, const srsran::pdcp_sn_vector_t& pdcp_sn) = 0;
};
class pdcp_interface_gw
// Data-plane interface for Stack after EPS bearer to LCID conversion
class pdcp_interface_stack
{
public:
virtual void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) = 0;
virtual bool is_lcid_enabled(uint32_t lcid) = 0;
virtual void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu, int sn = -1) = 0;
virtual bool is_lcid_enabled(uint32_t lcid) = 0;
};
// STACK interface for GW
class stack_interface_gw : public pdcp_interface_gw
// STACK interface for GW (based on EPS-bearer IDs)
class stack_interface_gw
{
public:
virtual bool is_registered() = 0;
virtual bool start_service_request() = 0;
virtual void write_sdu(uint32_t eps_bearer_id, srsran::unique_byte_buffer_t sdu) = 0;
///< Allow GW to query if a radio bearer for a given EPS bearer ID is currently active
virtual bool has_active_radio_bearer(uint32_t eps_bearer_id) = 0;
};
} // namespace srsue

@ -33,8 +33,8 @@ public:
virtual void reset() = 0;
virtual void reestablish() = 0;
virtual void reestablish(uint32_t lcid) = 0;
virtual void add_bearer(uint32_t lcid, const srsran::rlc_config_t& cnfg) = 0;
virtual void add_bearer_mrb(uint32_t lcid) = 0;
virtual int add_bearer(uint32_t lcid, const srsran::rlc_config_t& cnfg) = 0;
virtual int add_bearer_mrb(uint32_t lcid) = 0;
virtual void del_bearer(uint32_t lcid) = 0;
virtual void suspend_bearer(uint32_t lcid) = 0;
virtual void resume_bearer(uint32_t lcid) = 0;

@ -81,7 +81,6 @@ public:
virtual bool is_connected() = 0;
virtual void paging_completed(bool outcome) = 0;
virtual const char* get_rb_name(uint32_t lcid) = 0;
virtual uint32_t get_lcid_for_eps_bearer(const uint32_t& eps_bearer_id) = 0;
virtual bool has_nr_dc() = 0;
};
@ -109,8 +108,8 @@ public:
class rrc_nr_interface_rrc
{
public:
virtual void get_eutra_nr_capabilities(srsran::byte_buffer_t* eutra_nr_caps) = 0;
virtual void get_nr_capabilities(srsran::byte_buffer_t* nr_cap) = 0;
virtual int get_eutra_nr_capabilities(srsran::byte_buffer_t* eutra_nr_caps) = 0;
virtual int get_nr_capabilities(srsran::byte_buffer_t* nr_cap) = 0;
virtual void phy_set_cells_to_meas(uint32_t carrier_freq_r15) = 0;
virtual void phy_meas_stop() = 0;
virtual bool rrc_reconfiguration(bool endc_release_and_add_r15,

@ -66,8 +66,13 @@ SRSRAN_API int srsran_enb_dl_nr_base_zero(srsran_enb_dl_nr_t* q);
SRSRAN_API void srsran_enb_dl_nr_gen_signal(srsran_enb_dl_nr_t* q);
SRSRAN_API int
srsran_enb_dl_nr_pdcch_put(srsran_enb_dl_nr_t* q, const srsran_slot_cfg_t* slot_cfg, const srsran_dci_dl_nr_t* dci_dl);
SRSRAN_API int srsran_enb_dl_nr_pdcch_put_dl(srsran_enb_dl_nr_t* q,
const srsran_slot_cfg_t* slot_cfg,
const srsran_dci_dl_nr_t* dci_dl);
SRSRAN_API int srsran_enb_dl_nr_pdcch_put_ul(srsran_enb_dl_nr_t* q,
const srsran_slot_cfg_t* slot_cfg,
const srsran_dci_ul_nr_t* dci_ul);
SRSRAN_API int srsran_enb_dl_nr_pdsch_put(srsran_enb_dl_nr_t* q,
const srsran_slot_cfg_t* slot,
@ -77,4 +82,10 @@ SRSRAN_API int srsran_enb_dl_nr_pdsch_put(srsran_enb_dl_nr_t* q,
SRSRAN_API int
srsran_enb_dl_nr_pdsch_info(const srsran_enb_dl_nr_t* q, const srsran_sch_cfg_nr_t* cfg, char* str, uint32_t str_len);
SRSRAN_API int
srsran_enb_dl_nr_pdcch_dl_info(const srsran_enb_dl_nr_t* q, const srsran_dci_dl_nr_t* dci, char* str, uint32_t str_len);
SRSRAN_API int
srsran_enb_dl_nr_pdcch_ul_info(const srsran_enb_dl_nr_t* q, const srsran_dci_ul_nr_t* dci, char* str, uint32_t str_len);
#endif // SRSRAN_ENB_DL_NR_H

@ -148,4 +148,13 @@ SRSRAN_API int srsran_ra_ul_set_grant_uci_nr(const srsran_carrier_nr_t* carri
const srsran_uci_cfg_nr_t* uci_cfg,
srsran_sch_cfg_nr_t* pusch_cfg);
/**
* @brief Calculates frequency allocation type 1 RIV field
* @param N_rb Number of resource blocks
* @param start_rb Start resource block index
* @param length_rb Number of resource blocks
* @return The RIV field with the encoded value
*/
SRSRAN_API uint32_t srsran_ra_nr_type1_riv(uint32_t N_rb, uint32_t start_rb, uint32_t length_rb);
#endif // SRSRAN_RA_NR_H

@ -178,7 +178,7 @@ SRSRAN_API int srsran_ue_dl_nr_gen_ack(const srsran_ue_dl_nr_harq_ack_cfg_t* cfg
const srsran_pdsch_ack_nr_t* ack_info,
srsran_uci_data_nr_t* uci_data);
SRSRAN_API int srsran_ue_dl_nr_ack_insert_m(srsran_pdsch_ack_nr_t* ack_info, srsran_pdsch_ack_m_nr_t* m);
SRSRAN_API int srsran_ue_dl_nr_ack_insert_m(srsran_pdsch_ack_nr_t* ack_info, const srsran_pdsch_ack_m_nr_t* m);
SRSRAN_API uint32_t srsran_ue_dl_nr_ack_info(const srsran_pdsch_ack_nr_t* ack_info, char* str, uint32_t str_len);

@ -28,8 +28,8 @@
#include "srsran/interfaces/ue_pdcp_interfaces.h"
#include "srsran/interfaces/ue_rlc_interfaces.h"
#include "srsran/interfaces/ue_rrc_interfaces.h"
#include "srsran/upper/rlc_common.h"
#include "srsran/upper/rlc_metrics.h"
#include "srsran/rlc/rlc_common.h"
#include "srsran/rlc/rlc_metrics.h"
namespace srsran {
@ -49,12 +49,6 @@ public:
srsran::timer_handler* timers_,
uint32_t lcid_);
void init(srsue::pdcp_interface_rlc* pdcp_,
srsue::rrc_interface_rlc* rrc_,
srsue::rrc_interface_rlc* rrc_nr_,
srsran::timer_handler* timers_,
uint32_t lcid_);
void init(srsue::pdcp_interface_rlc* pdcp_,
srsue::rrc_interface_rlc* rrc_,
srsran::timer_handler* timers_,
@ -91,8 +85,8 @@ public:
void reestablish(uint32_t lcid);
void reset();
void empty_queue();
void add_bearer(uint32_t lcid, const rlc_config_t& cnfg);
void add_bearer_mrb(uint32_t lcid);
int add_bearer(uint32_t lcid, const rlc_config_t& cnfg);
int add_bearer_mrb(uint32_t lcid);
void del_bearer(uint32_t lcid);
void del_bearer_mrb(uint32_t lcid);
void suspend_bearer(uint32_t lcid);
@ -107,11 +101,10 @@ private:
byte_buffer_pool* pool = nullptr;
srsue::pdcp_interface_rlc* pdcp = nullptr;
srsue::rrc_interface_rlc* rrc = nullptr;
srsue::rrc_interface_rlc* rrc_nr = nullptr;
srsran::timer_handler* timers = nullptr;
typedef std::map<uint16_t, rlc_common*> rlc_map_t;
typedef std::pair<uint16_t, rlc_common*> rlc_map_pair_t;
typedef std::map<uint16_t, std::unique_ptr<rlc_common> > rlc_map_t;
typedef std::pair<uint16_t, std::unique_ptr<rlc_common> > rlc_map_pair_t;
rlc_map_t rlc_array, rlc_array_mrb;
pthread_rwlock_t rwlock;

@ -24,8 +24,8 @@
#include "srsran/common/buffer_pool.h"
#include "srsran/common/common.h"
#include "srsran/rlc/rlc_common.h"
#include "srsran/upper/byte_buffer_queue.h"
#include "srsran/upper/rlc_common.h"
#include <map>
#include <mutex>
#include <pthread.h>

@ -32,9 +32,9 @@
#include "srsran/common/task_scheduler.h"
#include "srsran/common/timeout.h"
#include "srsran/interfaces/pdcp_interface_types.h"
#include "srsran/rlc/rlc_am_base.h"
#include "srsran/rlc/rlc_common.h"
#include "srsran/upper/byte_buffer_queue.h"
#include "srsran/upper/rlc_am_base.h"
#include "srsran/upper/rlc_common.h"
#include <deque>
#include <list>
#include <map>
@ -376,10 +376,10 @@ private:
void reestablish();
void stop();
int write_sdu(unique_byte_buffer_t sdu);
int write_sdu(unique_byte_buffer_t sdu);
uint32_t read_pdu(uint8_t* payload, uint32_t nof_bytes);
void discard_sdu(uint32_t discard_sn);
bool sdu_queue_is_full();
void discard_sdu(uint32_t discard_sn);
bool sdu_queue_is_full();
bool has_data();
uint32_t get_buffer_state();

@ -24,8 +24,8 @@
#include "srsran/common/buffer_pool.h"
#include "srsran/common/common.h"
#include "srsran/rlc/rlc_am_base.h"
#include "srsran/upper/byte_buffer_queue.h"
#include "srsran/upper/rlc_am_base.h"
#include <map>
#include <mutex>
#include <pthread.h>

@ -24,8 +24,8 @@
#include "srsran/adt/circular_buffer.h"
#include "srsran/interfaces/rlc_interface_types.h"
#include "srsran/upper/bearer_mem_pool.h"
#include "srsran/upper/rlc_metrics.h"
#include "srsran/rlc/bearer_mem_pool.h"
#include "srsran/rlc/rlc_metrics.h"
#include <stdlib.h>
namespace srsran {

@ -24,8 +24,8 @@
#include "srsran/common/buffer_pool.h"
#include "srsran/common/common.h"
#include "srsran/rlc/rlc_common.h"
#include "srsran/upper/byte_buffer_queue.h"
#include "srsran/upper/rlc_common.h"
namespace srsue {

@ -26,8 +26,8 @@
#include "srsran/common/buffer_pool.h"
#include "srsran/common/common.h"
#include "srsran/common/task_scheduler.h"
#include "srsran/rlc/rlc_common.h"
#include "srsran/upper/byte_buffer_queue.h"
#include "srsran/upper/rlc_common.h"
#include <map>
#include <mutex>
#include <pthread.h>

@ -24,8 +24,8 @@
#include "srsran/common/buffer_pool.h"
#include "srsran/common/common.h"
#include "srsran/rlc/rlc_um_base.h"
#include "srsran/upper/byte_buffer_queue.h"
#include "srsran/upper/rlc_um_base.h"
#include <map>
#include <mutex>
#include <pthread.h>

@ -25,8 +25,8 @@
#include "srsran/common/buffer_pool.h"
#include "srsran/common/common.h"
#include "srsran/interfaces/ue_interfaces.h"
#include "srsran/rlc/rlc_um_base.h"
#include "srsran/upper/byte_buffer_queue.h"
#include "srsran/upper/rlc_um_base.h"
#include <map>
#include <mutex>
#include <pthread.h>
@ -71,6 +71,9 @@ private:
uint32_t next_so = 0; // The segment offset for the next generated PDU
uint32_t UM_Window_Size;
uint32_t mod; // Rx counter modulus
static constexpr uint32_t head_len_full = 1; // full SDU header size is always
uint32_t head_len_first = 0, head_len_segment = 0; // are computed during configure based on SN length
@ -105,6 +108,9 @@ private:
uint32_t RX_Next_Highest = 0; // the SN following the SN of the UMD PDU with the highest SN among
// received UMD PDUs. It serves as the higher edge of the reassembly window.
uint32_t UM_Window_Size;
uint32_t mod; // Rx counter modulus
// Rx window
typedef struct {
std::map<uint32_t, rlc_umd_pdu_nr_t> segments; // Map of segments with SO as key

@ -36,6 +36,9 @@ public:
stack_test_dummy() {}
srsran::tti_point get_current_tti() override { return srsran::tti_point{tti % 10240}; }
void add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) final{};
void remove_eps_bearer(uint8_t eps_bearer_id) final{};
void reset_eps_bearers() final{};
// Testing utility functions
void run_tti()

@ -35,14 +35,10 @@ class pdcp : public srsue::pdcp_interface_rlc, public srsue::pdcp_interface_rrc
public:
pdcp(srsran::task_sched_handle task_sched_, const char* logname);
virtual ~pdcp();
void init(srsue::rlc_interface_pdcp* rlc_,
srsue::rrc_interface_pdcp* rrc_,
srsue::rrc_interface_pdcp* rrc_nr_,
srsue::gw_interface_pdcp* gw_);
void init(srsue::rlc_interface_pdcp* rlc_, srsue::rrc_interface_pdcp* rrc_, srsue::gw_interface_pdcp* gw_);
void stop();
// GW interface
// Stack interface
bool is_lcid_enabled(uint32_t lcid);
// RRC interface
@ -51,7 +47,7 @@ public:
void reset() override;
void write_sdu(uint32_t lcid, unique_byte_buffer_t sdu, int sn = -1) override;
void write_sdu_mch(uint32_t lcid, unique_byte_buffer_t sdu);
void add_bearer(uint32_t lcid, pdcp_config_t cnfg) override;
int add_bearer(uint32_t lcid, pdcp_config_t cnfg) override;
void add_bearer_mrb(uint32_t lcid, pdcp_config_t cnfg);
void del_bearer(uint32_t lcid) override;
void change_lcid(uint32_t old_lcid, uint32_t new_lcid) override;
@ -84,7 +80,6 @@ public:
private:
srsue::rlc_interface_pdcp* rlc = nullptr;
srsue::rrc_interface_pdcp* rrc = nullptr;
srsue::rrc_interface_pdcp* rrc_nr = nullptr;
srsue::gw_interface_pdcp* gw = nullptr;
srsran::task_sched_handle task_sched;
srslog::basic_logger& logger;
@ -104,4 +99,5 @@ private:
};
} // namespace srsran
#endif // SRSRAN_PDCP_H

@ -23,6 +23,8 @@ add_subdirectory(common)
add_subdirectory(mac)
add_subdirectory(phy)
add_subdirectory(radio)
add_subdirectory(rlc)
add_subdirectory(pdcp)
add_subdirectory(gtpu)
add_subdirectory(srslog)
add_subdirectory(system)
add_subdirectory(upper)

@ -109,26 +109,48 @@ rach_nr_cfg_t make_mac_rach_cfg(const rach_cfg_common_s& asn1_type)
return rach_nr_cfg;
};
rlc_config_t make_rlc_config_t(const rlc_cfg_c& asn1_type)
int make_rlc_config_t(const rlc_cfg_c& asn1_type, rlc_config_t* cfg_out)
{
rlc_config_t rlc_cfg = rlc_config_t::default_rlc_um_nr_config();
rlc_cfg.rat = srsran_rat_t::nr;
switch (asn1_type.type().value) {
case rlc_cfg_c::types_opts::am:
break;
asn1::log_warning("NR RLC type %s is not supported", asn1_type.type().to_string());
return SRSRAN_ERROR;
case rlc_cfg_c::types_opts::um_bi_dir:
case rlc_cfg_c::types_opts::um_uni_dir_dl:
case rlc_cfg_c::types_opts::um_uni_dir_ul:
rlc_cfg.rlc_mode = rlc_mode_t::um;
rlc_cfg.um_nr.t_reassembly_ms = asn1_type.um_bi_dir().dl_um_rlc.t_reassembly.value;
rlc_cfg.um_nr.sn_field_length = (rlc_um_nr_sn_size_t)asn1_type.um_bi_dir().dl_um_rlc.sn_field_len.value;
rlc_cfg.um_nr.mod = (rlc_cfg.um_nr.sn_field_length == rlc_um_nr_sn_size_t::size6bits) ? 64 : 4096;
rlc_cfg.um_nr.UM_Window_Size = (rlc_cfg.um_nr.sn_field_length == rlc_um_nr_sn_size_t::size6bits) ? 32 : 2048;
rlc_cfg.um_nr.t_reassembly_ms = asn1_type.um_bi_dir().dl_um_rlc.t_reassembly.to_number();
if (asn1_type.um_bi_dir().dl_um_rlc.sn_field_len_present &&
asn1_type.um_bi_dir().ul_um_rlc.sn_field_len_present &&
asn1_type.um_bi_dir().dl_um_rlc.sn_field_len != asn1_type.um_bi_dir().ul_um_rlc.sn_field_len) {
asn1::log_warning("NR RLC sequence number length is not the same in uplink and downlink");
return SRSRAN_ERROR;
}
switch (asn1_type.um_bi_dir().dl_um_rlc.sn_field_len.value) {
case asn1::rrc_nr::sn_field_len_um_opts::options::size6:
rlc_cfg.um_nr.sn_field_length = rlc_um_nr_sn_size_t::size6bits;
break;
case asn1::rrc_nr::sn_field_len_um_opts::options::size12:
rlc_cfg.um_nr.sn_field_length = rlc_um_nr_sn_size_t::size12bits;
break;
default:
break;
}
break;
case rlc_cfg_c::types_opts::um_uni_dir_dl:
asn1::log_warning("NR RLC type %s is not supported", asn1_type.type().to_string());
return SRSRAN_ERROR;
case rlc_cfg_c::types_opts::um_uni_dir_ul:
asn1::log_warning("NR RLC type %s is not supported", asn1_type.type().to_string());
return SRSRAN_ERROR;
default:
break;
}
return rlc_cfg;
*cfg_out = rlc_cfg;
return SRSRAN_SUCCESS;
}
srsran::pdcp_config_t make_drb_pdcp_config_t(const uint8_t bearer_id, bool is_ue, const pdcp_cfg_s& pdcp_cfg)

@ -164,7 +164,9 @@ int srsran_basic_vnf::handle_sf_ind(basic_vnf_api::sf_ind_msg_t* msg)
last_sf_indication_time = msg->t1;
if (m_gnb_stack != nullptr) {
m_gnb_stack->sf_indication(msg->tti);
srsran_slot_cfg_t slot_cfg = {};
slot_cfg.idx = msg->tti;
m_gnb_stack->slot_indication(slot_cfg);
} else if (m_ue_stack != nullptr) {
m_ue_stack->sf_indication(msg->tti);
} else {

@ -0,0 +1,13 @@
#
# 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.
#
set(SOURCES gtpu.cc)
add_library(srsran_gtpu STATIC ${SOURCES})
target_link_libraries(srsran_gtpu srsran_common srsran_asn1 ${ATOMIC_LIBS})
INSTALL(TARGETS srsran_gtpu DESTINATION ${LIBRARY_DIR})

@ -0,0 +1,16 @@
#
# 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.
#
set(SOURCES pdcp.cc
pdcp_entity_base.cc
pdcp_entity_lte.cc
pdcp_entity_nr.cc)
add_library(srsran_pdcp STATIC ${SOURCES})
target_link_libraries(srsran_pdcp srsran_common srsran_asn1 ${ATOMIC_LIBS})
INSTALL(TARGETS srsran_pdcp DESTINATION ${LIBRARY_DIR})

@ -39,15 +39,6 @@ pdcp::~pdcp()
pdcp_array_mrb.clear();
}
void pdcp::init(srsue::rlc_interface_pdcp* rlc_,
srsue::rrc_interface_pdcp* rrc_,
srsue::rrc_interface_pdcp* rrc_nr_,
srsue::gw_interface_pdcp* gw_)
{
init(rlc_, rrc_, gw_);
rrc_nr = rrc_nr_;
}
void pdcp::init(srsue::rlc_interface_pdcp* rlc_, srsue::rrc_interface_pdcp* rrc_, srsue::gw_interface_pdcp* gw_)
{
rlc = rlc_;
@ -97,7 +88,7 @@ void pdcp::write_sdu(uint32_t lcid, unique_byte_buffer_t sdu, int sn)
if (valid_lcid(lcid)) {
pdcp_array.at(lcid)->write_sdu(std::move(sdu), sn);
} else {
logger.warning("Writing sdu: lcid=%d. Deallocating sdu", lcid);
logger.warning("LCID %d doesn't exist. Deallocating SDU", lcid);
}
}
@ -108,39 +99,40 @@ void pdcp::write_sdu_mch(uint32_t lcid, unique_byte_buffer_t sdu)
}
}
void pdcp::add_bearer(uint32_t lcid, pdcp_config_t cfg)
int pdcp::add_bearer(uint32_t lcid, pdcp_config_t cfg)
{
if (not valid_lcid(lcid)) {
std::unique_ptr<pdcp_entity_base> entity;
// For now we create an pdcp entity lte for nr due to it's maturity
if (cfg.rat == srsran::srsran_rat_t::lte) {
entity.reset(new pdcp_entity_lte{rlc, rrc, gw, task_sched, logger, lcid});
} else if (cfg.rat == srsran::srsran_rat_t::nr) {
if (rrc_nr == nullptr) {
logger.warning("Cannot add PDCP entity - missing rrc_nr parent pointer");
return;
}
entity.reset(new pdcp_entity_lte{rlc, rrc_nr, gw, task_sched, logger, lcid});
}
if (valid_lcid(lcid)) {
logger.error("Bearer %s already configured.", rrc->get_rb_name(lcid));
return SRSRAN_ERROR;
}
if (not entity->configure(cfg)) {
logger.error("Can not configure PDCP entity");
return;
}
std::unique_ptr<pdcp_entity_base> entity;
if (not pdcp_array.insert(std::make_pair(lcid, std::move(entity))).second) {
logger.error("Error inserting PDCP entity in to array.");
return;
}
logger.info(
"Add %s (lcid=%d, bearer_id=%d, sn_len=%dbits)", rrc->get_rb_name(lcid), lcid, cfg.bearer_id, cfg.sn_len);
{
std::lock_guard<std::mutex> lock(cache_mutex);
valid_lcids_cached.insert(lcid);
}
} else {
logger.info("Bearer %s already configured.", rrc->get_rb_name(lcid));
// For now we create an pdcp entity lte for nr due to it's maturity
if (cfg.rat == srsran::srsran_rat_t::lte) {
entity.reset(new pdcp_entity_lte{rlc, rrc, gw, task_sched, logger, lcid});
} else if (cfg.rat == srsran::srsran_rat_t::nr) {
entity.reset(new pdcp_entity_lte{rlc, rrc, gw, task_sched, logger, lcid});
}
if (not entity->configure(cfg)) {
logger.error("Can not configure PDCP entity");
return SRSRAN_ERROR;
}
if (not pdcp_array.insert(std::make_pair(lcid, std::move(entity))).second) {
logger.error("Error inserting PDCP entity in to array.");
return SRSRAN_ERROR;
}
{
std::lock_guard<std::mutex> lock(cache_mutex);
valid_lcids_cached.insert(lcid);
}
logger.info("Add %s (lcid=%d, bearer_id=%d, sn_len=%dbits)", rrc->get_rb_name(lcid), lcid, cfg.bearer_id, cfg.sn_len);
return SRSRAN_SUCCESS;
}
void pdcp::add_bearer_mrb(uint32_t lcid, pdcp_config_t cfg)
@ -286,7 +278,7 @@ void pdcp::write_pdu(uint32_t lcid, unique_byte_buffer_t pdu)
if (valid_lcid(lcid)) {
pdcp_array.at(lcid)->write_pdu(std::move(pdu));
} else {
logger.warning("Writing pdu: lcid=%d. Deallocating pdu", lcid);
logger.warning("Dropping PDU, lcid=%d doesnt exists", lcid);
}
}

@ -189,20 +189,15 @@ int srsran_enb_dl_nr_base_zero(srsran_enb_dl_nr_t* q)
return SRSRAN_SUCCESS;
}
int srsran_enb_dl_nr_pdcch_put(srsran_enb_dl_nr_t* q,
const srsran_slot_cfg_t* slot_cfg,
const srsran_dci_dl_nr_t* dci_dl)
static int
enb_dl_nr_pdcch_put_msg(srsran_enb_dl_nr_t* q, const srsran_slot_cfg_t* slot_cfg, const srsran_dci_msg_nr_t* dci_msg)
{
if (q == NULL || slot_cfg == NULL || dci_dl == NULL) {
return SRSRAN_ERROR_INVALID_INPUTS;
}
if (dci_dl->ctx.coreset_id >= SRSRAN_UE_DL_NR_MAX_NOF_CORESET ||
!q->pdcch_cfg.coreset_present[dci_dl->ctx.coreset_id]) {
ERROR("Invalid CORESET ID %d", dci_dl->ctx.coreset_id);
if (dci_msg->ctx.coreset_id >= SRSRAN_UE_DL_NR_MAX_NOF_CORESET ||
!q->pdcch_cfg.coreset_present[dci_msg->ctx.coreset_id]) {
ERROR("Invalid CORESET ID %d", dci_msg->ctx.coreset_id);
return SRSRAN_ERROR;
}
srsran_coreset_t* coreset = &q->pdcch_cfg.coreset[dci_dl->ctx.coreset_id];
srsran_coreset_t* coreset = &q->pdcch_cfg.coreset[dci_msg->ctx.coreset_id];
if (srsran_pdcch_nr_set_carrier(&q->pdcch, &q->carrier, coreset) < SRSRAN_SUCCESS) {
ERROR("Error setting PDCCH carrier/CORESET");
@ -210,11 +205,31 @@ int srsran_enb_dl_nr_pdcch_put(srsran_enb_dl_nr_t* q,
}
// Put DMRS
if (srsran_dmrs_pdcch_put(&q->carrier, coreset, slot_cfg, &dci_dl->ctx.location, q->sf_symbols[0]) < SRSRAN_SUCCESS) {
if (srsran_dmrs_pdcch_put(&q->carrier, coreset, slot_cfg, &dci_msg->ctx.location, q->sf_symbols[0]) <
SRSRAN_SUCCESS) {
ERROR("Error putting PDCCH DMRS");
return SRSRAN_ERROR;
}
// PDCCH Encode
if (srsran_pdcch_nr_encode(&q->pdcch, dci_msg, q->sf_symbols[0]) < SRSRAN_SUCCESS) {
ERROR("Error encoding PDCCH");
return SRSRAN_ERROR;
}
INFO("DCI DL NR: L=%d; ncce=%d;", dci_msg->ctx.location.L, dci_msg->ctx.location.ncce);
return SRSRAN_SUCCESS;
}
int srsran_enb_dl_nr_pdcch_put_dl(srsran_enb_dl_nr_t* q,
const srsran_slot_cfg_t* slot_cfg,
const srsran_dci_dl_nr_t* dci_dl)
{
if (q == NULL || slot_cfg == NULL || dci_dl == NULL) {
return SRSRAN_ERROR_INVALID_INPUTS;
}
// Pack DCI
srsran_dci_msg_nr_t dci_msg = {};
if (srsran_dci_nr_dl_pack(&q->dci, dci_dl, &dci_msg) < SRSRAN_SUCCESS) {
@ -222,15 +237,29 @@ int srsran_enb_dl_nr_pdcch_put(srsran_enb_dl_nr_t* q,
return SRSRAN_ERROR;
}
// PDCCH Encode
if (srsran_pdcch_nr_encode(&q->pdcch, &dci_msg, q->sf_symbols[0]) < SRSRAN_SUCCESS) {
ERROR("Error encoding PDCCH");
INFO("DCI DL NR: L=%d; ncce=%d;", dci_dl->ctx.location.L, dci_dl->ctx.location.ncce);
return enb_dl_nr_pdcch_put_msg(q, slot_cfg, &dci_msg);
}
int srsran_enb_dl_nr_pdcch_put_ul(srsran_enb_dl_nr_t* q,
const srsran_slot_cfg_t* slot_cfg,
const srsran_dci_ul_nr_t* dci_ul)
{
if (q == NULL || slot_cfg == NULL || dci_ul == NULL) {
return SRSRAN_ERROR_INVALID_INPUTS;
}
// Pack DCI
srsran_dci_msg_nr_t dci_msg = {};
if (srsran_dci_nr_ul_pack(&q->dci, dci_ul, &dci_msg) < SRSRAN_SUCCESS) {
ERROR("Error packing UL DCI");
return SRSRAN_ERROR;
}
INFO("DCI DL NR: L=%d; ncce=%d;", dci_dl->ctx.location.L, dci_dl->ctx.location.ncce);
INFO("DCI DL NR: L=%d; ncce=%d;", dci_ul->ctx.location.L, dci_ul->ctx.location.ncce);
return SRSRAN_SUCCESS;
return enb_dl_nr_pdcch_put_msg(q, slot_cfg, &dci_msg);
}
int srsran_enb_dl_nr_pdsch_put(srsran_enb_dl_nr_t* q,
@ -261,3 +290,29 @@ int srsran_enb_dl_nr_pdsch_info(const srsran_enb_dl_nr_t* q,
return len;
}
int srsran_enb_dl_nr_pdcch_dl_info(const srsran_enb_dl_nr_t* q,
const srsran_dci_dl_nr_t* dci,
char* str,
uint32_t str_len)
{
int len = 0;
// Append PDCCH info
len += srsran_dci_dl_nr_to_str(&q->dci, dci, &str[len], str_len - len);
return len;
}
int srsran_enb_dl_nr_pdcch_ul_info(const srsran_enb_dl_nr_t* q,
const srsran_dci_ul_nr_t* dci,
char* str,
uint32_t str_len)
{
int len = 0;
// Append PDCCH info
len += srsran_dci_ul_nr_to_str(&q->dci, dci, &str[len], str_len - len);
return len;
}

@ -328,3 +328,8 @@ int srsran_ra_dl_nr_freq(const srsran_carrier_nr_t* carrier,
ERROR("Unhandled case");
return SRSRAN_ERROR;
}
uint32_t srsran_ra_nr_type1_riv(uint32_t N_prb, uint32_t start_rb, uint32_t length_rb)
{
return ra_helper_from_s_and_l(N_prb, start_rb, length_rb);
}

@ -82,6 +82,14 @@ static inline void ra_helper_compute_s_and_l(uint32_t N, uint32_t v, uint32_t* S
}
}
static inline uint32_t ra_helper_from_s_and_l(uint32_t N, uint32_t S, uint32_t L)
{
if ((L - 1) <= N / 2) {
return N * (L - 1) + S;
}
return N * (N - L + 1) + (N - 1 - S);
}
static int ra_helper_freq_type1(uint32_t N_bwp_size, uint32_t riv, srsran_sch_grant_nr_t* grant)
{
uint32_t start = 0;

@ -42,18 +42,18 @@ private:
Debug("Making USRP object with args '" << dev_addr.to_string() << "'");
UHD_SAFE_C_SAVE_ERROR(this, usrp = uhd::usrp::multi_usrp::make(dev_addr);)
SRSRAN_UHD_SAFE_C_LOG_ERROR(usrp = uhd::usrp::multi_usrp::make(dev_addr);)
}
uhd_error set_tx_subdev(const std::string& string)
{
Info("Setting tx_subdev_spec to '" << string << "'");
UHD_SAFE_C_SAVE_ERROR(this, usrp->set_tx_subdev_spec(string);)
SRSRAN_UHD_SAFE_C_LOG_ERROR(usrp->set_tx_subdev_spec(string);)
}
uhd_error set_rx_subdev(const std::string& string)
{
Info("Setting rx_subdev_spec to '" << string << "'");
UHD_SAFE_C_SAVE_ERROR(this, usrp->set_rx_subdev_spec(string);)
SRSRAN_UHD_SAFE_C_LOG_ERROR(usrp->set_rx_subdev_spec(string);)
}
uhd_error test_ad936x_device(uint32_t nof_channels)
@ -101,7 +101,7 @@ private:
}
if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT) {
last_error = md.strerror();
Error(md.strerror());
return UHD_ERROR_IO;
}
@ -245,9 +245,8 @@ public:
// Otherwise, close USRP and open again
usrp = nullptr;
Warning("Failed to open Rx stream '" << last_error << "', trying to open device again. " << ntrials
<< " trials left. Waiting for " << FE_RX_RESET_SLEEP_TIME_MS.count()
<< " ms");
Warning("Failed to open Rx stream, trying to open device again. "
<< ntrials << " trials left. Waiting for " << FE_RX_RESET_SLEEP_TIME_MS.count() << " ms");
// Sleep
std::this_thread::sleep_for(FE_RX_RESET_SLEEP_TIME_MS);
@ -263,103 +262,101 @@ public:
uhd_error get_mboard_name(std::string& mboard_name) override
{
UHD_SAFE_C_SAVE_ERROR(this, mboard_name = usrp->get_mboard_name();)
SRSRAN_UHD_SAFE_C_LOG_ERROR(mboard_name = usrp->get_mboard_name();)
}
uhd_error get_mboard_sensor_names(std::vector<std::string>& sensors) override
{
UHD_SAFE_C_SAVE_ERROR(this, sensors = usrp->get_mboard_sensor_names();)
SRSRAN_UHD_SAFE_C_LOG_ERROR(sensors = usrp->get_mboard_sensor_names();)
}
uhd_error get_rx_sensor_names(std::vector<std::string>& sensors) override
{
UHD_SAFE_C_SAVE_ERROR(this, sensors = usrp->get_rx_sensor_names();)
SRSRAN_UHD_SAFE_C_LOG_ERROR(sensors = usrp->get_rx_sensor_names();)
}
uhd_error get_sensor(const std::string& sensor_name, double& sensor_value) override
{
UHD_SAFE_C_SAVE_ERROR(this, sensor_value = usrp->get_mboard_sensor(sensor_name).to_real();)
SRSRAN_UHD_SAFE_C_LOG_ERROR(sensor_value = usrp->get_mboard_sensor(sensor_name).to_real();)
}
uhd_error get_sensor(const std::string& sensor_name, bool& sensor_value) override
{
UHD_SAFE_C_SAVE_ERROR(this, sensor_value = usrp->get_mboard_sensor(sensor_name).to_bool();)
SRSRAN_UHD_SAFE_C_LOG_ERROR(sensor_value = usrp->get_mboard_sensor(sensor_name).to_bool();)
}
uhd_error get_rx_sensor(const std::string& sensor_name, bool& sensor_value) override
{
UHD_SAFE_C_SAVE_ERROR(this, sensor_value = usrp->get_rx_sensor(sensor_name).to_bool();)
SRSRAN_UHD_SAFE_C_LOG_ERROR(sensor_value = usrp->get_rx_sensor(sensor_name).to_bool();)
}
uhd_error set_time_unknown_pps(const uhd::time_spec_t& timespec) override
{
Debug("Setting Time at next PPS...");
UHD_SAFE_C_SAVE_ERROR(this, usrp->set_time_unknown_pps(timespec);)
SRSRAN_UHD_SAFE_C_LOG_ERROR(usrp->set_time_unknown_pps(timespec);)
}
uhd_error get_time_now(uhd::time_spec_t& timespec) override
{
UHD_SAFE_C_SAVE_ERROR(this, timespec = usrp->get_time_now();)
SRSRAN_UHD_SAFE_C_LOG_ERROR(timespec = usrp->get_time_now();)
}
uhd_error set_sync_source(const std::string& sync_source, const std::string& clock_source) override
{
Debug("Setting PPS source to '" << sync_source << "' and clock source to '" << clock_source << "'");
#if UHD_VERSION < 3140099
UHD_SAFE_C_SAVE_ERROR(this, usrp->set_clock_source(clock_source); usrp->set_time_source(sync_source);)
SRSRAN_UHD_SAFE_C_LOG_ERROR(usrp->set_clock_source(clock_source); usrp->set_time_source(sync_source);)
#else
UHD_SAFE_C_SAVE_ERROR(this, usrp->set_sync_source(clock_source, sync_source);)
SRSRAN_UHD_SAFE_C_LOG_ERROR(usrp->set_sync_source(clock_source, sync_source);)
#endif
}
uhd_error get_gain_range(uhd::gain_range_t& tx_gain_range, uhd::gain_range_t& rx_gain_range) override
{
UHD_SAFE_C_SAVE_ERROR(this, tx_gain_range = usrp->get_tx_gain_range(); rx_gain_range = usrp->get_rx_gain_range();)
SRSRAN_UHD_SAFE_C_LOG_ERROR(tx_gain_range = usrp->get_tx_gain_range(); rx_gain_range = usrp->get_rx_gain_range();)
}
uhd_error set_master_clock_rate(double rate) override
{
Debug("Setting master clock rate to " << rate / 1e6 << " MHz");
UHD_SAFE_C_SAVE_ERROR(this, usrp->set_master_clock_rate(rate);)
SRSRAN_UHD_SAFE_C_LOG_ERROR(usrp->set_master_clock_rate(rate);)
}
uhd_error set_rx_rate(double rate) override
{
Debug("Setting Rx Rate to " << rate / 1e6 << "MHz");
UHD_SAFE_C_SAVE_ERROR(this, usrp->set_rx_rate(rate);)
SRSRAN_UHD_SAFE_C_LOG_ERROR(usrp->set_rx_rate(rate);)
}
uhd_error set_tx_rate(double rate) override
{
Debug("Setting Tx Rate to " << rate / 1e6 << "MHz");
UHD_SAFE_C_SAVE_ERROR(this, usrp->set_tx_rate(rate);)
SRSRAN_UHD_SAFE_C_LOG_ERROR(usrp->set_tx_rate(rate);)
}
uhd_error set_command_time(const uhd::time_spec_t& timespec) override
{
UHD_SAFE_C_SAVE_ERROR(this, usrp->set_command_time(timespec);)
SRSRAN_UHD_SAFE_C_LOG_ERROR(usrp->set_command_time(timespec);)
}
uhd_error get_rx_stream(size_t& max_num_samps) override
{
Debug("Creating Rx stream");
UHD_SAFE_C_SAVE_ERROR(
this, rx_stream = nullptr; rx_stream = usrp->get_rx_stream(stream_args);
max_num_samps = rx_stream->get_max_num_samps();
if (max_num_samps == 0UL) {
last_error = "The maximum number of receive samples is zero.";
return UHD_ERROR_VALUE;
})
SRSRAN_UHD_SAFE_C_LOG_ERROR(rx_stream = nullptr; rx_stream = usrp->get_rx_stream(stream_args);
max_num_samps = rx_stream->get_max_num_samps();
if (max_num_samps == 0UL) {
Error("The maximum number of receive samples is zero.");
return UHD_ERROR_VALUE;
})
}
uhd_error get_tx_stream(size_t& max_num_samps) override
{
Debug("Creating Tx stream");
UHD_SAFE_C_SAVE_ERROR(
this, tx_stream = nullptr; tx_stream = usrp->get_tx_stream(stream_args);
max_num_samps = tx_stream->get_max_num_samps();
if (max_num_samps == 0UL) {
last_error = "The maximum number of transmit samples is zero.";
return UHD_ERROR_VALUE;
})
SRSRAN_UHD_SAFE_C_LOG_ERROR(tx_stream = nullptr; tx_stream = usrp->get_tx_stream(stream_args);
max_num_samps = tx_stream->get_max_num_samps();
if (max_num_samps == 0UL) {
Error("The maximum number of transmit samples is zero.");
return UHD_ERROR_VALUE;
})
}
uhd_error set_tx_gain(size_t ch, double gain) override
{
Debug("Setting channel " << ch << " Tx gain to " << gain << " dB");
UHD_SAFE_C_SAVE_ERROR(this, usrp->set_tx_gain(gain, ch);)
SRSRAN_UHD_SAFE_C_LOG_ERROR(usrp->set_tx_gain(gain, ch);)
}
uhd_error set_rx_gain(size_t ch, double gain) override
{
Debug("Setting channel " << ch << " Rx gain to " << gain << " dB");
UHD_SAFE_C_SAVE_ERROR(this, usrp->set_rx_gain(gain, ch);)
SRSRAN_UHD_SAFE_C_LOG_ERROR(usrp->set_rx_gain(gain, ch);)
}
uhd_error get_rx_gain(double& gain) override { UHD_SAFE_C_SAVE_ERROR(this, gain = usrp->get_rx_gain();) }
uhd_error get_tx_gain(double& gain) override { UHD_SAFE_C_SAVE_ERROR(this, gain = usrp->get_tx_gain();) }
uhd_error get_rx_gain(double& gain) override { SRSRAN_UHD_SAFE_C_LOG_ERROR(gain = usrp->get_rx_gain();) }
uhd_error get_tx_gain(double& gain) override { SRSRAN_UHD_SAFE_C_LOG_ERROR(gain = usrp->get_tx_gain();) }
uhd_error set_tx_freq(uint32_t ch, double target_freq, double& actual_freq) override
{
Debug("Setting channel " << ch << " Tx frequency to " << target_freq / 1e6 << " MHz");
@ -378,8 +375,8 @@ public:
tune_request.dsp_freq_policy = uhd::tune_request_t::POLICY_AUTO;
}
UHD_SAFE_C_SAVE_ERROR(this, uhd::tune_result_t tune_result = usrp->set_tx_freq(tune_request, ch);
actual_freq = tune_result.target_rf_freq;)
SRSRAN_UHD_SAFE_C_LOG_ERROR(uhd::tune_result_t tune_result = usrp->set_tx_freq(tune_request, ch);
actual_freq = tune_result.target_rf_freq;)
}
uhd_error set_rx_freq(uint32_t ch, double target_freq, double& actual_freq) override
{
@ -399,8 +396,8 @@ public:
tune_request.dsp_freq_policy = uhd::tune_request_t::POLICY_AUTO;
}
UHD_SAFE_C_SAVE_ERROR(this, uhd::tune_result_t tune_result = usrp->set_rx_freq(tune_request, ch);
actual_freq = tune_result.target_rf_freq;)
SRSRAN_UHD_SAFE_C_LOG_ERROR(uhd::tune_result_t tune_result = usrp->set_rx_freq(tune_request, ch);
actual_freq = tune_result.target_rf_freq;)
}
};

@ -199,11 +199,6 @@ void suppress_handler(const char* x)
static cf_t zero_mem[64 * 1024] = {};
#define print_usrp_error(h) \
do { \
ERROR("USRP reported the following error: %s", h->uhd->last_error.c_str()); \
} while (false)
static void log_overflow(rf_uhd_handler_t* h)
{
if (h->tx_state == RF_UHD_IMP_TX_STATE_BURST) {
@ -252,8 +247,6 @@ static void log_underflow(rf_uhd_handler_t* h)
static void log_rx_error(rf_uhd_handler_t* h)
{
if (h->uhd_error_handler) {
ERROR("USRP reported the following error: %s", h->uhd->last_error.c_str());
srsran_rf_error_t error;
bzero(&error, sizeof(srsran_rf_error_t));
error.type = srsran_rf_error_t::SRSRAN_RF_ERROR_RX;
@ -281,7 +274,6 @@ static void* async_thread(void* h)
if (handler->uhd->is_tx_ready()) {
lock.unlock();
if (handler->uhd->recv_async_msg(md, RF_UHD_IMP_ASYNCH_MSG_TIMEOUT_S, valid) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return nullptr;
}
@ -378,7 +370,6 @@ static int set_time_to_gps_time(rf_uhd_handler_t* handler)
std::vector<std::string> sensors;
if (handler->uhd->get_mboard_sensor_names(sensors) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
@ -404,14 +395,12 @@ static int set_time_to_gps_time(rf_uhd_handler_t* handler)
// Get actual sensor value
double frac_secs = 0.0;
if (handler->uhd->get_sensor(sensor_name, frac_secs) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
// Get time and set
printf("Setting USRP time to %fs\n", frac_secs);
if (handler->uhd->set_time_unknown_pps(uhd::time_spec_t(frac_secs)) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
@ -432,13 +421,11 @@ static int wait_sensor_locked(rf_uhd_handler_t* handler,
if (is_mboard) {
// motherboard sensor
if (handler->uhd->get_mboard_sensor_names(sensors) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
} else {
// daughterboard sensor
if (handler->uhd->get_rx_sensor_names(sensors) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
}
@ -466,12 +453,10 @@ static int wait_sensor_locked(rf_uhd_handler_t* handler,
// Get actual sensor value
if (is_mboard) {
if (handler->uhd->get_sensor(sensor_name, is_locked) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
} else {
if (handler->uhd->get_rx_sensor(sensor_name, is_locked) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
}
@ -519,7 +504,6 @@ static inline int rf_uhd_start_rx_stream_unsafe(rf_uhd_handler_t* handler)
// Issue stream command
if (handler->uhd->start_rx_stream(RF_UHD_IMP_STREAM_DELAY_S) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
@ -546,7 +530,6 @@ static inline int rf_uhd_stop_rx_stream_unsafe(rf_uhd_handler_t* handler)
// Issue stream command
if (handler->uhd->stop_rx_stream() != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
@ -588,7 +571,6 @@ void rf_uhd_flush_buffer(void* h)
do {
if (handler->uhd->receive(data, handler->rx_nof_samples, md, 0.0, false, rxd_samples) != UHD_ERROR_NONE) {
log_rx_error(handler);
print_usrp_error(handler);
return;
}
} while (rxd_samples > 0 and md.error_code == uhd::rx_metadata_t::ERROR_CODE_NONE);
@ -773,7 +755,6 @@ static int uhd_init(rf_uhd_handler_t* handler, char* args, uint32_t nof_channels
// Make USRP
if (handler->uhd->usrp_make(device_addr, nof_channels) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
@ -794,7 +775,6 @@ static int uhd_init(rf_uhd_handler_t* handler, char* args, uint32_t nof_channels
if (handler->devname.empty()) {
std::string mboard_name;
if (handler->uhd->get_mboard_name(mboard_name) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
@ -819,7 +799,6 @@ static int uhd_init(rf_uhd_handler_t* handler, char* args, uint32_t nof_channels
// Set sync source
if (handler->uhd->set_sync_source(sync_src, clock_src) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
@ -846,11 +825,9 @@ static int uhd_init(rf_uhd_handler_t* handler, char* args, uint32_t nof_channels
// Set default Tx/Rx rates
if (handler->uhd->set_rx_rate(handler->rx_rate) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
if (handler->uhd->set_tx_rate(handler->tx_rate) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
@ -860,12 +837,10 @@ static int uhd_init(rf_uhd_handler_t* handler, char* args, uint32_t nof_channels
}
if (handler->uhd->get_rx_stream(handler->rx_nof_samples) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
if (handler->uhd->get_tx_stream(handler->tx_nof_samples) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
@ -874,7 +849,6 @@ static int uhd_init(rf_uhd_handler_t* handler, char* args, uint32_t nof_channels
for (uint32_t i = 0; i < nof_channels; i++) {
if (std::isnormal(handler->rx_freq[i])) {
if (handler->uhd->set_rx_freq(i, handler->rx_freq[i], handler->rx_freq[i]) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
rf_uhd_rx_wait_lo_locked(handler);
@ -884,7 +858,6 @@ static int uhd_init(rf_uhd_handler_t* handler, char* args, uint32_t nof_channels
for (uint32_t i = 0; i < nof_channels; i++) {
if (std::isnormal(handler->tx_freq[i])) {
if (handler->uhd->set_tx_freq(i, handler->tx_freq[i], handler->tx_freq[i]) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
}
@ -894,7 +867,6 @@ static int uhd_init(rf_uhd_handler_t* handler, char* args, uint32_t nof_channels
uhd::gain_range_t tx_gain_range;
uhd::gain_range_t rx_gain_range;
if (handler->uhd->get_gain_range(tx_gain_range, rx_gain_range) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
handler->info.min_tx_gain = tx_gain_range.start();
@ -915,7 +887,6 @@ static int uhd_init(rf_uhd_handler_t* handler, char* args, uint32_t nof_channels
// Restore priorities
if (uhd_set_thread_priority(0, false) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
@ -974,9 +945,7 @@ static inline void rf_uhd_set_master_clock_rate_unsafe(rf_uhd_handler_t* handler
{
// Set master clock rate if it is allowed and change is required
if (handler->dynamic_master_rate and handler->current_master_clock != rate) {
if (handler->uhd->set_master_clock_rate(rate) != UHD_ERROR_NONE) {
print_usrp_error(handler);
}
handler->uhd->set_master_clock_rate(rate);
handler->current_master_clock = rate;
}
}
@ -999,7 +968,6 @@ static inline int rf_uhd_imp_end_burst(rf_uhd_handler_t* handler)
// Actual base-band transmission
if (handler->uhd->send(buffs_ptr, 0, md, RF_UHD_IMP_TRX_TIMEOUT_S, txd_samples) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
@ -1034,7 +1002,6 @@ double rf_uhd_set_rx_srate(void* h, double freq)
if (handler->nof_rx_channels > 1) {
uhd::time_spec_t timespec;
if (handler->uhd->get_time_now(timespec) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
timespec += RF_UHD_IMP_TIMED_COMMAND_DELAY_S;
@ -1043,13 +1010,11 @@ double rf_uhd_set_rx_srate(void* h, double freq)
// Set RX rate
if (handler->uhd->set_rx_rate(freq) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
if (RF_UHD_IMP_PROHIBITED_STREAM_REMAKE.count(handler->devname) == 0) {
if (handler->uhd->get_rx_stream(handler->rx_nof_samples) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
}
@ -1088,7 +1053,6 @@ double rf_uhd_set_tx_srate(void* h, double freq)
if (handler->nof_tx_channels > 1) {
uhd::time_spec_t timespec;
if (handler->uhd->get_time_now(timespec) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
timespec += RF_UHD_IMP_TIMED_COMMAND_DELAY_S;
@ -1097,13 +1061,11 @@ double rf_uhd_set_tx_srate(void* h, double freq)
// Set TX rate
if (handler->uhd->set_tx_rate(freq) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
if (RF_UHD_IMP_PROHIBITED_STREAM_REMAKE.count(handler->devname) == 0) {
if (handler->uhd->get_tx_stream(handler->tx_nof_samples) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
}
@ -1123,7 +1085,6 @@ int rf_uhd_set_rx_gain(void* h, double gain)
rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h;
for (size_t i = 0; i < handler->nof_rx_channels; i++) {
if (rf_uhd_set_rx_gain_ch(h, i, gain)) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
}
@ -1134,7 +1095,6 @@ int rf_uhd_set_rx_gain_ch(void* h, uint32_t ch, double gain)
{
rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h;
if (handler->uhd->set_rx_gain(ch, gain) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
@ -1145,7 +1105,6 @@ int rf_uhd_set_tx_gain(void* h, double gain)
rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h;
for (size_t i = 0; i < handler->nof_tx_channels; i++) {
if (rf_uhd_set_tx_gain_ch(h, i, gain)) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
}
@ -1156,7 +1115,6 @@ int rf_uhd_set_tx_gain_ch(void* h, uint32_t ch, double gain)
{
rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h;
if (handler->uhd->set_tx_gain(ch, gain) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
@ -1168,7 +1126,6 @@ double rf_uhd_get_rx_gain(void* h)
double gain = 0.0;
if (handler->uhd->get_rx_gain(gain) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
@ -1181,7 +1138,6 @@ double rf_uhd_get_tx_gain(void* h)
double gain = 0.0;
if (handler->uhd->get_tx_gain(gain) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
@ -1210,13 +1166,9 @@ static bool rf_uhd_set_freq_ch(rf_uhd_handler_t* handler, uint32_t ch, double& f
// Set frequency
if (is_tx) {
if (handler->uhd->set_tx_freq(ch, freq, curr_freq) != UHD_ERROR_NONE) {
print_usrp_error(handler);
}
handler->uhd->set_tx_freq(ch, freq, curr_freq);
} else {
if (handler->uhd->set_rx_freq(ch, freq, curr_freq) != UHD_ERROR_NONE) {
print_usrp_error(handler);
}
handler->uhd->set_rx_freq(ch, freq, curr_freq);
}
return true;
}
@ -1260,9 +1212,7 @@ void rf_uhd_get_time(void* h, time_t* secs, double* frac_secs)
{
rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h;
uhd::time_spec_t timespec;
if (handler->uhd->get_time_now(timespec) != UHD_ERROR_NONE) {
print_usrp_error(handler);
}
handler->uhd->get_time_now(timespec);
if (secs != nullptr) {
*secs = timespec.get_full_secs();
}
@ -1280,9 +1230,7 @@ void rf_uhd_sync_pps(void* h)
rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h;
uhd::time_spec_t timespec(0.0);
if (handler->uhd->set_time_unknown_pps(timespec) != UHD_ERROR_NONE) {
print_usrp_error(handler);
}
handler->uhd->set_time_unknown_pps(timespec);
}
int rf_uhd_recv_with_time(void* h, void* data, uint32_t nsamples, bool blocking, time_t* secs, double* frac_secs)
@ -1332,7 +1280,6 @@ int rf_uhd_recv_with_time_multi(void* h,
if (handler->uhd->receive(buffs_ptr, num_rx_samples, md, 1.0, false, rxd_samples) != UHD_ERROR_NONE) {
log_rx_error(handler);
print_usrp_error(handler);
return SRSRAN_ERROR;
}
@ -1426,7 +1373,6 @@ int rf_uhd_send_timed_multi(void* h,
if (is_start_of_burst) {
// It gets the USRP time for transmissions without time
if (handler->uhd->get_time_now(md.time_spec) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
@ -1508,7 +1454,6 @@ int rf_uhd_send_timed_multi(void* h,
if (handler->tx_state != RF_UHD_IMP_TX_STATE_WAIT_EOB_ACK) {
// Actual transmission
if (handler->uhd->send(buffs_ptr, tx_samples, md, RF_UHD_IMP_TRX_TIMEOUT_S, txd_samples) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}

@ -108,17 +108,16 @@ private:
// Destroy any previous USRP instance
device3 = nullptr;
UHD_SAFE_C_SAVE_ERROR(this, device3 = uhd::device3::make(dev_addr);)
SRSRAN_UHD_SAFE_C_LOG_ERROR(device3 = uhd::device3::make(dev_addr);)
}
template <class T>
uhd_error parse_param(uhd::device_addr_t& args, const std::string& param, T& value, bool pop = true)
{
UHD_SAFE_C_SAVE_ERROR(
this,
SRSRAN_UHD_SAFE_C_LOG_ERROR(
// Check if parameter exists
if (not args.has_key(param)) {
last_error = "RF-NOC requires " + param + " parameter";
Error("RF-NOC requires " + param + " parameter");
return UHD_ERROR_KEY;
}
@ -144,14 +143,14 @@ private:
// Parse number of radios
parse_param(args, "rfnoc_nof_radios", nof_radios);
if (nof_radios == 0) {
last_error = "RF-NOC Number of radios cannot be zero";
Error("RF-NOC Number of radios cannot be zero");
return UHD_ERROR_KEY;
}
// Parse number of channels per radio
parse_param(args, "rfnoc_nof_channels", nof_channels);
if (nof_channels == 0) {
last_error = "RF-NOC Number of channels cannot be zero";
Error("RF-NOC Number of channels cannot be zero");
return UHD_ERROR_KEY;
}
@ -167,8 +166,7 @@ private:
uhd_error create_control_interfaces()
{
UHD_SAFE_C_SAVE_ERROR(
this,
SRSRAN_UHD_SAFE_C_LOG_ERROR(
// Create Radio control
if (not loopback) {
radio_ctrl.resize(nof_radios);
@ -325,9 +323,7 @@ private:
nof_samples_per_packet = spp * 4 + 2 * sizeof(uint64_t);
}
UHD_SAFE_C_SAVE_ERROR(
this,
SRSRAN_UHD_SAFE_C_LOG_ERROR(
// Get Tx and Rx Graph
graph = device3->create_graph("graph");
@ -367,9 +363,7 @@ private:
nof_samples_per_packet = spp * 4 + 2 * sizeof(uint64_t);
}
UHD_SAFE_C_SAVE_ERROR(
this,
SRSRAN_UHD_SAFE_C_LOG_ERROR(
// Get Tx and Rx Graph
graph = device3->create_graph("graph");
@ -425,10 +419,10 @@ public:
// Check number of channels
if (nof_channels_ % nof_channels != 0 or nof_channels_ / nof_channels > nof_radios) {
last_error = "Number of requested channels (" + std::to_string(nof_channels_) +
") is different than the RFNOC "
"available channels (" +
std::to_string(nof_radios * nof_channels) + ")";
Error("Number of requested channels (" + std::to_string(nof_channels_) +
") is different than the RFNOC "
"available channels (" +
std::to_string(nof_radios * nof_channels) + ")");
return UHD_ERROR_VALUE;
}
@ -470,49 +464,41 @@ public:
};
uhd_error get_mboard_sensor_names(std::vector<std::string>& sensors) override
{
UHD_SAFE_C_SAVE_ERROR(
this, if (device3->get_tree()->exists(TREE_MBOARD_SENSORS)) {
sensors = device3->get_tree()->list(TREE_MBOARD_SENSORS);
})
SRSRAN_UHD_SAFE_C_LOG_ERROR(if (device3->get_tree()->exists(TREE_MBOARD_SENSORS)) {
sensors = device3->get_tree()->list(TREE_MBOARD_SENSORS);
})
}
uhd_error get_rx_sensor_names(std::vector<std::string>& sensors) override
{
UHD_SAFE_C_SAVE_ERROR(
this,
SRSRAN_UHD_SAFE_C_LOG_ERROR(
if (device3->get_tree()->exists(TREE_RX_SENSORS)) { sensors = device3->get_tree()->list(TREE_RX_SENSORS); })
}
uhd_error get_sensor(const std::string& sensor_name, double& sensor_value) override
{
UHD_SAFE_C_SAVE_ERROR(
this,
SRSRAN_UHD_SAFE_C_LOG_ERROR(
sensor_value =
device3->get_tree()->access<uhd::sensor_value_t>(TREE_MBOARD_SENSORS / sensor_name).get().to_real();)
}
uhd_error get_sensor(const std::string& sensor_name, bool& sensor_value) override
{
UHD_SAFE_C_SAVE_ERROR(
this,
SRSRAN_UHD_SAFE_C_LOG_ERROR(
sensor_value =
device3->get_tree()->access<uhd::sensor_value_t>(TREE_MBOARD_SENSORS / sensor_name).get().to_bool();)
}
uhd_error get_rx_sensor(const std::string& sensor_name, bool& sensor_value) override
{
UHD_SAFE_C_SAVE_ERROR(
this,
SRSRAN_UHD_SAFE_C_LOG_ERROR(
sensor_value = device3->get_tree()->access<uhd::sensor_value_t>(TREE_RX_SENSORS / sensor_name).get().to_bool();)
}
uhd_error set_time_unknown_pps(const uhd::time_spec_t& timespec) override
{
Info("Setting time " << timespec.get_real_secs() << " at next PPS...");
UHD_SAFE_C_SAVE_ERROR(
this,
for (auto& r
: radio_ctrl) { r->set_time_next_pps(timespec); });
SRSRAN_UHD_SAFE_C_LOG_ERROR(for (auto& r : radio_ctrl) { r->set_time_next_pps(timespec); });
}
uhd_error get_time_now(uhd::time_spec_t& timespec) override
{
UHD_SAFE_C_SAVE_ERROR(this, timespec = device3->get_tree()->access<uhd::time_spec_t>(TREE_TIME_NOW).get();
Info("-- " << timespec.get_real_secs());)
SRSRAN_UHD_SAFE_C_LOG_ERROR(timespec = device3->get_tree()->access<uhd::time_spec_t>(TREE_TIME_NOW).get();
Info("-- " << timespec.get_real_secs());)
}
uhd_error set_sync_source(const std::string& sync_source, const std::string& clock_source) override
{
@ -520,13 +506,12 @@ public:
return UHD_ERROR_NONE;
}
UHD_SAFE_C_SAVE_ERROR(
this, for (size_t radio_idx = 0; radio_idx < nof_radios; radio_idx++) {
UHD_LOG_DEBUG(radio_id[radio_idx],
"Setting PPS source to '" << sync_source << "' and clock source to '" << clock_source << "'");
radio_ctrl[radio_idx]->set_clock_source(clock_source);
radio_ctrl[radio_idx]->set_time_source(sync_source);
})
SRSRAN_UHD_SAFE_C_LOG_ERROR(for (size_t radio_idx = 0; radio_idx < nof_radios; radio_idx++) {
UHD_LOG_DEBUG(radio_id[radio_idx],
"Setting PPS source to '" << sync_source << "' and clock source to '" << clock_source << "'");
radio_ctrl[radio_idx]->set_clock_source(clock_source);
radio_ctrl[radio_idx]->set_time_source(sync_source);
})
}
uhd_error get_gain_range(uhd::gain_range_t& tx_gain_range, uhd::gain_range_t& rx_gain_range) override
{
@ -538,29 +523,27 @@ public:
uhd_error set_master_clock_rate(double rate) override { return UHD_ERROR_NONE; }
uhd_error set_rx_rate(double rate) override
{
UHD_SAFE_C_SAVE_ERROR(
this, for (size_t i = 0; i < nof_radios; i++) {
for (size_t j = 0; j < nof_channels; j++) {
UHD_LOG_DEBUG(ddc_id[i], "Setting channel " << j << " output rate to " << rate / 1e6 << " MHz");
ddc_ctrl[i]->set_arg("output_rate", std::to_string(rate), j);
}
})
SRSRAN_UHD_SAFE_C_LOG_ERROR(for (size_t i = 0; i < nof_radios; i++) {
for (size_t j = 0; j < nof_channels; j++) {
UHD_LOG_DEBUG(ddc_id[i], "Setting channel " << j << " output rate to " << rate / 1e6 << " MHz");
ddc_ctrl[i]->set_arg("output_rate", std::to_string(rate), j);
}
})
}
uhd_error set_tx_rate(double rate) override
{
UHD_SAFE_C_SAVE_ERROR(
this, for (size_t i = 0; i < nof_radios; i++) {
for (size_t j = 0; j < nof_channels; j++) {
UHD_LOG_DEBUG(duc_id[i], "Setting channel " << j << " input rate to " << rate / 1e6 << " MHz");
duc_ctrl[i]->set_arg("input_rate", std::to_string(rate), j);
}
})
SRSRAN_UHD_SAFE_C_LOG_ERROR(for (size_t i = 0; i < nof_radios; i++) {
for (size_t j = 0; j < nof_channels; j++) {
UHD_LOG_DEBUG(duc_id[i], "Setting channel " << j << " input rate to " << rate / 1e6 << " MHz");
duc_ctrl[i]->set_arg("input_rate", std::to_string(rate), j);
}
})
}
uhd_error set_command_time(const uhd::time_spec_t& timespec) override { return UHD_ERROR_NONE; }
uhd_error get_rx_stream(size_t& max_num_samps) override
{
UHD_SAFE_C_SAVE_ERROR(
this, uhd::stream_args_t stream_args("fc32", "sc16");
SRSRAN_UHD_SAFE_C_LOG_ERROR(
uhd::stream_args_t stream_args("fc32", "sc16");
stream_args.channels.resize(nof_radios * nof_channels);
@ -584,8 +567,8 @@ public:
}
uhd_error get_tx_stream(size_t& max_num_samps) override
{
UHD_SAFE_C_SAVE_ERROR(
this, uhd::stream_args_t stream_args("fc32", "sc16");
SRSRAN_UHD_SAFE_C_LOG_ERROR(
uhd::stream_args_t stream_args("fc32", "sc16");
stream_args.channels.resize(nof_radios * nof_channels);
if (spp != 0) { stream_args.args["spp"] = std::to_string(spp); }
@ -614,7 +597,7 @@ public:
uhd_error set_tx_gain(size_t ch, double gain) override
{
if (ch >= nof_channels * nof_radios) {
last_error = "Invalid channel index " + std::to_string(ch);
Error("Invalid channel index " + std::to_string(ch));
return UHD_ERROR_INDEX;
}
@ -627,12 +610,11 @@ public:
// Set the gain for the channel zero only
if (channel_idx != 0) {
last_error = "None";
return UHD_ERROR_NONE;
}
UHD_SAFE_C_SAVE_ERROR(
this, UHD_LOG_DEBUG(radio_id[radio_idx], "Setting TX Gain: " << gain << " dB...");
SRSRAN_UHD_SAFE_C_LOG_ERROR(
UHD_LOG_DEBUG(radio_id[radio_idx], "Setting TX Gain: " << gain << " dB...");
radio_ctrl[radio_idx]->set_tx_gain(gain, 0);
UHD_LOG_DEBUG(radio_id[radio_idx], "Actual TX Gain: " << radio_ctrl[radio_idx]->get_rx_gain(0) << " dB...");)
}
@ -640,7 +622,7 @@ public:
uhd_error set_rx_gain(size_t ch, double gain) override
{
if (ch >= nof_channels * nof_radios) {
last_error = "Invalid channel index " + std::to_string(ch);
Error("Invalid channel index " + std::to_string(ch));
return UHD_ERROR_INDEX;
}
@ -653,12 +635,11 @@ public:
// Set the gain for the channel zero only
if (channel_idx != 0) {
last_error = "None";
return UHD_ERROR_NONE;
}
UHD_SAFE_C_SAVE_ERROR(
this, UHD_LOG_DEBUG(radio_id[radio_idx], "Setting RX Gain: " << gain << " dB...");
SRSRAN_UHD_SAFE_C_LOG_ERROR(
UHD_LOG_DEBUG(radio_id[radio_idx], "Setting RX Gain: " << gain << " dB...");
radio_ctrl[radio_idx]->set_rx_gain(gain, 0);
UHD_LOG_DEBUG(radio_id[radio_idx], "Actual RX Gain: " << radio_ctrl[radio_idx]->get_rx_gain(0) << " dB...");)
}
@ -668,7 +649,7 @@ public:
return UHD_ERROR_NONE;
}
UHD_SAFE_C_SAVE_ERROR(this, gain = radio_ctrl[0]->get_tx_gain(0);)
SRSRAN_UHD_SAFE_C_LOG_ERROR(gain = radio_ctrl[0]->get_tx_gain(0);)
}
uhd_error get_rx_gain(double& gain) override
{
@ -676,23 +657,22 @@ public:
return UHD_ERROR_NONE;
}
UHD_SAFE_C_SAVE_ERROR(this, gain = radio_ctrl[0]->get_rx_gain(0);)
SRSRAN_UHD_SAFE_C_LOG_ERROR(gain = radio_ctrl[0]->get_rx_gain(0);)
}
uhd_error set_tx_freq(uint32_t ch, double target_freq, double& actual_freq) override
{
if (ch >= tx_freq_hz.size()) {
last_error = "Invalid channel index " + std::to_string(ch);
Error("Invalid channel index " + std::to_string(ch));
return UHD_ERROR_INDEX;
}
if (not std::isnormal(target_freq)) {
last_error = "Invalid TX frequency value " + std::to_string(target_freq) + " for channel " + std::to_string(ch);
Error("Invalid TX frequency value " + std::to_string(target_freq) + " for channel " + std::to_string(ch));
return UHD_ERROR_VALUE;
}
// Nothing to update
if (std::round(tx_freq_hz[ch]) == std::round(target_freq)) {
last_error = "None";
return UHD_ERROR_NONE;
}
@ -704,9 +684,7 @@ public:
size_t i = ch / nof_channels;
size_t j = ch % nof_channels;
UHD_SAFE_C_SAVE_ERROR(
this,
SRSRAN_UHD_SAFE_C_LOG_ERROR(
// Set Radio Tx freq
if (not std::isnormal(tx_center_freq_hz[i]) and not loopback) {
UHD_LOG_DEBUG(radio_id[i],
@ -731,18 +709,17 @@ public:
uhd_error set_rx_freq(uint32_t ch, double target_freq, double& actual_freq) override
{
if (ch >= rx_freq_hz.size()) {
last_error = "Invalid channel index " + std::to_string(ch);
Error("Invalid channel index " + std::to_string(ch));
return UHD_ERROR_INDEX;
}
if (not std::isnormal(target_freq)) {
last_error = "Invalid TX frequency value " + std::to_string(target_freq) + " for channel " + std::to_string(ch);
Error("Invalid TX frequency value " + std::to_string(target_freq) + " for channel " + std::to_string(ch));
return UHD_ERROR_VALUE;
}
// Nothing to update
if (std::round(rx_freq_hz[ch]) == std::round(target_freq)) {
last_error = "None";
return UHD_ERROR_NONE;
}
@ -754,9 +731,7 @@ public:
size_t i = ch / nof_channels;
size_t j = ch % nof_channels;
UHD_SAFE_C_SAVE_ERROR(
this,
SRSRAN_UHD_SAFE_C_LOG_ERROR(
// Set Radio Tx freq
if (not std::isnormal(rx_center_freq_hz[i]) and not loopback) {
UHD_LOG_DEBUG(radio_id[i], "Setting RX Freq: " << target_freq / 1e6 << " MHz...");

@ -25,17 +25,37 @@
#include <uhd/utils/log.hpp>
#ifdef UHD_LOG_INFO
#define Error(message) UHD_LOG_ERROR("UHD RF", message)
#define Warning(message) UHD_LOG_WARNING("UHD RF", message)
#define Info(message) UHD_LOG_INFO("UHD RF", message)
#define Debug(message) UHD_LOG_DEBUG("UHD RF", message)
#define Trace(message) UHD_LOG_TRACE("UHD RF", message)
#else
#define Error(message) UHD_LOG << message << std::endl
#define Warning(message) UHD_LOG << message << std::endl
#define Info(message) UHD_LOG << message << std::endl
#define Debug(message) UHD_LOG << message << std::endl
#define Trace(message) UHD_LOG << message << std::endl
#endif
#define SRSRAN_UHD_SAFE_C_LOG_ERROR(...) \
try { \
__VA_ARGS__ \
} catch (const uhd::exception& e) { \
Error(e.what()); \
return error_from_uhd_exception(&e); \
} catch (const boost::exception& e) { \
Error(boost::diagnostic_information(e)); \
return UHD_ERROR_BOOSTEXCEPT; \
} catch (const std::exception& e) { \
Error(e.what()); \
return UHD_ERROR_STDEXCEPT; \
} catch (...) { \
Error("Unrecognized exception caught."); \
return UHD_ERROR_UNKNOWN; \
} \
return UHD_ERROR_NONE;
#ifdef ENABLE_UHD_X300_FW_RESET
#include <uhd/transport/udp_simple.hpp>
@ -54,8 +74,7 @@ private:
#ifdef ENABLE_UHD_X300_FW_RESET
uhd_error try_usrp_x300_reset(const uhd::device_addr_t& dev_addr)
{
UHD_SAFE_C_SAVE_ERROR(
this,
SRSRAN_UHD_SAFE_C_LOG_ERROR(
// It is not possible to reset device if IP address is not provided
if (not dev_addr.has_key("addr")) { return UHD_ERROR_NONE; }
@ -118,8 +137,6 @@ protected:
}
public:
std::string last_error;
virtual uhd_error usrp_make(const uhd::device_addr_t& dev_addr, uint32_t nof_channels) = 0;
virtual uhd_error get_mboard_name(std::string& mboard_name) = 0;
virtual uhd_error get_mboard_sensor_names(std::vector<std::string>& sensors) = 0;
@ -138,19 +155,19 @@ public:
return err;
}
UHD_SAFE_C_SAVE_ERROR(this, uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
stream_cmd.time_spec = time_spec;
stream_cmd.time_spec += delay;
stream_cmd.stream_now = not std::isnormal(delay);
SRSRAN_UHD_SAFE_C_LOG_ERROR(uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
stream_cmd.time_spec = time_spec;
stream_cmd.time_spec += delay;
stream_cmd.stream_now = not std::isnormal(delay);
rx_stream->issue_stream_cmd(stream_cmd);)
rx_stream->issue_stream_cmd(stream_cmd);)
}
uhd_error stop_rx_stream()
{
Debug("Stopping Rx stream");
UHD_SAFE_C_SAVE_ERROR(this, uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
stream_cmd.stream_now = true;
rx_stream->issue_stream_cmd(stream_cmd);)
SRSRAN_UHD_SAFE_C_LOG_ERROR(uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
stream_cmd.stream_now = true;
rx_stream->issue_stream_cmd(stream_cmd);)
}
virtual uhd_error set_sync_source(const std::string& sync_source, const std::string& clock_source) = 0;
virtual uhd_error get_gain_range(uhd::gain_range_t& tx_gain_range, uhd::gain_range_t& rx_gain_range) = 0;
@ -173,12 +190,13 @@ public:
const bool one_packet,
size_t& nof_rxd_samples)
{
UHD_SAFE_C_SAVE_ERROR(this, uhd::rx_streamer::buffs_type buffs_cpp(buffs, rx_stream->get_num_channels());
nof_rxd_samples = rx_stream->recv(buffs_cpp, nsamps_per_buff, metadata, timeout, one_packet);)
SRSRAN_UHD_SAFE_C_LOG_ERROR(uhd::rx_streamer::buffs_type buffs_cpp(buffs, rx_stream->get_num_channels());
nof_rxd_samples =
rx_stream->recv(buffs_cpp, nsamps_per_buff, metadata, timeout, one_packet);)
}
virtual uhd_error recv_async_msg(uhd::async_metadata_t& async_metadata, double timeout, bool& valid)
{
UHD_SAFE_C_SAVE_ERROR(this, valid = tx_stream->recv_async_msg(async_metadata, timeout);)
SRSRAN_UHD_SAFE_C_LOG_ERROR(valid = tx_stream->recv_async_msg(async_metadata, timeout);)
}
uhd_error send(void** buffs,
const size_t nsamps_per_buff,
@ -186,8 +204,8 @@ public:
const double timeout,
size_t& nof_txd_samples)
{
UHD_SAFE_C_SAVE_ERROR(this, uhd::tx_streamer::buffs_type buffs_cpp(buffs, tx_stream->get_num_channels());
nof_txd_samples = tx_stream->send(buffs_cpp, nsamps_per_buff, metadata, timeout);)
SRSRAN_UHD_SAFE_C_LOG_ERROR(uhd::tx_streamer::buffs_type buffs_cpp(buffs, tx_stream->get_num_channels());
nof_txd_samples = tx_stream->send(buffs_cpp, nsamps_per_buff, metadata, timeout);)
}
virtual bool is_rx_ready() { return rx_stream != nullptr; }
virtual bool is_tx_ready() { return tx_stream != nullptr; }

@ -88,7 +88,6 @@ private:
if (valid) {
switch (async_metadata.event_code) {
case uhd::async_metadata_t::EVENT_CODE_BURST_ACK:
Warning("BURST ACK") break;
case uhd::async_metadata_t::EVENT_CODE_UNDERFLOW:
@ -223,16 +222,13 @@ public:
uhd::log::set_console_level(uhd::log::severity_level::trace);
if (rfnoc->usrp_make(hint, config.nof_channels * config.nof_radios) != UHD_ERROR_NONE) {
Warning(rfnoc->last_error);
return SRSRAN_ERROR;
}
if (rfnoc->set_tx_rate(config.srate_hz) != UHD_ERROR_NONE) {
Warning(rfnoc->last_error);
return SRSRAN_ERROR;
}
if (rfnoc->set_rx_rate(config.srate_hz) != UHD_ERROR_NONE) {
Warning(rfnoc->last_error);
return SRSRAN_ERROR;
}
@ -248,7 +244,6 @@ public:
}
if (rfnoc->start_rx_stream(config.init_tx_time) != UHD_ERROR_NONE) {
Warning(rfnoc->last_error);
return SRSRAN_ERROR;
}

@ -779,7 +779,7 @@ int srsran_ue_dl_nr_gen_ack(const srsran_ue_dl_nr_harq_ack_cfg_t* cfg,
return SRSRAN_ERROR;
}
int srsran_ue_dl_nr_ack_insert_m(srsran_pdsch_ack_nr_t* ack_info, srsran_pdsch_ack_m_nr_t* m)
int srsran_ue_dl_nr_ack_insert_m(srsran_pdsch_ack_nr_t* ack_info, const srsran_pdsch_ack_m_nr_t* m)
{
// Check inputs
if (ack_info == NULL || m == NULL) {

@ -18,21 +18,16 @@
# and at http://www.gnu.org/licenses/.
#
set(SOURCES gtpu.cc
pdcp.cc
pdcp_entity_base.cc
pdcp_entity_lte.cc
rlc.cc
set(SOURCES rlc.cc
rlc_tm.cc
rlc_um_base.cc
rlc_um_lte.cc
rlc_am_base.cc
rlc_am_lte.cc
pdcp_entity_nr.cc
rlc_um_nr.cc
rlc_am_nr.cc
bearer_mem_pool.cc)
add_library(srsran_upper STATIC ${SOURCES})
target_link_libraries(srsran_upper srsran_common srsran_asn1 ${ATOMIC_LIBS})
INSTALL(TARGETS srsran_upper DESTINATION ${LIBRARY_DIR})
add_library(srsran_rlc STATIC ${SOURCES})
target_link_libraries(srsran_rlc srsran_common ${ATOMIC_LIBS})
INSTALL(TARGETS srsran_rlc DESTINATION ${LIBRARY_DIR})

@ -19,11 +19,11 @@
*
*/
#include "srsran/upper/bearer_mem_pool.h"
#include "srsran/rlc/bearer_mem_pool.h"
#include "srsran/adt/pool/batch_mem_pool.h"
#include "srsran/upper/rlc_am_lte.h"
#include "srsran/upper/rlc_um_lte.h"
#include "srsran/upper/rlc_um_nr.h"
#include "srsran/rlc/rlc_am_lte.h"
#include "srsran/rlc/rlc_um_lte.h"
#include "srsran/rlc/rlc_um_nr.h"
namespace srsran {

@ -19,18 +19,17 @@
*
*/
#include "srsran/upper/rlc.h"
#include "srsran/rlc/rlc.h"
#include "srsran/common/rwlock_guard.h"
#include "srsran/upper/rlc_am_lte.h"
#include "srsran/upper/rlc_tm.h"
#include "srsran/upper/rlc_um_lte.h"
#include "srsran/upper/rlc_um_nr.h"
#include "srsran/rlc/rlc_am_lte.h"
#include "srsran/rlc/rlc_tm.h"
#include "srsran/rlc/rlc_um_lte.h"
#include "srsran/rlc/rlc_um_nr.h"
namespace srsran {
rlc::rlc(const char* logname) : logger(srslog::fetch_basic_logger(logname))
rlc::rlc(const char* logname) : logger(srslog::fetch_basic_logger(logname)), pool(byte_buffer_pool::get_instance())
{
pool = byte_buffer_pool::get_instance();
pthread_rwlock_init(&rwlock, NULL);
}
@ -38,32 +37,13 @@ rlc::~rlc()
{
// destroy all remaining entities
{
rwlock_write_guard lock(rwlock);
for (rlc_map_t::iterator it = rlc_array.begin(); it != rlc_array.end(); ++it) {
delete (it->second);
}
srsran::rwlock_write_guard lock(rwlock);
rlc_array.clear();
for (rlc_map_t::iterator it = rlc_array_mrb.begin(); it != rlc_array_mrb.end(); ++it) {
delete (it->second);
}
rlc_array_mrb.clear();
}
pthread_rwlock_destroy(&rwlock);
}
void rlc::init(srsue::pdcp_interface_rlc* pdcp_,
srsue::rrc_interface_rlc* rrc_,
srsue::rrc_interface_rlc* rrc_nr_,
srsran::timer_handler* timers_,
uint32_t lcid_)
{
init(pdcp_, rrc_, timers_, lcid_);
rrc_nr = rrc_nr_;
}
void rlc::init(srsue::pdcp_interface_rlc* pdcp_,
srsue::rrc_interface_rlc* rrc_,
srsran::timer_handler* timers_,
@ -180,11 +160,6 @@ void rlc::reset()
{
{
rwlock_write_guard lock(rwlock);
for (rlc_map_t::iterator it = rlc_array.begin(); it != rlc_array.end(); ++it) {
it->second->stop();
delete (it->second);
}
rlc_array.clear();
// the multicast bearer (MRB) is not removed here because eMBMS services continue to be streamed in idle mode (3GPP
// TS 23.246 version 14.1.0 Release 14 section 8)
@ -408,117 +383,98 @@ bool rlc::has_data(uint32_t lcid)
}
// Methods modifying the RLC array need to acquire the write-lock
void rlc::add_bearer(uint32_t lcid, const rlc_config_t& cnfg)
int rlc::add_bearer(uint32_t lcid, const rlc_config_t& cnfg)
{
rwlock_write_guard lock(rwlock);
rlc_common* rlc_entity = nullptr;
// Check this for later rrc_nr pointer access
if (cnfg.rat == srsran::srsran_rat_t::nr && rrc_nr == nullptr) {
logger.error("Cannot add/modify RLC entity - missing rrc_nr parent pointer for rat type nr");
return;
}
if (cnfg.rlc_mode != rlc_mode_t::tm and rlc_array.find(lcid) != rlc_array.end()) {
if (rlc_array[lcid]->get_mode() != cnfg.rlc_mode) {
logger.info("Switching RLC entity type. Recreating it.");
rlc_array.erase(lcid);
}
if (valid_lcid(lcid)) {
logger.error("LCID %d already exists", lcid);
return SRSRAN_ERROR;
}
std::unique_ptr<rlc_common> rlc_entity;
switch (cnfg.rlc_mode) {
case rlc_mode_t::tm:
rlc_entity = std::unique_ptr<rlc_common>(new rlc_tm(logger, lcid, pdcp, rrc));
break;
case rlc_mode_t::am:
switch (cnfg.rat) {
case srsran_rat_t::lte:
rlc_entity = std::unique_ptr<rlc_common>(new rlc_am_lte(logger, lcid, pdcp, rrc, timers));
break;
default:
logger.error("AM not supported for this RAT");
return SRSRAN_ERROR;
}
break;
case rlc_mode_t::um:
switch (cnfg.rat) {
case srsran_rat_t::lte:
rlc_entity = std::unique_ptr<rlc_common>(new rlc_um_lte(logger, lcid, pdcp, rrc, timers));
break;
case srsran_rat_t::nr:
rlc_entity = std::unique_ptr<rlc_common>(new rlc_um_nr(logger, lcid, pdcp, rrc, timers));
break;
default:
logger.error("UM not supported for this RAT");
return SRSRAN_ERROR;
}
break;
default:
logger.error("Cannot add RLC entity - invalid mode");
return SRSRAN_ERROR;
}
if (not valid_lcid(lcid)) {
switch (cnfg.rat) {
case srsran_rat_t::lte:
switch (cnfg.rlc_mode) {
case rlc_mode_t::tm:
rlc_entity = new rlc_tm(logger, lcid, pdcp, rrc);
break;
case rlc_mode_t::am:
rlc_entity = new rlc_am_lte(logger, lcid, pdcp, rrc, timers);
break;
case rlc_mode_t::um:
rlc_entity = new rlc_um_lte(logger, lcid, pdcp, rrc, timers);
break;
default:
logger.error("Cannot add RLC entity - invalid mode");
return;
}
if (rlc_entity != nullptr) {
rlc_entity->set_bsr_callback(bsr_callback);
}
break;
case srsran_rat_t::nr:
switch (cnfg.rlc_mode) {
case rlc_mode_t::tm:
rlc_entity = new rlc_tm(logger, lcid, pdcp, rrc_nr);
break;
case rlc_mode_t::um:
rlc_entity = new rlc_um_nr(logger, lcid, pdcp, rrc_nr, timers);
break;
default:
logger.error("Cannot add RLC entity - invalid mode");
return;
}
break;
default:
logger.error("RAT not supported");
return;
}
if (not rlc_array.insert(rlc_map_pair_t(lcid, rlc_entity)).second) {
logger.error("Error inserting RLC entity in to array.");
goto delete_and_exit;
}
logger.info("Added %s radio bearer with LCID %d in %s", to_string(cnfg.rat), lcid, to_string(cnfg.rlc_mode));
rlc_entity = NULL;
// make sure entity has been created
if (rlc_entity == nullptr) {
logger.error("Couldn't allocate new RLC entity");
return SRSRAN_ERROR;
}
// configure and add to array
if (cnfg.rlc_mode != rlc_mode_t::tm and rlc_array.find(lcid) != rlc_array.end()) {
if (not rlc_array.at(lcid)->configure(cnfg)) {
// configure entity
if (cnfg.rlc_mode != rlc_mode_t::tm) {
if (not rlc_entity->configure(cnfg)) {
logger.error("Error configuring RLC entity.");
goto delete_and_exit;
return SRSRAN_ERROR;
}
}
logger.info("Configured %s radio bearer with LCID %d in %s", to_string(cnfg.rat), lcid, to_string(cnfg.rlc_mode));
rlc_entity->set_bsr_callback(bsr_callback);
delete_and_exit:
if (rlc_entity) {
delete (rlc_entity);
if (not rlc_array.insert(rlc_map_pair_t(lcid, std::move(rlc_entity))).second) {
logger.error("Error inserting RLC entity in to array.");
return SRSRAN_ERROR;
}
logger.info("Added %s radio bearer with LCID %d in %s", to_string(cnfg.rat), lcid, to_string(cnfg.rlc_mode));
return SRSRAN_SUCCESS;
}
void rlc::add_bearer_mrb(uint32_t lcid)
int rlc::add_bearer_mrb(uint32_t lcid)
{
rwlock_write_guard lock(rwlock);
rlc_common* rlc_entity = NULL;
if (not valid_lcid_mrb(lcid)) {
rlc_entity = new rlc_um_lte(logger, lcid, pdcp, rrc, timers);
std::unique_ptr<rlc_common> rlc_entity =
std::unique_ptr<rlc_common>(new rlc_um_lte(logger, lcid, pdcp, rrc, timers));
// configure and add to array
if (not rlc_entity->configure(rlc_config_t::mch_config())) {
if (not rlc_entity or rlc_entity->configure(rlc_config_t::mch_config()) == false) {
logger.error("Error configuring RLC entity.");
goto delete_and_exit;
return SRSRAN_ERROR;
}
if (rlc_array_mrb.count(lcid) == 0) {
if (not rlc_array_mrb.insert(rlc_map_pair_t(lcid, rlc_entity)).second) {
if (not rlc_array_mrb.insert(rlc_map_pair_t(lcid, std::move(rlc_entity))).second) {
logger.error("Error inserting RLC entity in to array.");
goto delete_and_exit;
return SRSRAN_ERROR;
}
}
logger.warning("Added bearer MRB%d with mode RLC_UM", lcid);
return;
logger.info("Added bearer MRB%d with mode RLC_UM", lcid);
} else {
logger.warning("Bearer MRB%d already created.", lcid);
}
delete_and_exit:
if (rlc_entity != NULL) {
delete (rlc_entity);
}
return SRSRAN_SUCCESS;
}
void rlc::del_bearer(uint32_t lcid)
@ -528,7 +484,6 @@ void rlc::del_bearer(uint32_t lcid)
if (valid_lcid(lcid)) {
rlc_map_t::iterator it = rlc_array.find(lcid);
it->second->stop();
delete (it->second);
rlc_array.erase(it);
logger.info("Deleted RLC bearer with LCID %d", lcid);
} else {
@ -543,9 +498,8 @@ void rlc::del_bearer_mrb(uint32_t lcid)
if (valid_lcid_mrb(lcid)) {
rlc_map_t::iterator it = rlc_array_mrb.find(lcid);
it->second->stop();
delete (it->second);
rlc_array_mrb.erase(it);
logger.warning("Deleted RLC MRB bearer with LCID %d", lcid);
logger.info("Deleted RLC MRB bearer with LCID %d", lcid);
} else {
logger.error("Can't delete bearer with LCID %d. Bearer doesn't exist.", lcid);
}
@ -558,9 +512,9 @@ void rlc::change_lcid(uint32_t old_lcid, uint32_t new_lcid)
// make sure old LCID exists and new LCID is still free
if (valid_lcid(old_lcid) && not valid_lcid(new_lcid)) {
// insert old rlc entity into new LCID
rlc_map_t::iterator it = rlc_array.find(old_lcid);
rlc_common* rlc_entity = it->second;
if (not rlc_array.insert(rlc_map_pair_t(new_lcid, rlc_entity)).second) {
rlc_map_t::iterator it = rlc_array.find(old_lcid);
std::unique_ptr<rlc_common> rlc_entity = std::move(it->second);
if (not rlc_array.insert(rlc_map_pair_t(new_lcid, std::move(rlc_entity))).second) {
logger.error("Error inserting RLC entity into array.");
return;
}

@ -19,7 +19,7 @@
*
*/
#include "srsran/upper/rlc_am_base.h"
#include "srsran/rlc/rlc_am_base.h"
#include <sstream>
namespace srsran {

@ -19,7 +19,7 @@
*
*/
#include "srsran/upper/rlc_am_lte.h"
#include "srsran/rlc/rlc_am_lte.h"
#include "srsran/common/string_helpers.h"
#include "srsran/interfaces/ue_pdcp_interfaces.h"
#include "srsran/interfaces/ue_rrc_interfaces.h"

@ -19,7 +19,7 @@
*
*/
#include "srsran/upper/rlc_am_nr.h"
#include "srsran/rlc/rlc_am_nr.h"
#include <sstream>
namespace srsran {

@ -19,7 +19,7 @@
*
*/
#include "srsran/upper/rlc_tm.h"
#include "srsran/rlc/rlc_tm.h"
#include "srsran/common/common_lte.h"
#include "srsran/interfaces/ue_pdcp_interfaces.h"
#include "srsran/interfaces/ue_rrc_interfaces.h"

@ -19,7 +19,7 @@
*
*/
#include "srsran/upper/rlc_um_base.h"
#include "srsran/rlc/rlc_um_base.h"
#include "srsran/interfaces/ue_rrc_interfaces.h"
#include <sstream>

@ -19,7 +19,7 @@
*
*/
#include "srsran/upper/rlc_um_lte.h"
#include "srsran/rlc/rlc_um_lte.h"
#include "srsran/interfaces/ue_pdcp_interfaces.h"
#include <sstream>

@ -19,11 +19,11 @@
*
*/
#include "srsran/upper/rlc_um_nr.h"
#include "srsran/rlc/rlc_um_nr.h"
#include "srsran/interfaces/ue_pdcp_interfaces.h"
#include <sstream>
#define RX_MOD_NR_BASE(x) (((x)-RX_Next_Highest - cfg.um_nr.UM_Window_Size) % cfg.um_nr.mod)
#define RX_MOD_NR_BASE(x) (((x)-RX_Next_Highest - UM_Window_Size) % mod)
namespace srsran {
@ -103,10 +103,8 @@ bool rlc_um_nr::rlc_um_nr_tx::configure(const rlc_config_t& cnfg_, std::string r
{
cfg = cnfg_;
if (cfg.um_nr.mod == 0) {
logger.error("Error configuring %s RLC UM: tx_mod==0", rb_name.c_str());
return false;
}
mod = (cfg.um_nr.sn_field_length == rlc_um_nr_sn_size_t::size6bits) ? 64 : 4096;
UM_Window_Size = (cfg.um_nr.sn_field_length == rlc_um_nr_sn_size_t::size6bits) ? 32 : 2048;
// calculate header sizes for configured SN length
rlc_um_nr_pdu_header_t header = {};
@ -197,7 +195,7 @@ uint32_t rlc_um_nr::rlc_um_nr_tx::build_data_pdu(unique_byte_buffer_t pdu, uint8
// Update SN if needed
if (header.si == rlc_nr_si_field_t::last_segment) {
TX_Next = (TX_Next + 1) % cfg.um_nr.mod;
TX_Next = (TX_Next + 1) % mod;
next_so = 0;
}
@ -238,10 +236,8 @@ rlc_um_nr::rlc_um_nr_rx::rlc_um_nr_rx(rlc_um_base* parent_) :
bool rlc_um_nr::rlc_um_nr_rx::configure(const rlc_config_t& cnfg_, std::string rb_name_)
{
if (cfg.um_nr.mod == 0) {
logger.error("Error configuring %s RLC UM: rx_mod==0", rb_name.c_str());
return false;
}
mod = (cfg.um_nr.sn_field_length == rlc_um_nr_sn_size_t::size6bits) ? 64 : 4096;
UM_Window_Size = (cfg.um_nr.sn_field_length == rlc_um_nr_sn_size_t::size6bits) ? 32 : 2048;
// check timer
if (not reassembly_timer.is_valid()) {
@ -306,7 +302,7 @@ void rlc_um_nr::rlc_um_nr_rx::timer_expired(uint32_t timeout_id)
// update RX_Next_Reassembly to the next SN that has not been reassembled yet
RX_Next_Reassembly = RX_Timer_Trigger;
while (RX_MOD_NR_BASE(RX_Next_Reassembly) < RX_MOD_NR_BASE(RX_Next_Highest)) {
RX_Next_Reassembly = (RX_Next_Reassembly + 1) % cfg.um_nr.mod;
RX_Next_Reassembly = (RX_Next_Reassembly + 1) % mod;
debug_state();
}
@ -334,14 +330,14 @@ void rlc_um_nr::rlc_um_nr_rx::timer_expired(uint32_t timeout_id)
// Sec 5.2.2.2.1
bool rlc_um_nr::rlc_um_nr_rx::sn_in_reassembly_window(const uint32_t sn)
{
return (RX_MOD_NR_BASE(RX_Next_Highest - cfg.um_nr.UM_Window_Size) <= RX_MOD_NR_BASE(sn) &&
return (RX_MOD_NR_BASE(RX_Next_Highest - UM_Window_Size) <= RX_MOD_NR_BASE(sn) &&
RX_MOD_NR_BASE(sn) < RX_MOD_NR_BASE(RX_Next_Highest));
}
// Sec 5.2.2.2.2
bool rlc_um_nr::rlc_um_nr_rx::sn_invalid_for_rx_buffer(const uint32_t sn)
{
return (RX_MOD_NR_BASE(RX_Next_Highest - cfg.um_nr.UM_Window_Size) <= RX_MOD_NR_BASE(sn) &&
return (RX_MOD_NR_BASE(RX_Next_Highest - UM_Window_Size) <= RX_MOD_NR_BASE(sn) &&
RX_MOD_NR_BASE(sn) < RX_MOD_NR_BASE(RX_Next_Reassembly));
}
@ -423,9 +419,9 @@ void rlc_um_nr::rlc_um_nr_rx::handle_rx_buffer_update(const uint32_t sn)
// find next SN in rx buffer
if (sn == RX_Next_Reassembly) {
RX_Next_Reassembly = ((RX_Next_Reassembly + 1) % cfg.um_nr.mod);
RX_Next_Reassembly = ((RX_Next_Reassembly + 1) % mod);
while (RX_MOD_NR_BASE(RX_Next_Reassembly) < RX_MOD_NR_BASE(RX_Next_Highest)) {
RX_Next_Reassembly = (RX_Next_Reassembly + 1) % cfg.um_nr.mod;
RX_Next_Reassembly = (RX_Next_Reassembly + 1) % mod;
}
logger.debug("Updating RX_Next_Reassembly=%d", RX_Next_Reassembly);
}
@ -453,7 +449,7 @@ void rlc_um_nr::rlc_um_nr_rx::handle_rx_buffer_update(const uint32_t sn)
logger.info("%s SN: %d outside rx window [%d:%d] - discarding",
rb_name.c_str(),
it->first,
RX_Next_Highest - cfg.um_nr.UM_Window_Size,
RX_Next_Highest - UM_Window_Size,
RX_Next_Highest);
it = rx_window.erase(it);
metrics.num_lost_pdus++;
@ -465,7 +461,7 @@ void rlc_um_nr::rlc_um_nr_rx::handle_rx_buffer_update(const uint32_t sn)
if (not sn_in_reassembly_window(RX_Next_Reassembly)) {
// update RX_Next_Reassembly to first SN that has not been reassembled and delivered
for (const auto& rx_pdu : rx_window) {
if (rx_pdu.first >= RX_MOD_NR_BASE(RX_Next_Highest - cfg.um_nr.UM_Window_Size)) {
if (rx_pdu.first >= RX_MOD_NR_BASE(RX_Next_Highest - UM_Window_Size)) {
RX_Next_Reassembly = rx_pdu.first;
logger.debug("Updating RX_Next_Reassembly=%d", RX_Next_Reassembly);
break;

@ -94,8 +94,6 @@ void backend_worker::start(backend_priority priority)
void backend_worker::do_work()
{
assert(running_flag && "Thread entry function called without running thread");
/// This period defines the time the worker will sleep while waiting for new entries. This is required to check the
/// termination variable periodically.
constexpr std::chrono::microseconds sleep_period{100};

@ -23,5 +23,6 @@ add_subdirectory(common)
add_subdirectory(mac)
add_subdirectory(phy)
add_subdirectory(srslog)
add_subdirectory(upper)
add_subdirectory(rlc)
add_subdirectory(pdcp)
add_subdirectory(adt)

@ -43,10 +43,10 @@ int test_rlc_config()
rlc_cfg_asn1.to_json(jw);
srslog::fetch_basic_logger("RRC").info("RLC NR Config: \n %s", jw.to_string().c_str());
rlc_config_t rlc_cfg = make_rlc_config_t(rlc_cfg_asn1);
rlc_config_t rlc_cfg;
TESTASSERT(make_rlc_config_t(rlc_cfg_asn1, &rlc_cfg) == SRSRAN_SUCCESS);
TESTASSERT(rlc_cfg.rat == srsran_rat_t::nr);
TESTASSERT(rlc_cfg.um_nr.sn_field_length == rlc_um_nr_sn_size_t::size12bits);
TESTASSERT(rlc_cfg.um_nr.UM_Window_Size == 2048);
return SRSRAN_SUCCESS;
}

@ -0,0 +1,43 @@
#
# 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.
#
set(CTEST_LABELS "lib;pdcp")
add_executable(pdcp_nr_test_tx pdcp_nr_test_tx.cc)
target_link_libraries(pdcp_nr_test_tx srsran_pdcp srsran_common)
add_nr_test(pdcp_nr_test_tx pdcp_nr_test_tx)
add_executable(pdcp_nr_test_rx pdcp_nr_test_rx.cc)
target_link_libraries(pdcp_nr_test_rx srsran_pdcp srsran_common)
add_nr_test(pdcp_nr_test_rx pdcp_nr_test_rx)
add_executable(pdcp_nr_test_discard_sdu pdcp_nr_test_discard_sdu.cc)
target_link_libraries(pdcp_nr_test_discard_sdu srsran_pdcp srsran_common ${ATOMIC_LIBS})
add_nr_test(pdcp_nr_test_discard_sdu pdcp_nr_test_discard_sdu)
add_executable(pdcp_lte_test_rx pdcp_lte_test_rx.cc)
target_link_libraries(pdcp_lte_test_rx srsran_pdcp srsran_common)
add_test(pdcp_lte_test_rx pdcp_lte_test_rx)
add_executable(pdcp_lte_test_discard_sdu pdcp_lte_test_discard_sdu.cc)
target_link_libraries(pdcp_lte_test_discard_sdu srsran_pdcp srsran_common)
add_test(pdcp_lte_test_discard_sdu pdcp_lte_test_discard_sdu)
add_executable(pdcp_lte_test_status_report pdcp_lte_test_status_report.cc)
target_link_libraries(pdcp_lte_test_status_report srsran_pdcp srsran_common)
add_test(pdcp_lte_test_status_report pdcp_lte_test_status_report)
########################################################################
# Option to run command after build (useful for remote builds)
########################################################################
if (NOT ${BUILD_CMD} STREQUAL "")
message(STATUS "Added custom post-build command: ${BUILD_CMD}")
add_custom_command(TARGET ip_test POST_BUILD COMMAND ${BUILD_CMD})
else(NOT ${BUILD_CMD} STREQUAL "")
message(STATUS "No post-build command defined")
endif (NOT ${BUILD_CMD} STREQUAL "")

@ -179,7 +179,7 @@ static int work_gnb_dl(srsran_enb_dl_nr_t* enb_dl,
dci_dl.rv = 0;
// Put actual DCI
if (srsran_enb_dl_nr_pdcch_put(enb_dl, slot, &dci_dl) < SRSRAN_SUCCESS) {
if (srsran_enb_dl_nr_pdcch_put_dl(enb_dl, slot, &dci_dl) < SRSRAN_SUCCESS) {
ERROR("Error putting PDCCH");
return SRSRAN_ERROR;
}

@ -18,26 +18,26 @@
# and at http://www.gnu.org/licenses/.
#
set(CTEST_LABELS "lib;upper")
set(CTEST_LABELS "lib;rlc")
add_executable(rlc_am_data_test rlc_am_data_test.cc)
target_link_libraries(rlc_am_data_test srsran_upper srsran_phy srsran_common)
target_link_libraries(rlc_am_data_test srsran_rlc srsran_phy srsran_common)
add_lte_test(rlc_am_data_test rlc_am_data_test)
add_executable(rlc_am_control_test rlc_am_control_test.cc)
target_link_libraries(rlc_am_control_test srsran_upper srsran_phy)
target_link_libraries(rlc_am_control_test srsran_rlc srsran_phy)
add_lte_test(rlc_am_control_test rlc_am_control_test)
add_executable(rlc_am_test rlc_am_test.cc)
target_link_libraries(rlc_am_test srsran_upper srsran_phy srsran_common)
target_link_libraries(rlc_am_test srsran_rlc srsran_phy srsran_common)
add_lte_test(rlc_am_test rlc_am_test)
add_executable(rlc_am_nr_pdu_test rlc_am_nr_pdu_test.cc)
target_link_libraries(rlc_am_nr_pdu_test srsran_upper srsran_phy)
target_link_libraries(rlc_am_nr_pdu_test srsran_rlc srsran_phy)
add_nr_test(rlc_am_nr_pdu_test rlc_am_nr_pdu_test)
add_executable(rlc_stress_test rlc_stress_test.cc)
target_link_libraries(rlc_stress_test srsran_upper srsran_mac srsran_phy srsran_common ${Boost_LIBRARIES} ${ATOMIC_LIBS})
target_link_libraries(rlc_stress_test srsran_rlc srsran_mac srsran_phy srsran_common ${Boost_LIBRARIES} ${ATOMIC_LIBS})
add_lte_test(rlc_am_stress_test rlc_stress_test --mode=AM --loglevel 1 --sdu_gen_delay 250)
add_lte_test(rlc_um_stress_test rlc_stress_test --mode=UM --loglevel 1)
add_lte_test(rlc_tm_stress_test rlc_stress_test --mode=TM --loglevel 1 --random_opp=false)
@ -46,49 +46,25 @@ add_nr_test(rlc_um6_nr_stress_test rlc_stress_test --rat NR --mode=UM6 --logleve
add_nr_test(rlc_um12_nr_stress_test rlc_stress_test --rat NR --mode=UM12 --loglevel 1)
add_executable(rlc_um_data_test rlc_um_data_test.cc)
target_link_libraries(rlc_um_data_test srsran_upper srsran_phy srsran_common)
target_link_libraries(rlc_um_data_test srsran_rlc srsran_phy srsran_common)
add_test(rlc_um_data_test rlc_um_data_test)
add_executable(rlc_um_test rlc_um_test.cc)
target_link_libraries(rlc_um_test srsran_upper srsran_phy)
target_link_libraries(rlc_um_test srsran_rlc srsran_phy)
add_test(rlc_um_test rlc_um_test)
add_executable(rlc_common_test rlc_common_test.cc)
target_link_libraries(rlc_common_test srsran_upper srsran_phy)
target_link_libraries(rlc_common_test srsran_rlc srsran_phy)
add_test(rlc_common_test rlc_common_test)
add_executable(rlc_um_nr_pdu_test rlc_um_nr_pdu_test.cc)
target_link_libraries(rlc_um_nr_pdu_test srsran_upper srsran_mac srsran_phy)
target_link_libraries(rlc_um_nr_pdu_test srsran_rlc srsran_mac srsran_phy)
add_nr_test(rlc_um_nr_pdu_test rlc_um_nr_pdu_test)
add_executable(rlc_um_nr_test rlc_um_nr_test.cc)
target_link_libraries(rlc_um_nr_test srsran_upper srsran_phy)
target_link_libraries(rlc_um_nr_test srsran_rlc srsran_phy)
add_nr_test(rlc_um_nr_test rlc_um_nr_test)
add_executable(pdcp_nr_test_tx pdcp_nr_test_tx.cc)
target_link_libraries(pdcp_nr_test_tx srsran_upper srsran_common)
add_nr_test(pdcp_nr_test_tx pdcp_nr_test_tx)
add_executable(pdcp_nr_test_rx pdcp_nr_test_rx.cc)
target_link_libraries(pdcp_nr_test_rx srsran_upper srsran_common)
add_nr_test(pdcp_nr_test_rx pdcp_nr_test_rx)
add_executable(pdcp_nr_test_discard_sdu pdcp_nr_test_discard_sdu.cc)
target_link_libraries(pdcp_nr_test_discard_sdu srsran_upper srsran_common ${ATOMIC_LIBS})
add_nr_test(pdcp_nr_test_discard_sdu pdcp_nr_test_discard_sdu)
add_executable(pdcp_lte_test_rx pdcp_lte_test_rx.cc)
target_link_libraries(pdcp_lte_test_rx srsran_upper srsran_common)
add_test(pdcp_lte_test_rx pdcp_lte_test_rx)
add_executable(pdcp_lte_test_discard_sdu pdcp_lte_test_discard_sdu.cc)
target_link_libraries(pdcp_lte_test_discard_sdu srsran_upper srsran_common)
add_test(pdcp_lte_test_discard_sdu pdcp_lte_test_discard_sdu)
add_executable(pdcp_lte_test_status_report pdcp_lte_test_status_report.cc)
target_link_libraries(pdcp_lte_test_status_report srsran_upper srsran_common)
add_test(pdcp_lte_test_status_report pdcp_lte_test_status_report)
########################################################################
# Option to run command after build (useful for remote builds)
########################################################################

@ -20,7 +20,7 @@
*/
#include "srsran/common/test_common.h"
#include "srsran/upper/rlc_am_lte.h"
#include "srsran/rlc/rlc_am_lte.h"
#include <iostream>
// Simple status PDU

@ -20,7 +20,7 @@
*/
#include "srsran/common/test_common.h"
#include "srsran/upper/rlc_am_lte.h"
#include "srsran/rlc/rlc_am_lte.h"
#include <iostream>
// Fixed header only

@ -20,8 +20,8 @@
*/
#include "srsran/config.h"
#include "srsran/upper/rlc.h"
#include "srsran/upper/rlc_am_nr.h"
#include "srsran/rlc/rlc.h"
#include "srsran/rlc/rlc_am_nr.h"
#include <array>
#include <iostream>

@ -25,7 +25,7 @@
#include "srsran/common/threads.h"
#include "srsran/interfaces/ue_pdcp_interfaces.h"
#include "srsran/interfaces/ue_rrc_interfaces.h"
#include "srsran/upper/rlc_am_lte.h"
#include "srsran/rlc/rlc_am_lte.h"
#define NBUFS 5
#define HAVE_PCAP 0
@ -84,8 +84,8 @@ public:
const char* get_rb_name(uint32_t lcid) { return ""; }
std::vector<unique_byte_buffer_t> sdus;
rlc_pcap* pcap = nullptr;
bool max_retx_triggered = false;
rlc_pcap* pcap = nullptr;
bool max_retx_triggered = false;
bool protocol_failure_triggered = false;
std::map<uint32_t, uint32_t> notified_counts; // Map of PDCP SNs to number of notifications

@ -19,7 +19,7 @@
*
*/
#include "srsran/upper/rlc.h"
#include "srsran/rlc/rlc.h"
#include <iostream>
#define TESTASSERT(cond) \

@ -25,7 +25,7 @@
#include "srsran/common/test_common.h"
#include "srsran/common/threads.h"
#include "srsran/common/tsan_options.h"
#include "srsran/upper/rlc.h"
#include "srsran/rlc/rlc.h"
#include <boost/program_options.hpp>
#include <boost/program_options/parsers.hpp>
#include <cassert>

@ -20,7 +20,7 @@
*/
#include "srsran/common/test_common.h"
#include "srsran/upper/rlc_um_lte.h"
#include "srsran/rlc/rlc_um_lte.h"
#include <iostream>
// Fixed header only

@ -20,8 +20,8 @@
*/
#include "srsran/config.h"
#include "srsran/upper/rlc.h"
#include "srsran/upper/rlc_um_nr.h"
#include "srsran/rlc/rlc.h"
#include "srsran/rlc/rlc_um_nr.h"
#include <array>
#include <iostream>

@ -22,8 +22,8 @@
#include "rlc_test_common.h"
#include "srsran/config.h"
#include "srsran/interfaces/ue_pdcp_interfaces.h"
#include "srsran/upper/rlc.h"
#include "srsran/upper/rlc_um_nr.h"
#include "srsran/rlc/rlc.h"
#include "srsran/rlc/rlc_um_nr.h"
#include <array>
#include <iostream>

@ -20,7 +20,7 @@
*/
#include "rlc_test_common.h"
#include "srsran/upper/rlc_um_lte.h"
#include "srsran/rlc/rlc_um_lte.h"
#include <iostream>
#define TESTASSERT(cond) \

@ -333,6 +333,8 @@ enable = false
# eea_pref_list: Ordered preference list for the selection of encryption algorithm (EEA) (default: EEA0, EEA2, EEA1).
# eia_pref_list: Ordered preference list for the selection of integrity algorithm (EIA) (default: EIA2, EIA1, EIA0).
# gtpu_tunnel_timeout: Time that GTPU takes to release indirect forwarding tunnel since the last received GTPU PDU (0 for no timer).
#ts1_reloc_prep_timeout: S1AP TS 36.413 TS1RelocPrep Expiry Timeout value in milliseconds
#ts1_reloc_overall_timeout: S1AP TS 36.413 TS1RelocOverall Expiry Timeout value in milliseconds
#
#####################################################################
[expert]
@ -361,3 +363,5 @@ enable = false
#eia_pref_list = EIA2, EIA1, EIA0
#gtpu_tunnel_timeout = 0
#extended_cp = false
#ts1_reloc_prep_timeout = 10000
#ts1_reloc_overall_timeout = 10000

@ -1,93 +0,0 @@
/**
* Copyright 2013-2021 Software Radio Systems Limited
*
* This file is part of srsRAN.
*
* srsRAN is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsRAN is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef SRSENB_NR_CC_WORKER_H
#define SRSENB_NR_CC_WORKER_H
#include "srsenb/hdr/phy/phy_interfaces.h"
#include "srsran/interfaces/gnb_interfaces.h"
#include "srsran/interfaces/rrc_nr_interface_types.h"
#include "srsran/phy/enb/enb_dl_nr.h"
#include "srsran/srslog/srslog.h"
#include "srsran/srsran.h"
#include <array>
#include <vector>
namespace srsenb {
namespace nr {
struct phy_nr_args_t {
uint32_t nof_carriers = 1;
uint32_t nof_ports = 1;
srsran_enb_dl_nr_args_t dl = {};
};
class phy_nr_state
{
public:
phy_cell_cfg_list_nr_t cell_list = {};
phy_nr_args_t args;
srsran::phy_cfg_nr_t cfg;
phy_nr_state()
{
args.nof_carriers = 1;
args.dl.nof_max_prb = 100;
args.dl.nof_tx_antennas = 1;
args.dl.pdsch.measure_evm = true;
args.dl.pdsch.measure_time = true;
args.dl.pdsch.sch.disable_simd = false;
}
};
class cc_worker
{
public:
cc_worker(uint32_t cc_idx, srslog::basic_logger& logger, phy_nr_state& phy_state_);
~cc_worker();
bool set_carrier(const srsran_carrier_nr_t* carrier);
void set_tti(uint32_t tti);
cf_t* get_tx_buffer(uint32_t antenna_idx);
cf_t* get_rx_buffer(uint32_t antenna_idx);
uint32_t get_buffer_len();
bool work_dl(const srsran_slot_cfg_t& dl_slot_cfg, stack_interface_phy_nr::dl_sched_t& dl_grants);
private:
int encode_pdsch(stack_interface_phy_nr::dl_sched_grant_t* grants, uint32_t nof_grants);
int encode_pdcch_dl(stack_interface_phy_nr::dl_sched_grant_t* grants, uint32_t nof_grants);
srsran_slot_cfg_t dl_slot_cfg = {};
uint32_t cc_idx = 0;
std::array<cf_t*, SRSRAN_MAX_PORTS> tx_buffer = {};
std::array<cf_t*, SRSRAN_MAX_PORTS> rx_buffer = {};
uint32_t buffer_sz = 0;
phy_nr_state& phy_state;
srsran_enb_dl_nr_t enb_dl = {};
srslog::basic_logger& logger;
};
} // namespace nr
} // namespace srsenb
#endif // SRSENB_NR_CC_WORKER_H

@ -1,73 +0,0 @@
/**
* Copyright 2013-2021 Software Radio Systems Limited
*
* This file is part of srsRAN.
*
* srsRAN is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsRAN is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef SRSENB_NR_PHCH_WORKER_H
#define SRSENB_NR_PHCH_WORKER_H
#include "cc_worker.h"
#include "srsran/common/thread_pool.h"
#include "srsran/interfaces/phy_common_interface.h"
#include "srsran/srslog/srslog.h"
namespace srsenb {
namespace nr {
/**
* The sf_worker class handles the PHY processing, UL and DL procedures associated with 1 subframe.
* It contains multiple cc_worker objects, one for each component carrier which may be executed in
* one or multiple threads.
*
* A sf_worker object is executed by a thread within the thread_pool.
*/
class sf_worker final : public srsran::thread_pool::worker
{
public:
sf_worker(srsran::phy_common_interface& common_, phy_nr_state& phy_state_, srslog::basic_logger& logger);
~sf_worker();
bool set_carrier_unlocked(uint32_t cc_idx, const srsran_carrier_nr_t* carrier_);
/* Functions used by main PHY thread */
cf_t* get_buffer_rx(uint32_t cc_idx, uint32_t antenna_idx);
cf_t* get_buffer_tx(uint32_t cc_idx, uint32_t antenna_idx);
uint32_t get_buffer_len();
void set_tti(uint32_t tti);
private:
/* Inherited from thread_pool::worker. Function called every subframe to run the DL/UL processing */
void work_imp() override;
std::vector<std::unique_ptr<cc_worker> > cc_workers;
srsran::phy_common_interface& common;
phy_nr_state& phy_state;
srslog::basic_logger& logger;
// Temporal attributes
srsran_softbuffer_tx_t softbuffer_tx = {};
std::vector<uint8_t> data;
};
} // namespace nr
} // namespace srsenb
#endif // SRSENB_NR_PHCH_WORKER_H

@ -0,0 +1,90 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSENB_NR_SLOT_WORKER_H
#define SRSENB_NR_SLOT_WORKER_H
#include "srsran/common/thread_pool.h"
#include "srsran/interfaces/gnb_interfaces.h"
#include "srsran/interfaces/phy_common_interface.h"
#include "srsran/srslog/srslog.h"
#include "srsran/srsran.h"
namespace srsenb {
namespace nr {
/**
* The slot_worker class handles the PHY processing, UL and DL procedures associated with 1 slot.
*
* A slot_worker object is executed by a thread within the thread_pool.
*/
class slot_worker final : public srsran::thread_pool::worker
{
public:
struct args_t {
uint32_t cell_index = 0;
srsran_carrier_nr_t carrier = {};
uint32_t nof_tx_ports = 1;
uint32_t nof_rx_ports = 1;
uint32_t pusch_max_nof_iter = 10;
srsran_pdcch_cfg_nr_t pdcch_cfg = {}; ///< PDCCH configuration
};
slot_worker(srsran::phy_common_interface& common_, stack_interface_phy_nr& stack_, srslog::basic_logger& logger);
~slot_worker();
bool init(const args_t& args);
/* Functions used by main PHY thread */
cf_t* get_buffer_rx(uint32_t antenna_idx);
cf_t* get_buffer_tx(uint32_t antenna_idx);
uint32_t get_buffer_len();
void set_time(const uint32_t& tti, const srsran::rf_timestamp_t& timestamp);
private:
/**
* @brief Inherited from thread_pool::worker. Function called every slot to run the DL/UL processing
*/
void work_imp() override;
/**
* @brief Retrieves the scheduling results for the UL processing and performs reception
* @return True if no error occurs, false otherwise
*/
bool work_ul();
/**
* @brief Retrieves the scheduling results for the DL processing and performs transmission
* @return True if no error occurs, false otherwise
*/
bool work_dl();
srsran::phy_common_interface& common;
stack_interface_phy_nr& stack;
srslog::basic_logger& logger;
uint32_t sf_len = 0;
uint32_t cell_index = 0;
srsran_slot_cfg_t dl_slot_cfg = {};
srsran_slot_cfg_t ul_slot_cfg = {};
srsran_pdcch_cfg_nr_t pdcch_cfg = {};
srsran::rf_timestamp_t tx_time = {};
srsran_enb_dl_nr_t gnb_dl = {};
std::vector<cf_t*> tx_buffer; ///< Baseband transmit buffers
std::vector<cf_t*> rx_buffer; ///< Baseband receive buffers
};
} // namespace nr
} // namespace srsenb
#endif // SRSENB_NR_PHCH_WORKER_H

@ -22,32 +22,42 @@
#ifndef SRSENB_NR_WORKER_POOL_H
#define SRSENB_NR_WORKER_POOL_H
#include "sf_worker.h"
#include "slot_worker.h"
#include "srsenb/hdr/phy/phy_interfaces.h"
#include "srsran/common/thread_pool.h"
#include "srsran/interfaces/gnb_interfaces.h"
namespace srsenb {
namespace nr {
class worker_pool
{
srsran::thread_pool pool;
std::vector<std::unique_ptr<sf_worker> > workers;
phy_nr_state phy_state;
srsran::phy_common_interface& common;
stack_interface_phy_nr& stack;
srslog::sink& log_sink;
srsran::thread_pool pool;
std::vector<std::unique_ptr<slot_worker> > workers;
public:
sf_worker* operator[](std::size_t pos) { return workers.at(pos).get(); }
worker_pool(uint32_t max_workers);
bool init(const phy_cell_cfg_list_nr_t& cell_list,
const phy_args_t& args,
srsran::phy_common_interface& common,
srslog::sink& log_sink,
int prio);
sf_worker* wait_worker(uint32_t tti);
sf_worker* wait_worker_id(uint32_t id);
void start_worker(sf_worker* w);
void stop();
struct args_t {
uint32_t nof_phy_threads = 3;
uint32_t prio = 52;
std::string log_level = "info";
uint32_t log_hex_limit = 64;
std::string log_id_preamble = "";
uint32_t pusch_max_nof_iter = 10;
};
slot_worker* operator[](std::size_t pos) { return workers.at(pos).get(); }
worker_pool(srsran::phy_common_interface& common,
stack_interface_phy_nr& stack,
srslog::sink& log_sink,
uint32_t max_workers);
bool init(const args_t& args, const phy_cell_cfg_list_nr_t& cell_list);
slot_worker* wait_worker(uint32_t tti);
slot_worker* wait_worker_id(uint32_t id);
void start_worker(slot_worker* w);
void stop();
};
} // namespace nr

@ -86,11 +86,11 @@ private:
srslog::basic_logger& phy_log;
srslog::basic_logger& phy_lib_log;
lte::worker_pool lte_workers;
nr::worker_pool nr_workers;
phy_common workers_common;
prach_worker_pool prach;
txrx tx_rx;
lte::worker_pool lte_workers;
std::unique_ptr<nr::worker_pool> nr_workers;
phy_common workers_common;
prach_worker_pool prach;
txrx tx_rx;
bool initialized = false;

@ -25,7 +25,7 @@
#include "srsran/asn1/rrc/rr_common.h"
#include "srsran/common/interfaces_common.h"
#include "srsran/phy/channel/channel.h"
#include "srsran/phy/common/phy_common_nr.h"
#include "srsran/srsran.h"
#include <inttypes.h>
#include <vector>
@ -43,14 +43,15 @@ struct phy_cell_cfg_t {
};
struct phy_cell_cfg_nr_t {
srsran_carrier_nr_t carrier;
uint32_t rf_port;
uint32_t cell_id;
double dl_freq_hz;
double ul_freq_hz;
uint32_t root_seq_idx;
uint32_t num_ra_preambles;
float gain_db;
srsran_carrier_nr_t carrier;
uint32_t rf_port;
uint32_t cell_id;
double dl_freq_hz;
double ul_freq_hz;
uint32_t root_seq_idx;
uint32_t num_ra_preambles;
float gain_db;
srsran_pdcch_cfg_nr_t pdcch = {}; ///< Common CORESET and Search Space configuration
};
typedef std::vector<phy_cell_cfg_t> phy_cell_cfg_list_t;
@ -60,18 +61,18 @@ struct phy_args_t {
std::string type;
srsran::phy_log_args_t log;
float max_prach_offset_us = 10;
int pusch_max_its = 10;
bool pusch_8bit_decoder = false;
float tx_amplitude = 1.0f;
uint32_t nof_phy_threads = 1;
std::string equalizer_mode = "mmse";
float estimator_fil_w = 1.0f;
bool pusch_meas_epre = true;
bool pusch_meas_evm = false;
bool pusch_meas_ta = true;
bool pucch_meas_ta = true;
uint32_t nof_prach_threads = 1;
float max_prach_offset_us = 10;
int pusch_max_its = 10;
bool pusch_8bit_decoder = false;
float tx_amplitude = 1.0f;
uint32_t nof_phy_threads = 1;
std::string equalizer_mode = "mmse";
float estimator_fil_w = 1.0f;
bool pusch_meas_epre = true;
bool pusch_meas_evm = false;
bool pusch_meas_ta = true;
bool pucch_meas_ta = true;
uint32_t nof_prach_threads = 1;
bool extended_cp = false;
srsran::channel::args_t dl_channel_args;
srsran::channel::args_t ul_channel_args;

@ -64,23 +64,26 @@ public:
bool get_metrics(srsenb::stack_metrics_t* metrics) final;
// GW srsue stack_interface_gw dummy interface
bool is_registered() { return true; };
bool start_service_request() { return true; };
bool is_registered() override { return true; };
bool start_service_request() override { return true; };
// PHY->MAC interface
int sf_indication(const uint32_t tti);
int rx_data_indication(rx_data_ind_t& grant);
int rx_data_indication(rx_data_ind_t& grant) override;
// Temporary GW interface
void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu);
bool is_lcid_enabled(uint32_t lcid);
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);
// MAC interface to trigger processing of received PDUs
void process_pdus() final;
void toggle_padding() { srsran::console("padding not available for NR\n"); }
void toggle_padding() override { srsran::console("padding not available for NR\n"); }
int slot_indication(const srsran_slot_cfg_t& slot_cfg) override;
int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) override;
int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) override;
private:
void run_thread() final;

@ -62,18 +62,21 @@ public:
void get_metrics(srsenb::mac_metrics_t& metrics);
// MAC interface for RRC
int cell_cfg(srsenb::sched_interface::cell_cfg_t* cell_cfg);
int cell_cfg(srsenb::sched_interface::cell_cfg_t* cell_cfg) override;
int read_pdu_bcch_bch(uint8_t* payload);
// MAC interface for RLC
// TODO:
int rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t retx_queue) { return 0; }
int rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t retx_queue) override { return 0; }
// Interface for PHY
int sf_indication(const uint32_t tti);
int rx_data_indication(stack_interface_phy_nr::rx_data_ind_t& grant);
void process_pdus();
int slot_indication(const srsran_slot_cfg_t& slot_cfg) override;
int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) override;
int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) override;
private:
void get_dl_config(const uint32_t tti,

@ -0,0 +1,67 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSRAN_SCHED_NR_H
#define SRSRAN_SCHED_NR_H
#include "sched_nr_common.h"
#include "sched_nr_interface.h"
#include "sched_nr_ue.h"
#include "srsran/adt/pool/cached_alloc.h"
#include "srsran/common/tti_point.h"
#include <array>
extern "C" {
#include "srsran/config.h"
}
namespace srsenb {
namespace sched_nr_impl {
class sched_worker_manager;
}
class ue_event_manager;
class sched_nr final : public sched_nr_interface
{
public:
explicit sched_nr(const sched_cfg_t& sched_cfg);
~sched_nr() override;
int cell_cfg(srsran::const_span<cell_cfg_t> cell_list) override;
void ue_cfg(uint16_t rnti, const ue_cfg_t& cfg) override;
void slot_indication(tti_point tti_rx) override;
int generate_sched_result(tti_point tti_rx, uint32_t cc, tti_request_t& tti_req) override;
void dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) override;
void ul_sr_info(tti_point tti_rx, uint16_t rnti) override;
private:
void ue_cfg_impl(uint16_t rnti, const ue_cfg_t& cfg);
// args
sched_nr_impl::sched_params cfg;
using sched_worker_manager = sched_nr_impl::sched_worker_manager;
std::unique_ptr<sched_worker_manager> sched_workers;
using ue_map_t = sched_nr_impl::ue_map_t;
std::mutex ue_db_mutex;
ue_map_t ue_db;
// management of PHY UE feedback
std::unique_ptr<ue_event_manager> pending_events;
};
} // namespace srsenb
#endif // SRSRAN_SCHED_NR_H

@ -0,0 +1,102 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSRAN_SCHED_NR_COMMON_H
#define SRSRAN_SCHED_NR_COMMON_H
#include "sched_nr_interface.h"
#include "srsran/adt/bounded_bitset.h"
namespace srsenb {
const static size_t SCHED_NR_MAX_USERS = 4;
const static size_t SCHED_NR_NOF_SUBFRAMES = 10;
const static size_t SCHED_NR_NOF_HARQS = 16;
static const size_t MAX_NOF_AGGR_LEVELS = 5;
namespace sched_nr_impl {
const static size_t MAX_GRANTS = sched_nr_interface::MAX_GRANTS;
using sched_cfg_t = sched_nr_interface::sched_cfg_t;
using cell_cfg_t = sched_nr_interface::cell_cfg_t;
struct sched_cell_params {
const uint32_t cc;
const cell_cfg_t cell_cfg;
const sched_cfg_t& sched_cfg;
sched_cell_params(uint32_t cc_, const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_);
};
struct sched_params {
const sched_cfg_t sched_cfg;
std::vector<sched_cell_params> cells;
explicit sched_params(const sched_cfg_t& sched_cfg_);
};
using pdcchmask_t = srsran::bounded_bitset<SCHED_NR_MAX_NOF_RBGS, true>;
using rbgmask_t = srsran::bounded_bitset<SCHED_NR_MAX_NOF_RBGS, true>;
struct resource_guard {
public:
resource_guard() = default;
resource_guard(const resource_guard& other) = delete;
resource_guard(resource_guard&& other) = delete;
resource_guard& operator=(const resource_guard& other) = delete;
resource_guard& operator=(resource_guard&& other) = delete;
bool busy() const { return flag; }
struct token {
token() = default;
token(resource_guard& parent) : flag(parent.busy() ? nullptr : &parent.flag)
{
if (flag != nullptr) {
*flag = true;
}
}
token(token&&) noexcept = default;
token& operator=(token&&) noexcept = default;
void release() { flag.reset(); }
bool owns_token() const { return flag != nullptr; }
bool empty() const { return flag == nullptr; }
private:
struct release_deleter {
void operator()(bool* ptr)
{
if (ptr != nullptr) {
srsran_assert(*ptr == true, "resource token: detected inconsistency token state");
*ptr = false;
}
}
};
std::unique_ptr<bool, release_deleter> flag;
};
private:
bool flag = false;
};
using pdcch_cce_pos_list = srsran::bounded_vector<uint32_t, SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR>;
using bwp_cce_pos_list = std::array<std::array<pdcch_cce_pos_list, MAX_NOF_AGGR_LEVELS>, SRSRAN_NOF_SF_X_FRAME>;
void get_dci_locs(const srsran_coreset_t& coreset,
const srsran_search_space_t& search_space,
uint16_t rnti,
bwp_cce_pos_list& cce_locs);
} // namespace sched_nr_impl
} // namespace srsenb
#endif // SRSRAN_SCHED_NR_COMMON_H

@ -0,0 +1,114 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSRAN_SCHED_NR_HARQ_H
#define SRSRAN_SCHED_NR_HARQ_H
#include "sched_nr_common.h"
#include "srsran/common/tti_point.h"
#include <array>
namespace srsenb {
namespace sched_nr_impl {
class harq_proc
{
public:
explicit harq_proc(uint32_t id_) : pid(id_) {}
bool empty() const
{
return std::all_of(tb.begin(), tb.end(), [](const tb_t& t) { return not t.active; });
}
bool empty(uint32_t tb_idx) const { return not tb[tb_idx].active; }
bool has_pending_retx(tti_point tti_rx) const { return not empty() and not tb[0].ack_state and tti_ack <= tti_rx; }
uint32_t nof_retx() const { return tb[0].n_rtx; }
uint32_t max_nof_retx() const { return max_retx; }
uint32_t tbs() const { return tb[0].tbs; }
uint32_t ndi() const { return tb[0].ndi; }
uint32_t mcs() const { return tb[0].mcs; }
bool ack_info(uint32_t tb_idx, bool ack);
void new_tti(tti_point tti_rx);
void reset();
bool
new_tx(tti_point tti_tx, tti_point tti_ack, const rbgmask_t& rbgmask, uint32_t mcs, uint32_t tbs, uint32_t max_retx);
bool new_retx(tti_point tti_tx, tti_point tti_ack, const rbgmask_t& rbgmask, int* mcs, int* tbs);
const uint32_t pid;
private:
struct tb_t {
bool active = false;
bool ack_state = false;
bool ndi = false;
uint32_t n_rtx = 0;
uint32_t mcs = 0;
uint32_t tbs = 0;
};
uint32_t max_retx = 1;
tti_point tti_tx;
tti_point tti_ack;
rbgmask_t rbgmask;
std::array<tb_t, SCHED_NR_MAX_TB> tb;
};
class harq_entity
{
public:
explicit harq_entity(uint32_t nof_harq_procs = SCHED_NR_MAX_HARQ);
void new_tti(tti_point tti_rx_);
void dl_ack_info(uint32_t pid, uint32_t tb_idx, bool ack) { dl_harqs[pid].ack_info(tb_idx, ack); }
harq_proc* find_pending_dl_retx()
{
return find_dl([this](const harq_proc& h) { return h.has_pending_retx(tti_rx); });
}
harq_proc* find_pending_ul_retx()
{
return find_ul([this](const harq_proc& h) { return h.has_pending_retx(tti_rx); });
}
harq_proc* find_empty_dl_harq()
{
return find_dl([](const harq_proc& h) { return h.empty(); });
}
harq_proc* find_empty_ul_harq()
{
return find_ul([](const harq_proc& h) { return h.empty(); });
}
private:
template <typename Predicate>
harq_proc* find_dl(Predicate p)
{
auto it = std::find_if(dl_harqs.begin(), dl_harqs.end(), p);
return (it == dl_harqs.end()) ? nullptr : &(*it);
}
template <typename Predicate>
harq_proc* find_ul(Predicate p)
{
auto it = std::find_if(ul_harqs.begin(), ul_harqs.end(), p);
return (it == ul_harqs.end()) ? nullptr : &(*it);
}
tti_point tti_rx;
std::vector<harq_proc> dl_harqs;
std::vector<harq_proc> ul_harqs;
};
} // namespace sched_nr_impl
} // namespace srsenb
#endif // SRSRAN_SCHED_NR_HARQ_H

@ -0,0 +1,128 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSRAN_SCHED_NR_INTERFACE_H
#define SRSRAN_SCHED_NR_INTERFACE_H
#include "srsran/adt/bounded_bitset.h"
#include "srsran/adt/bounded_vector.h"
#include "srsran/adt/span.h"
#include "srsran/common/tti_point.h"
#include "srsran/interfaces/gnb_interfaces.h"
#include "srsran/interfaces/rrc_nr_interface_types.h"
#include "srsran/phy/phch/dci_nr.h"
namespace srsenb {
const static size_t SCHED_NR_MAX_CARRIERS = 4;
const static uint16_t SCHED_NR_INVALID_RNTI = 0;
const static size_t SCHED_NR_MAX_PDSCH_DATA = 16;
const static size_t SCHED_NR_MAX_NOF_RBGS = 25;
const static size_t SCHED_NR_MAX_UL_ALLOCS = 16;
const static size_t SCHED_NR_MAX_TB = 1;
const static size_t SCHED_NR_MAX_HARQ = 16;
const static size_t SCHED_NR_MAX_BWP_PER_CELL = 1;
class sched_nr_interface
{
public:
using pdcch_bitmap = srsran::bounded_bitset<SCHED_NR_MAX_NOF_RBGS, true>;
using rbg_bitmap = srsran::bounded_bitset<SCHED_NR_MAX_NOF_RBGS, true>;
///// Configuration /////
struct pdsch_td_res_alloc {
uint8_t k0 = 0; // 0..32
uint8_t k1 = 4; // 0..32
};
using pdsch_td_res_alloc_list = srsran::bounded_vector<pdsch_td_res_alloc, SCHED_NR_MAX_UL_ALLOCS>;
struct pusch_td_res_alloc {
uint8_t k2 = 4; // 0..32
};
using pusch_td_res_alloc_list = srsran::bounded_vector<pusch_td_res_alloc, SCHED_NR_MAX_UL_ALLOCS>;
struct bwp_cfg_t {
uint32_t start_rb = 0;
uint32_t rb_width = 100;
};
struct cell_cfg_t {
uint32_t nof_prb = 100;
uint32_t nof_rbg = 25;
srsran::bounded_vector<bwp_cfg_t, SCHED_NR_MAX_BWP_PER_CELL> bwps{1};
};
struct sched_cfg_t {
uint32_t nof_concurrent_subframes = 1;
};
struct ue_cc_cfg_t {
bool active = false;
pdsch_td_res_alloc_list pdsch_res_list{1};
pusch_td_res_alloc_list pusch_res_list{1};
};
struct ue_cfg_t {
uint32_t maxharq_tx = 4;
srsran::bounded_vector<ue_cc_cfg_t, SCHED_NR_MAX_CARRIERS> carriers;
srsran::phy_cfg_nr_t phy_cfg = {};
};
///// Sched Result /////
const static int MAX_GRANTS = 64;
using pdcch_dl_t = mac_interface_phy_nr::pdcch_dl_t;
using pdcch_ul_t = mac_interface_phy_nr::pdcch_ul_t;
using pdcch_dl_list_t = srsran::bounded_vector<pdcch_dl_t, MAX_GRANTS>;
using pdcch_ul_list_t = srsran::bounded_vector<pdcch_ul_t, MAX_GRANTS>;
struct pdsch_t {
srsran_sch_cfg_nr_t sch = {}; ///< PDSCH configuration
};
using pdsch_list_t = srsran::bounded_vector<pdsch_t, SCHED_NR_MAX_PDSCH_DATA>;
struct dl_tti_request_t {
tti_point pdsch_tti;
pdcch_dl_list_t pdcchs;
pdsch_list_t pdschs;
};
struct pusch_grant {
srsran_dci_ul_nr_t dci;
rbg_bitmap bitmap;
};
using pusch_list = srsran::bounded_vector<pusch_grant, SCHED_NR_MAX_PDSCH_DATA>;
struct ul_tti_request_t {
tti_point pusch_tti;
srsran::bounded_vector<pusch_grant, SCHED_NR_MAX_UL_ALLOCS> pusch;
};
struct tti_request_t {
dl_tti_request_t dl_res;
ul_tti_request_t ul_res;
};
virtual ~sched_nr_interface() = default;
virtual int cell_cfg(srsran::const_span<sched_nr_interface::cell_cfg_t> ue_cfg) = 0;
virtual void ue_cfg(uint16_t rnti, const ue_cfg_t& ue_cfg) = 0;
virtual void slot_indication(tti_point tti_rx) = 0;
virtual int generate_sched_result(tti_point tti_rx, uint32_t cc, tti_request_t& result) = 0;
virtual void dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) = 0;
virtual void ul_sr_info(tti_point, uint16_t rnti) = 0;
};
} // namespace srsenb
#endif // SRSRAN_SCHED_NR_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.
*
*/
#ifndef SRSRAN_SCHED_NR_PDCCH_H
#define SRSRAN_SCHED_NR_PDCCH_H
#include "srsenb/hdr/stack/mac/nr/sched_nr_common.h"
#include "srsran/adt/bounded_bitset.h"
#include "srsran/adt/bounded_vector.h"
#include "srsran/phy/common/phy_common_nr.h"
#include "srsran/phy/phch/dci.h"
namespace srsenb {
namespace sched_nr_impl {
using coreset_bitmap = srsran::bounded_bitset<SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE * SRSRAN_CORESET_DURATION_MAX, true>;
enum class pdcch_grant_type_t { sib, dl_data, ul_data };
class slot_ue;
using pdcch_dl_t = sched_nr_interface::pdcch_dl_t;
using pdcch_dl_list_t = sched_nr_interface::pdcch_dl_list_t;
using pdcch_ul_t = sched_nr_interface::pdcch_ul_t;
using pdcch_ul_list_t = sched_nr_interface::pdcch_ul_list_t;
class coreset_region
{
public:
coreset_region(uint32_t bwp_id_,
uint32_t slot_idx,
uint32_t nof_td_symbols,
uint32_t nof_freq_resources,
pdcch_dl_list_t& pdcch_list);
void reset();
/**
* Allocates DCI space in PDCCH, avoiding in the process collisions with other users
* @param pdcch_grant_type_t allocation type (e.g. DL data, UL data, SIB)
* @param aggr_idx Aggregation level index (0..4)
* @param user UE object or null in case of broadcast/RAR/paging allocation
* @return if the allocation was successful
*/
bool alloc_dci(pdcch_grant_type_t alloc_type, uint32_t aggr_idx, uint32_t coreset_id, slot_ue* user = nullptr);
void rem_last_dci();
uint32_t get_td_symbols() const { return nof_symbols; }
uint32_t get_freq_resources() const { return nof_freq_res; }
uint32_t nof_cces() const { return nof_freq_res * nof_symbols; }
size_t nof_allocs() const { return dfs_tree.size(); }
private:
uint32_t bwp_id;
uint32_t slot_idx;
uint32_t nof_symbols;
uint32_t nof_freq_res;
// List of PDCCH grants
struct alloc_record {
uint32_t coreset_id;
uint32_t aggr_idx;
uint32_t idx;
pdcch_grant_type_t alloc_type;
slot_ue* ue;
};
srsran::bounded_vector<alloc_record, MAX_GRANTS> dci_list;
pdcch_dl_list_t& pdcch_dl_list;
// DFS decision tree of PDCCH grants
struct tree_node {
uint16_t rnti = SRSRAN_INVALID_RNTI;
uint32_t record_idx = 0;
uint32_t dci_pos_idx = 0;
srsran_dci_location_t dci_pos = {0, 0};
/// Accumulation of all PDCCH masks for the current solution (DFS path)
coreset_bitmap total_mask, current_mask;
};
using alloc_tree_dfs_t = srsran::bounded_vector<tree_node, MAX_GRANTS>;
alloc_tree_dfs_t dfs_tree, saved_dfs_tree;
srsran::span<const uint32_t> get_cce_loc_table(const alloc_record& record) const;
bool alloc_dfs_node(const alloc_record& record, uint32_t dci_idx);
bool get_next_dfs();
};
} // namespace sched_nr_impl
} // namespace srsenb
#endif // SRSRAN_SCHED_NR_PDCCH_H

@ -0,0 +1,33 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSRAN_SCHED_NR_PHY_HELPERS_H
#define SRSRAN_SCHED_NR_PHY_HELPERS_H
#include "sched_nr_common.h"
namespace srsenb {
namespace sched_nr_impl {
uint32_t get_P(uint32_t bwp_nof_prb, bool config_1_or_2);
uint32_t get_nof_rbgs(uint32_t bwp_nof_prb, uint32_t bwp_start, bool config1_or_2);
void bitmap_to_prb_array(const rbgmask_t& bitmap, uint32_t bwp_nof_prb, srsran_sch_grant_nr_t& grant);
class slot_ue;
void fill_dci_ue_cfg(const slot_ue& ue, srsran_dci_dl_nr_t& dci);
void fill_dci_ue_cfg(const slot_ue& ue, srsran_dci_ul_nr_t& dci);
} // namespace sched_nr_impl
} // namespace srsenb
#endif // SRSRAN_SCHED_NR_PHY_HELPERS_H

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save