mirror of https://github.com/PentHertz/srsLTE.git
Merge branch 'next' into agpl_next
This commit is contained in:
commit
2cda208936
|
@ -1,6 +1,6 @@
|
||||||
<!--
|
<!--
|
||||||
Before filing an issue, search for solutions here:
|
Before filing an issue, search for solutions here:
|
||||||
- srsRAN users mailing list (http://www.softwareradiosystems.com/mailman/listinfo/srsran-users)
|
- srsRAN users mailing list (https://lists.srsran.com/mailman/listinfo/srsran-users)
|
||||||
-->
|
-->
|
||||||
|
|
||||||
## Issue Description ##
|
## Issue Description ##
|
||||||
|
|
|
@ -549,6 +549,11 @@ if(CMAKE_C_COMPILER_ID MATCHES "GNU")
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --param large-function-growth=1600")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --param large-function-growth=1600")
|
||||||
endif(CMAKE_C_COMPILER_ID MATCHES "GNU")
|
endif(CMAKE_C_COMPILER_ID MATCHES "GNU")
|
||||||
|
|
||||||
|
if (EXTRA_TERM_TIMEOUT_S)
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DSRSRAN_TERM_TIMEOUT_S=${EXTRA_TERM_TIMEOUT_S}")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSRSRAN_TERM_TIMEOUT_S=${EXTRA_TERM_TIMEOUT_S}")
|
||||||
|
endif (EXTRA_TERM_TIMEOUT_S)
|
||||||
|
|
||||||
message(STATUS "CMAKE_C_FLAGS is ${CMAKE_C_FLAGS}")
|
message(STATUS "CMAKE_C_FLAGS is ${CMAKE_C_FLAGS}")
|
||||||
message(STATUS "CMAKE_CXX_FLAGS is ${CMAKE_CXX_FLAGS}")
|
message(STATUS "CMAKE_CXX_FLAGS is ${CMAKE_CXX_FLAGS}")
|
||||||
|
|
||||||
|
|
|
@ -21,4 +21,4 @@ For license details, see LICENSE file.
|
||||||
Support
|
Support
|
||||||
=======
|
=======
|
||||||
|
|
||||||
Mailing list: http://www.srs.io/mailman/listinfo/srslte-users
|
Mailing list: https://lists.srsran.com/mailman/listinfo/srsran-users
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "srsran/common/rwlock_guard.h"
|
#include "srsran/common/rwlock_guard.h"
|
||||||
#include "srsran/srslog/srslog.h"
|
#include "srsran/srslog/srslog.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <unordered_map>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
namespace srsran {
|
namespace srsran {
|
||||||
|
@ -159,7 +160,7 @@ public:
|
||||||
private:
|
private:
|
||||||
srslog::basic_logger& logger;
|
srslog::basic_logger& logger;
|
||||||
|
|
||||||
srsenb::rnti_map_t<srsran::detail::ue_bearer_manager_impl> users_map;
|
std::unordered_map<uint16_t, srsran::detail::ue_bearer_manager_impl> users_map;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace srsenb
|
} // namespace srsenb
|
||||||
|
|
|
@ -85,6 +85,7 @@ public:
|
||||||
|
|
||||||
bool bind_addr(const char* bind_addr_str, int port);
|
bool bind_addr(const char* bind_addr_str, int port);
|
||||||
bool connect_to(const char* dest_addr_str, int dest_port, sockaddr_in* dest_sockaddr = nullptr);
|
bool connect_to(const char* dest_addr_str, int dest_port, sockaddr_in* dest_sockaddr = nullptr);
|
||||||
|
bool start_listen();
|
||||||
bool open_socket(net_utils::addr_family ip, net_utils::socket_type socket_type, net_utils::protocol_type protocol);
|
bool open_socket(net_utils::addr_family ip, net_utils::socket_type socket_type, net_utils::protocol_type protocol);
|
||||||
int get_socket() const { return sockfd; };
|
int get_socket() const { return sockfd; };
|
||||||
|
|
||||||
|
@ -95,8 +96,7 @@ protected:
|
||||||
|
|
||||||
namespace net_utils {
|
namespace net_utils {
|
||||||
|
|
||||||
bool sctp_init_client(unique_socket* socket, net_utils::socket_type socktype, const char* bind_addr_str, int bind_port);
|
bool sctp_init_socket(unique_socket* socket, net_utils::socket_type socktype, const char* bind_addr_str, int bind_port);
|
||||||
bool sctp_init_server(unique_socket* socket, net_utils::socket_type socktype, const char* bind_addr_str, int port);
|
|
||||||
|
|
||||||
} // namespace net_utils
|
} // namespace net_utils
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,9 @@ const char* __tsan_default_suppressions()
|
||||||
// Lock order inversion issues in these functions, ignore it as it uses rw locks in read mode
|
// Lock order inversion issues in these functions, ignore it as it uses rw locks in read mode
|
||||||
"deadlock:srsenb::mac::rlc_buffer_state\n"
|
"deadlock:srsenb::mac::rlc_buffer_state\n"
|
||||||
"deadlock:srsenb::mac::snr_info\n"
|
"deadlock:srsenb::mac::snr_info\n"
|
||||||
"deadlock:srsenb::mac::ack_info\n";
|
"deadlock:srsenb::mac::ack_info\n"
|
||||||
|
"deadlock:srsenb::rlc::rb_is_um\n"
|
||||||
|
"deadlock:srsenb::mac::sr_detected\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -50,6 +50,7 @@ public:
|
||||||
virtual void discard_sdu(uint16_t rnti, uint32_t lcid, uint32_t sn) = 0;
|
virtual void discard_sdu(uint16_t rnti, uint32_t lcid, uint32_t sn) = 0;
|
||||||
virtual bool rb_is_um(uint16_t rnti, uint32_t lcid) = 0;
|
virtual bool rb_is_um(uint16_t rnti, uint32_t lcid) = 0;
|
||||||
virtual bool sdu_queue_is_full(uint16_t rnti, uint32_t lcid) = 0;
|
virtual bool sdu_queue_is_full(uint16_t rnti, uint32_t lcid) = 0;
|
||||||
|
virtual bool is_suspended(uint16_t rnti, uint32_t lcid) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// RLC interface for RRC
|
// RLC interface for RRC
|
||||||
|
@ -65,6 +66,7 @@ public:
|
||||||
virtual void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu) = 0;
|
virtual void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu) = 0;
|
||||||
virtual bool has_bearer(uint16_t rnti, uint32_t lcid) = 0;
|
virtual bool has_bearer(uint16_t rnti, uint32_t lcid) = 0;
|
||||||
virtual bool suspend_bearer(uint16_t rnti, uint32_t lcid) = 0;
|
virtual bool suspend_bearer(uint16_t rnti, uint32_t lcid) = 0;
|
||||||
|
virtual bool is_suspended(uint16_t rnti, uint32_t lcid) = 0;
|
||||||
virtual bool resume_bearer(uint16_t rnti, uint32_t lcid) = 0;
|
virtual bool resume_bearer(uint16_t rnti, uint32_t lcid) = 0;
|
||||||
virtual void reestablish(uint16_t rnti) = 0;
|
virtual void reestablish(uint16_t rnti) = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -40,7 +40,7 @@ struct meas_cell_cfg_t {
|
||||||
uint32_t earfcn;
|
uint32_t earfcn;
|
||||||
uint16_t pci;
|
uint16_t pci;
|
||||||
uint32_t eci;
|
uint32_t eci;
|
||||||
float q_offset;
|
asn1::rrc::q_offset_range_e cell_individual_offset;
|
||||||
uint32_t allowed_meas_bw;
|
uint32_t allowed_meas_bw;
|
||||||
bool direct_forward_path_available;
|
bool direct_forward_path_available;
|
||||||
};
|
};
|
||||||
|
|
|
@ -203,7 +203,7 @@ class mac_interface_phy_nr
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const static int MAX_SSB = 4;
|
const static int MAX_SSB = 4;
|
||||||
const static int MAX_GRANTS = 64;
|
const static int MAX_GRANTS = 32;
|
||||||
const static int MAX_PUCCH_MSG = 64;
|
const static int MAX_PUCCH_MSG = 64;
|
||||||
const static int MAX_PUCCH_CANDIDATES = 2;
|
const static int MAX_PUCCH_CANDIDATES = 2;
|
||||||
const static int MAX_NZP_CSI_RS = 4;
|
const static int MAX_NZP_CSI_RS = 4;
|
||||||
|
|
|
@ -60,6 +60,8 @@ public:
|
||||||
|
|
||||||
///< Allow PDCP to query SDU queue status
|
///< Allow PDCP to query SDU queue status
|
||||||
virtual bool sdu_queue_is_full(uint32_t lcid) = 0;
|
virtual bool sdu_queue_is_full(uint32_t lcid) = 0;
|
||||||
|
|
||||||
|
virtual bool is_suspended(const uint32_t lcid) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class rlc_interface_mac : public srsran::read_pdu_interface
|
class rlc_interface_mac : public srsran::read_pdu_interface
|
||||||
|
|
|
@ -139,4 +139,8 @@ typedef struct SRSRAN_API {
|
||||||
|
|
||||||
SRSRAN_API bool srsran_csi_rs_resource_mapping_is_valid(const srsran_csi_rs_resource_mapping_t* res);
|
SRSRAN_API bool srsran_csi_rs_resource_mapping_is_valid(const srsran_csi_rs_resource_mapping_t* res);
|
||||||
|
|
||||||
|
SRSRAN_API uint32_t srsran_csi_rs_resource_mapping_info(const srsran_csi_rs_resource_mapping_t* res,
|
||||||
|
char* str,
|
||||||
|
uint32_t str_len);
|
||||||
|
|
||||||
#endif // SRSRAN_CSI_RS_CFG_H
|
#endif // SRSRAN_CSI_RS_CFG_H
|
||||||
|
|
|
@ -48,7 +48,7 @@ srsran_csi_new_nzp_csi_rs_measurement(const srsran_csi_hl_resource_cfg_t csi_res
|
||||||
*/
|
*/
|
||||||
SRSRAN_API int srsran_csi_reports_generate(const srsran_csi_hl_cfg_t* cfg,
|
SRSRAN_API int srsran_csi_reports_generate(const srsran_csi_hl_cfg_t* cfg,
|
||||||
const srsran_slot_cfg_t* slot_cfg,
|
const srsran_slot_cfg_t* slot_cfg,
|
||||||
srsran_csi_report_cfg_t report_cfg[SRSRAN_CSI_MAX_NOF_REPORT]);
|
srsran_csi_report_cfg_t report_cfg[SRSRAN_CSI_SLOT_MAX_NOF_REPORT]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Quantifies a given set of CSI reports from the given set of measurements
|
* @brief Quantifies a given set of CSI reports from the given set of measurements
|
||||||
|
@ -58,9 +58,9 @@ SRSRAN_API int srsran_csi_reports_generate(const srsran_csi_hl_cfg_t* cfg,
|
||||||
* @return The number CSI reports for transmission if the provided data is valid, SRSRAN_ERROR code otherwise
|
* @return The number CSI reports for transmission if the provided data is valid, SRSRAN_ERROR code otherwise
|
||||||
*/
|
*/
|
||||||
SRSRAN_API int
|
SRSRAN_API int
|
||||||
srsran_csi_reports_quantify(const srsran_csi_report_cfg_t reports[SRSRAN_CSI_MAX_NOF_REPORT],
|
srsran_csi_reports_quantify(const srsran_csi_report_cfg_t reports[SRSRAN_CSI_SLOT_MAX_NOF_REPORT],
|
||||||
const srsran_csi_channel_measurements_t measurements[SRSRAN_CSI_MAX_NOF_RESOURCES],
|
const srsran_csi_channel_measurements_t measurements[SRSRAN_CSI_MAX_NOF_RESOURCES],
|
||||||
srsran_csi_report_value_t report_value[SRSRAN_CSI_MAX_NOF_REPORT]);
|
srsran_csi_report_value_t report_value[SRSRAN_CSI_SLOT_MAX_NOF_REPORT]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Compute number of CSI bits necessary to transmit all the CSI reports for a PUCCH transmission
|
* @brief Compute number of CSI bits necessary to transmit all the CSI reports for a PUCCH transmission
|
||||||
|
|
|
@ -31,6 +31,11 @@
|
||||||
*/
|
*/
|
||||||
#define SRSRAN_CSI_MAX_NOF_REPORT 48
|
#define SRSRAN_CSI_MAX_NOF_REPORT 48
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum number of supported simultaneous CSI reports in a single slot transmission
|
||||||
|
*/
|
||||||
|
#define SRSRAN_CSI_SLOT_MAX_NOF_REPORT 2
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Maximum number of CSI-RS resources defined in TS 38.331 maxNrofCSI-ResourceConfigurations
|
* @brief Maximum number of CSI-RS resources defined in TS 38.331 maxNrofCSI-ResourceConfigurations
|
||||||
*/
|
*/
|
||||||
|
@ -202,13 +207,4 @@ typedef struct SRSRAN_API {
|
||||||
};
|
};
|
||||||
} srsran_csi_report_value_t;
|
} srsran_csi_report_value_t;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Complete report configuration and value
|
|
||||||
*/
|
|
||||||
typedef struct SRSRAN_API {
|
|
||||||
srsran_csi_report_cfg_t cfg[SRSRAN_CSI_MAX_NOF_REPORT]; ///< Configuration ready for encoding
|
|
||||||
srsran_csi_report_value_t value[SRSRAN_CSI_MAX_NOF_REPORT]; ///< Quantified values
|
|
||||||
uint32_t nof_reports; ///< Total number of reports to transmit
|
|
||||||
} srsran_csi_reports_t;
|
|
||||||
|
|
||||||
#endif // SRSRAN_CSI_CFG_H
|
#endif // SRSRAN_CSI_CFG_H
|
||||||
|
|
|
@ -80,7 +80,7 @@ typedef struct SRSRAN_API {
|
||||||
srsran_harq_ack_cfg_t ack; ///< HARQ-ACK configuration
|
srsran_harq_ack_cfg_t ack; ///< HARQ-ACK configuration
|
||||||
uint32_t o_sr; ///< Number of SR bits
|
uint32_t o_sr; ///< Number of SR bits
|
||||||
bool sr_positive_present; ///< Set to true if there is at least one positive SR
|
bool sr_positive_present; ///< Set to true if there is at least one positive SR
|
||||||
srsran_csi_report_cfg_t csi[SRSRAN_CSI_MAX_NOF_REPORT]; ///< CSI report configuration
|
srsran_csi_report_cfg_t csi[SRSRAN_CSI_SLOT_MAX_NOF_REPORT]; ///< CSI report configuration
|
||||||
uint32_t nof_csi; ///< Number of CSI reports
|
uint32_t nof_csi; ///< Number of CSI reports
|
||||||
union {
|
union {
|
||||||
srsran_uci_nr_pucch_cfg_t pucch; ///< Configuration for transmission in PUCCH
|
srsran_uci_nr_pucch_cfg_t pucch; ///< Configuration for transmission in PUCCH
|
||||||
|
@ -94,7 +94,7 @@ typedef struct SRSRAN_API {
|
||||||
typedef struct SRSRAN_API {
|
typedef struct SRSRAN_API {
|
||||||
uint8_t ack[SRSRAN_HARQ_ACK_MAX_NOF_BITS]; ///< HARQ ACK feedback bits
|
uint8_t ack[SRSRAN_HARQ_ACK_MAX_NOF_BITS]; ///< HARQ ACK feedback bits
|
||||||
uint32_t sr; ///< Number of positive SR
|
uint32_t sr; ///< Number of positive SR
|
||||||
srsran_csi_report_value_t csi[SRSRAN_CSI_MAX_NOF_REPORT]; ///< Packed CSI report values
|
srsran_csi_report_value_t csi[SRSRAN_CSI_SLOT_MAX_NOF_REPORT]; ///< Packed CSI report values
|
||||||
bool valid; ///< Indicates whether the message has been decoded successfully, ignored in the transmitter
|
bool valid; ///< Indicates whether the message has been decoded successfully, ignored in the transmitter
|
||||||
} srsran_uci_value_nr_t;
|
} srsran_uci_value_nr_t;
|
||||||
|
|
||||||
|
|
|
@ -182,6 +182,9 @@ private:
|
||||||
*/
|
*/
|
||||||
bool tx_dev(const uint32_t& device_idx, rf_buffer_interface& buffer, const srsran_timestamp_t& tx_time_);
|
bool tx_dev(const uint32_t& device_idx, rf_buffer_interface& buffer, const srsran_timestamp_t& tx_time_);
|
||||||
|
|
||||||
|
// private unprotected tx_end implementation
|
||||||
|
void tx_end_nolock();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method for receiving over a single RF device. This function maps automatically the logical receive buffers
|
* Helper method for receiving over a single RF device. This function maps automatically the logical receive buffers
|
||||||
* to the physical RF buffers for the given device.
|
* to the physical RF buffers for the given device.
|
||||||
|
|
|
@ -68,6 +68,7 @@ public:
|
||||||
// MAC interface
|
// MAC interface
|
||||||
bool has_data_locked(const uint32_t lcid);
|
bool has_data_locked(const uint32_t lcid);
|
||||||
uint32_t get_buffer_state(const uint32_t lcid);
|
uint32_t get_buffer_state(const uint32_t lcid);
|
||||||
|
void get_buffer_state(uint32_t lcid, uint32_t& tx_queue, uint32_t& prio_tx_queue);
|
||||||
uint32_t get_total_mch_buffer_state(uint32_t lcid);
|
uint32_t get_total_mch_buffer_state(uint32_t lcid);
|
||||||
uint32_t read_pdu(uint32_t lcid, uint8_t* payload, uint32_t nof_bytes);
|
uint32_t read_pdu(uint32_t lcid, uint8_t* payload, uint32_t nof_bytes);
|
||||||
uint32_t read_pdu_mch(uint32_t lcid, uint8_t* payload, uint32_t nof_bytes);
|
uint32_t read_pdu_mch(uint32_t lcid, uint8_t* payload, uint32_t nof_bytes);
|
||||||
|
|
|
@ -355,6 +355,7 @@ public:
|
||||||
// MAC interface
|
// MAC interface
|
||||||
bool has_data();
|
bool has_data();
|
||||||
uint32_t get_buffer_state();
|
uint32_t get_buffer_state();
|
||||||
|
void get_buffer_state(uint32_t& tx_queue, uint32_t& prio_tx_queue);
|
||||||
uint32_t read_pdu(uint8_t* payload, uint32_t nof_bytes);
|
uint32_t read_pdu(uint8_t* payload, uint32_t nof_bytes);
|
||||||
void write_pdu(uint8_t* payload, uint32_t nof_bytes);
|
void write_pdu(uint8_t* payload, uint32_t nof_bytes);
|
||||||
|
|
||||||
|
@ -384,6 +385,7 @@ private:
|
||||||
|
|
||||||
bool has_data();
|
bool has_data();
|
||||||
uint32_t get_buffer_state();
|
uint32_t get_buffer_state();
|
||||||
|
void get_buffer_state(uint32_t& new_tx, uint32_t& prio_tx);
|
||||||
|
|
||||||
// Timeout callback interface
|
// Timeout callback interface
|
||||||
void timer_expired(uint32_t timeout_id);
|
void timer_expired(uint32_t timeout_id);
|
||||||
|
@ -394,6 +396,8 @@ private:
|
||||||
void set_bsr_callback(bsr_callback_t callback);
|
void set_bsr_callback(bsr_callback_t callback);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void stop_nolock();
|
||||||
|
|
||||||
int build_status_pdu(uint8_t* payload, uint32_t nof_bytes);
|
int build_status_pdu(uint8_t* payload, uint32_t nof_bytes);
|
||||||
int build_retx_pdu(uint8_t* payload, uint32_t nof_bytes);
|
int build_retx_pdu(uint8_t* payload, uint32_t nof_bytes);
|
||||||
int build_segment(uint8_t* payload, uint32_t nof_bytes, rlc_amd_retx_t retx);
|
int build_segment(uint8_t* payload, uint32_t nof_bytes, rlc_amd_retx_t retx);
|
||||||
|
|
|
@ -282,6 +282,7 @@ public:
|
||||||
virtual bool has_data() = 0;
|
virtual bool has_data() = 0;
|
||||||
bool is_suspended() { return suspended; };
|
bool is_suspended() { return suspended; };
|
||||||
virtual uint32_t get_buffer_state() = 0;
|
virtual uint32_t get_buffer_state() = 0;
|
||||||
|
virtual void get_buffer_state(uint32_t& tx_queue, uint32_t& prio_tx_queue) = 0;
|
||||||
virtual uint32_t read_pdu(uint8_t* payload, uint32_t nof_bytes) = 0;
|
virtual uint32_t read_pdu(uint8_t* payload, uint32_t nof_bytes) = 0;
|
||||||
virtual void write_pdu(uint8_t* payload, uint32_t nof_bytes) = 0;
|
virtual void write_pdu(uint8_t* payload, uint32_t nof_bytes) = 0;
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,7 @@ public:
|
||||||
// MAC interface
|
// MAC interface
|
||||||
bool has_data() override;
|
bool has_data() override;
|
||||||
uint32_t get_buffer_state() override;
|
uint32_t get_buffer_state() override;
|
||||||
|
void get_buffer_state(uint32_t& newtx_queue, uint32_t& prio_tx_queue) override;
|
||||||
uint32_t read_pdu(uint8_t* payload, uint32_t nof_bytes) override;
|
uint32_t read_pdu(uint8_t* payload, uint32_t nof_bytes) override;
|
||||||
void write_pdu(uint8_t* payload, uint32_t nof_bytes) override;
|
void write_pdu(uint8_t* payload, uint32_t nof_bytes) override;
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,7 @@ public:
|
||||||
// MAC interface
|
// MAC interface
|
||||||
bool has_data();
|
bool has_data();
|
||||||
uint32_t get_buffer_state();
|
uint32_t get_buffer_state();
|
||||||
|
void get_buffer_state(uint32_t& newtx_queue, uint32_t& prio_tx_queue);
|
||||||
uint32_t read_pdu(uint8_t* payload, uint32_t nof_bytes);
|
uint32_t read_pdu(uint8_t* payload, uint32_t nof_bytes);
|
||||||
void write_pdu(uint8_t* payload, uint32_t nof_bytes);
|
void write_pdu(uint8_t* payload, uint32_t nof_bytes);
|
||||||
int get_increment_sequence_num();
|
int get_increment_sequence_num();
|
||||||
|
|
|
@ -127,12 +127,13 @@ void enb_bearer_manager::add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, sr
|
||||||
auto user_it = users_map.find(rnti);
|
auto user_it = users_map.find(rnti);
|
||||||
if (user_it == users_map.end()) {
|
if (user_it == users_map.end()) {
|
||||||
// add empty bearer map
|
// add empty bearer map
|
||||||
auto p = users_map.insert(rnti, srsran::detail::ue_bearer_manager_impl{});
|
// users_map.emplace( ) returns pair<iterator,bool>
|
||||||
if (!p) {
|
auto p = users_map.emplace( rnti, srsran::detail::ue_bearer_manager_impl{});
|
||||||
|
if (!p.second) {
|
||||||
logger.error("Bearers: Unable to add a new bearer map for rnti=0x%x", rnti);
|
logger.error("Bearers: Unable to add a new bearer map for rnti=0x%x", rnti);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
user_it = p.value();
|
user_it = p.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user_it->second.add_eps_bearer(eps_bearer_id, rat, lcid)) {
|
if (user_it->second.add_eps_bearer(eps_bearer_id, rat, lcid)) {
|
||||||
|
|
|
@ -204,6 +204,8 @@ bool bind_addr(int fd, const sockaddr_in& addr_in)
|
||||||
perror("bind()");
|
perror("bind()");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
srslog::fetch_basic_logger(LOGSERVICE)
|
||||||
|
.debug("Successfully bound to address %s:%d", get_ip(addr_in).c_str(), get_port(addr_in));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,7 +217,11 @@ bool bind_addr(int fd, const char* bind_addr_str, int port, sockaddr_in* addr_re
|
||||||
.error("Failed to convert IP address (%s) to sockaddr_in struct", bind_addr_str);
|
.error("Failed to convert IP address (%s) to sockaddr_in struct", bind_addr_str);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bind_addr(fd, addr_tmp);
|
|
||||||
|
if (not bind_addr(fd, addr_tmp)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (addr_result != nullptr) {
|
if (addr_result != nullptr) {
|
||||||
*addr_result = addr_tmp;
|
*addr_result = addr_tmp;
|
||||||
}
|
}
|
||||||
|
@ -245,6 +251,22 @@ bool connect_to(int fd, const char* dest_addr_str, int dest_port, sockaddr_in* d
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool start_listen(int fd)
|
||||||
|
{
|
||||||
|
if (fd < 0) {
|
||||||
|
srslog::fetch_basic_logger(LOGSERVICE).error("Tried to listen for connections with an invalid socket.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen for connections
|
||||||
|
if (listen(fd, SOMAXCONN) != 0) {
|
||||||
|
srslog::fetch_basic_logger(LOGSERVICE).error("Failed to listen to incoming SCTP connections");
|
||||||
|
perror("listen()");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace net_utils
|
} // namespace net_utils
|
||||||
|
|
||||||
/********************************************
|
/********************************************
|
||||||
|
@ -269,6 +291,18 @@ unique_socket& unique_socket::operator=(unique_socket&& other) noexcept
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool unique_socket::open_socket(net_utils::addr_family ip_type,
|
||||||
|
net_utils::socket_type socket_type,
|
||||||
|
net_utils::protocol_type protocol)
|
||||||
|
{
|
||||||
|
if (is_open()) {
|
||||||
|
srslog::fetch_basic_logger(LOGSERVICE).error("Socket is already open.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
sockfd = net_utils::open_socket(ip_type, socket_type, protocol);
|
||||||
|
return is_open();
|
||||||
|
}
|
||||||
|
|
||||||
void unique_socket::close()
|
void unique_socket::close()
|
||||||
{
|
{
|
||||||
if (sockfd >= 0) {
|
if (sockfd >= 0) {
|
||||||
|
@ -288,16 +322,9 @@ bool unique_socket::connect_to(const char* dest_addr_str, int dest_port, sockadd
|
||||||
return net_utils::connect_to(sockfd, dest_addr_str, dest_port, dest_sockaddr);
|
return net_utils::connect_to(sockfd, dest_addr_str, dest_port, dest_sockaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool unique_socket::open_socket(net_utils::addr_family ip_type,
|
bool unique_socket::start_listen()
|
||||||
net_utils::socket_type socket_type,
|
|
||||||
net_utils::protocol_type protocol)
|
|
||||||
{
|
{
|
||||||
if (is_open()) {
|
return net_utils::start_listen(sockfd);
|
||||||
srslog::fetch_basic_logger(LOGSERVICE).error("Socket is already open.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
sockfd = net_utils::open_socket(ip_type, socket_type, protocol);
|
|
||||||
return is_open();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -306,36 +333,18 @@ bool unique_socket::open_socket(net_utils::addr_family ip_type,
|
||||||
|
|
||||||
namespace net_utils {
|
namespace net_utils {
|
||||||
|
|
||||||
bool sctp_init_socket(unique_socket* socket, net_utils::socket_type socktype, const char* bind_addr_str, int port)
|
bool sctp_init_socket(unique_socket* socket, net_utils::socket_type socktype, const char* bind_addr_str, int bind_port)
|
||||||
{
|
{
|
||||||
if (not socket->open_socket(net_utils::addr_family::ipv4, socktype, net_utils::protocol_type::SCTP)) {
|
if (not socket->open_socket(net_utils::addr_family::ipv4, socktype, net_utils::protocol_type::SCTP)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (not socket->bind_addr(bind_addr_str, port)) {
|
if (not socket->bind_addr(bind_addr_str, bind_port)) {
|
||||||
socket->close();
|
socket->close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sctp_init_client(unique_socket* socket, net_utils::socket_type socktype, const char* bind_addr_str, int bind_port)
|
|
||||||
{
|
|
||||||
return sctp_init_socket(socket, socktype, bind_addr_str, bind_port);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sctp_init_server(unique_socket* socket, net_utils::socket_type socktype, const char* bind_addr_str, int port)
|
|
||||||
{
|
|
||||||
if (not sctp_init_socket(socket, socktype, bind_addr_str, port)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Listen for connections
|
|
||||||
if (listen(socket->fd(), SOMAXCONN) != 0) {
|
|
||||||
srslog::fetch_basic_logger(LOGSERVICE).error("Failed to listen to incoming SCTP connections");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace net_utils
|
} // namespace net_utils
|
||||||
|
|
||||||
/***************************************************************
|
/***************************************************************
|
||||||
|
|
|
@ -282,9 +282,13 @@ void phy_cfg_nr_default_t::make_pusch_default(srsran_sch_hl_cfg_nr_t& pusch)
|
||||||
pusch.typeA_pos = srsran_dmrs_sch_typeA_pos_2;
|
pusch.typeA_pos = srsran_dmrs_sch_typeA_pos_2;
|
||||||
|
|
||||||
pusch.scaling = 1.0f;
|
pusch.scaling = 1.0f;
|
||||||
pusch.beta_offsets.fix_ack = 12.625f;
|
pusch.beta_offsets.ack_index1 = 9;
|
||||||
pusch.beta_offsets.fix_csi1 = 2.25f;
|
pusch.beta_offsets.ack_index2 = 9;
|
||||||
pusch.beta_offsets.fix_csi2 = 2.25f;
|
pusch.beta_offsets.ack_index3 = 9;
|
||||||
|
pusch.beta_offsets.csi1_index1 = 6;
|
||||||
|
pusch.beta_offsets.csi1_index2 = 6;
|
||||||
|
pusch.beta_offsets.csi2_index1 = 6;
|
||||||
|
pusch.beta_offsets.csi2_index2 = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
void phy_cfg_nr_default_t::make_pucch_custom_one(srsran_pucch_nr_hl_cfg_t& pucch)
|
void phy_cfg_nr_default_t::make_pucch_custom_one(srsran_pucch_nr_hl_cfg_t& pucch)
|
||||||
|
|
|
@ -148,6 +148,11 @@ void pdcp_entity_lte::write_sdu(unique_byte_buffer_t sdu, int upper_sn)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rlc->is_suspended(lcid)) {
|
||||||
|
logger.warning("Trying to send SDU while re-establishment is in progress. Dropping SDU. LCID=%d", lcid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (rlc->sdu_queue_is_full(lcid)) {
|
if (rlc->sdu_queue_is_full(lcid)) {
|
||||||
logger.info(sdu->msg, sdu->N_bytes, "Dropping %s SDU due to full queue", rrc->get_rb_name(lcid));
|
logger.info(sdu->msg, sdu->N_bytes, "Dropping %s SDU due to full queue", rrc->get_rb_name(lcid));
|
||||||
return;
|
return;
|
||||||
|
@ -175,7 +180,6 @@ void pdcp_entity_lte::write_sdu(unique_byte_buffer_t sdu, int upper_sn)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for pending security config in transmit direction
|
// check for pending security config in transmit direction
|
||||||
if (enable_security_tx_sn != -1 && enable_security_tx_sn == static_cast<int32_t>(tx_count)) {
|
if (enable_security_tx_sn != -1 && enable_security_tx_sn == static_cast<int32_t>(tx_count)) {
|
||||||
enable_integrity(DIRECTION_TX);
|
enable_integrity(DIRECTION_TX);
|
||||||
|
|
|
@ -37,6 +37,13 @@
|
||||||
*/
|
*/
|
||||||
#define CSI_RS_MAX_SYMBOLS_SLOT 4
|
#define CSI_RS_MAX_SYMBOLS_SLOT 4
|
||||||
|
|
||||||
|
#define RESOURCE_ERROR(R) \
|
||||||
|
do { \
|
||||||
|
char res_info_str[256]; \
|
||||||
|
srsran_csi_rs_resource_mapping_info(R, res_info_str, (uint32_t)sizeof(res_info_str)); \
|
||||||
|
ERROR("Unhandled configuration %s", res_info_str); \
|
||||||
|
} while (false)
|
||||||
|
|
||||||
static int csi_rs_location_f(const srsran_csi_rs_resource_mapping_t* resource, uint32_t i)
|
static int csi_rs_location_f(const srsran_csi_rs_resource_mapping_t* resource, uint32_t i)
|
||||||
{
|
{
|
||||||
uint32_t count = 0;
|
uint32_t count = 0;
|
||||||
|
@ -69,7 +76,8 @@ static int csi_rs_location_f(const srsran_csi_rs_resource_mapping_t* resource, u
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ERROR("Unhandled configuration");
|
// Inform about an unhandled configuration
|
||||||
|
RESOURCE_ERROR(resource);
|
||||||
return SRSRAN_ERROR;
|
return SRSRAN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +130,8 @@ static int csi_rs_location_get_k_list(const srsran_csi_rs_resource_mapping_t* re
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ERROR("Unhandled configuration");
|
// Inform about an unhandled configuration
|
||||||
|
RESOURCE_ERROR(resource);
|
||||||
return SRSRAN_ERROR;
|
return SRSRAN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,7 +181,8 @@ static int csi_rs_location_get_l_list(const srsran_csi_rs_resource_mapping_t* re
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ERROR("Unhandled configuration");
|
// Inform about an unhandled configuration
|
||||||
|
RESOURCE_ERROR(resource);
|
||||||
return SRSRAN_ERROR;
|
return SRSRAN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,7 +235,8 @@ static int csi_rs_nof_cdm_groups(const srsran_csi_rs_resource_mapping_t* resourc
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
ERROR("Unhandled configuration");
|
// Inform about an unhandled configuration
|
||||||
|
RESOURCE_ERROR(resource);
|
||||||
return SRSRAN_ERROR;
|
return SRSRAN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,6 +263,89 @@ bool srsran_csi_rs_resource_mapping_is_valid(const srsran_csi_rs_resource_mappin
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t srsran_csi_rs_resource_mapping_info(const srsran_csi_rs_resource_mapping_t* res, char* str, uint32_t str_len)
|
||||||
|
{
|
||||||
|
uint32_t len = 0;
|
||||||
|
|
||||||
|
const char* row_str = "invalid";
|
||||||
|
uint32_t nof_freq_domain = 0;
|
||||||
|
switch (res->row) {
|
||||||
|
case srsran_csi_rs_resource_mapping_row_1:
|
||||||
|
row_str = "1";
|
||||||
|
nof_freq_domain = SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_ROW1;
|
||||||
|
break;
|
||||||
|
case srsran_csi_rs_resource_mapping_row_2:
|
||||||
|
row_str = "2";
|
||||||
|
nof_freq_domain = SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_ROW2;
|
||||||
|
break;
|
||||||
|
case srsran_csi_rs_resource_mapping_row_4:
|
||||||
|
row_str = "4";
|
||||||
|
nof_freq_domain = SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_ROW4;
|
||||||
|
break;
|
||||||
|
case srsran_csi_rs_resource_mapping_row_other:
|
||||||
|
row_str = "other";
|
||||||
|
nof_freq_domain = SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_OTHER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* cdm_str = "invalid";
|
||||||
|
switch (res->cdm) {
|
||||||
|
case srsran_csi_rs_cdm_nocdm:
|
||||||
|
cdm_str = "nocdm";
|
||||||
|
break;
|
||||||
|
case srsran_csi_rs_cdm_fd_cdm2:
|
||||||
|
cdm_str = "FD-CDM2";
|
||||||
|
break;
|
||||||
|
case srsran_csi_rs_cdm_cdm4_fd2_td2:
|
||||||
|
cdm_str = "CDM4-FD2-TD2";
|
||||||
|
break;
|
||||||
|
case srsran_csi_rs_cdm_cdm8_fd2_td4:
|
||||||
|
cdm_str = "CDM8-FD2-TD4";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* density_str = "invalid";
|
||||||
|
switch (res->density) {
|
||||||
|
case srsran_csi_rs_resource_mapping_density_three:
|
||||||
|
density_str = "3";
|
||||||
|
break;
|
||||||
|
case srsran_csi_rs_resource_mapping_density_dot5_even:
|
||||||
|
density_str = ".5 (even)";
|
||||||
|
break;
|
||||||
|
case srsran_csi_rs_resource_mapping_density_dot5_odd:
|
||||||
|
density_str = ".5 (odd)";
|
||||||
|
break;
|
||||||
|
case srsran_csi_rs_resource_mapping_density_one:
|
||||||
|
density_str = "1";
|
||||||
|
break;
|
||||||
|
case srsran_csi_rs_resource_mapping_density_spare:
|
||||||
|
density_str = "spare";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
char frequency_domain_alloc[SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_MAX + 1];
|
||||||
|
srsran_vec_sprint_bin(frequency_domain_alloc,
|
||||||
|
SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_MAX + 1,
|
||||||
|
(uint8_t*)res->frequency_domain_alloc,
|
||||||
|
nof_freq_domain);
|
||||||
|
|
||||||
|
len = srsran_print_check(str,
|
||||||
|
str_len,
|
||||||
|
len,
|
||||||
|
"row=%s freq=%s nof_ports=%d fist_symb=%d fist_symb2=%d cdm=%s density=%s rb=(%d:%d)",
|
||||||
|
row_str,
|
||||||
|
frequency_domain_alloc,
|
||||||
|
res->nof_ports,
|
||||||
|
res->first_symbol_idx,
|
||||||
|
res->first_symbol_idx2,
|
||||||
|
cdm_str,
|
||||||
|
density_str,
|
||||||
|
res->freq_band.start_rb,
|
||||||
|
res->freq_band.start_rb + res->freq_band.nof_rb - 1);
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t csi_rs_count(srsran_csi_rs_density_t density, uint32_t nprb)
|
uint32_t csi_rs_count(srsran_csi_rs_density_t density, uint32_t nprb)
|
||||||
{
|
{
|
||||||
switch (density) {
|
switch (density) {
|
||||||
|
@ -677,6 +771,7 @@ int srsran_csi_rs_nzp_measure_trs(const srsran_carrier_nr_t* carrier,
|
||||||
int ret = csi_rs_nzp_measure_set(carrier, slot_cfg, set, grid, measurements);
|
int ret = csi_rs_nzp_measure_set(carrier, slot_cfg, set, grid, measurements);
|
||||||
if (ret < SRSRAN_SUCCESS) {
|
if (ret < SRSRAN_SUCCESS) {
|
||||||
ERROR("Error performing measurements");
|
ERROR("Error performing measurements");
|
||||||
|
return SRSRAN_ERROR;
|
||||||
}
|
}
|
||||||
uint32_t count = (uint32_t)ret;
|
uint32_t count = (uint32_t)ret;
|
||||||
|
|
||||||
|
@ -772,6 +867,7 @@ int srsran_csi_rs_nzp_measure_channel(const srsran_carrier_nr_t* carrier
|
||||||
int ret = csi_rs_nzp_measure_set(carrier, slot_cfg, set, grid, measurements);
|
int ret = csi_rs_nzp_measure_set(carrier, slot_cfg, set, grid, measurements);
|
||||||
if (ret < SRSRAN_SUCCESS) {
|
if (ret < SRSRAN_SUCCESS) {
|
||||||
ERROR("Error performing measurements");
|
ERROR("Error performing measurements");
|
||||||
|
return SRSRAN_ERROR;
|
||||||
}
|
}
|
||||||
uint32_t count = (uint32_t)ret;
|
uint32_t count = (uint32_t)ret;
|
||||||
|
|
||||||
|
|
|
@ -188,7 +188,7 @@ int srsran_csi_new_nzp_csi_rs_measurement(
|
||||||
|
|
||||||
int srsran_csi_reports_generate(const srsran_csi_hl_cfg_t* cfg,
|
int srsran_csi_reports_generate(const srsran_csi_hl_cfg_t* cfg,
|
||||||
const srsran_slot_cfg_t* slot_cfg,
|
const srsran_slot_cfg_t* slot_cfg,
|
||||||
srsran_csi_report_cfg_t report_cfg[SRSRAN_CSI_MAX_NOF_REPORT])
|
srsran_csi_report_cfg_t report_cfg[SRSRAN_CSI_SLOT_MAX_NOF_REPORT])
|
||||||
{
|
{
|
||||||
uint32_t count = 0;
|
uint32_t count = 0;
|
||||||
|
|
||||||
|
@ -198,7 +198,7 @@ int srsran_csi_reports_generate(const srsran_csi_hl_cfg_t* cfg,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure report configuration is initialised to zero
|
// Make sure report configuration is initialised to zero
|
||||||
SRSRAN_MEM_ZERO(report_cfg, srsran_csi_report_cfg_t, SRSRAN_CSI_MAX_NOF_REPORT);
|
SRSRAN_MEM_ZERO(report_cfg, srsran_csi_report_cfg_t, SRSRAN_CSI_SLOT_MAX_NOF_REPORT);
|
||||||
|
|
||||||
// Iterate every possible configured CSI report
|
// Iterate every possible configured CSI report
|
||||||
for (uint32_t i = 0; i < SRSRAN_CSI_MAX_NOF_REPORT; i++) {
|
for (uint32_t i = 0; i < SRSRAN_CSI_MAX_NOF_REPORT; i++) {
|
||||||
|
@ -207,6 +207,13 @@ int srsran_csi_reports_generate(const srsran_csi_hl_cfg_t* cfg,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (count >= SRSRAN_CSI_SLOT_MAX_NOF_REPORT) {
|
||||||
|
ERROR("The number of CSI reports in the slot (%d) exceeds the maximum (%d)",
|
||||||
|
count++,
|
||||||
|
SRSRAN_CSI_SLOT_MAX_NOF_REPORT);
|
||||||
|
return SRSRAN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
// Configure report
|
// Configure report
|
||||||
report_cfg[count].cfg = cfg->reports[i];
|
report_cfg[count].cfg = cfg->reports[i];
|
||||||
report_cfg[count].nof_ports = 1;
|
report_cfg[count].nof_ports = 1;
|
||||||
|
@ -218,9 +225,9 @@ int srsran_csi_reports_generate(const srsran_csi_hl_cfg_t* cfg,
|
||||||
return (int)count;
|
return (int)count;
|
||||||
}
|
}
|
||||||
|
|
||||||
int srsran_csi_reports_quantify(const srsran_csi_report_cfg_t reports[SRSRAN_CSI_MAX_NOF_REPORT],
|
int srsran_csi_reports_quantify(const srsran_csi_report_cfg_t reports[SRSRAN_CSI_SLOT_MAX_NOF_REPORT],
|
||||||
const srsran_csi_channel_measurements_t measurements[SRSRAN_CSI_MAX_NOF_RESOURCES],
|
const srsran_csi_channel_measurements_t measurements[SRSRAN_CSI_MAX_NOF_RESOURCES],
|
||||||
srsran_csi_report_value_t report_value[SRSRAN_CSI_MAX_NOF_REPORT])
|
srsran_csi_report_value_t report_value[SRSRAN_CSI_SLOT_MAX_NOF_REPORT])
|
||||||
{
|
{
|
||||||
uint32_t count = 0;
|
uint32_t count = 0;
|
||||||
|
|
||||||
|
@ -230,7 +237,7 @@ int srsran_csi_reports_quantify(const srsran_csi_report_cfg_t reports[
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate every possible configured CSI report
|
// Iterate every possible configured CSI report
|
||||||
for (uint32_t i = 0; i < SRSRAN_CSI_MAX_NOF_REPORT; i++) {
|
for (uint32_t i = 0; i < SRSRAN_CSI_SLOT_MAX_NOF_REPORT; i++) {
|
||||||
// If the report is the last one, break
|
// If the report is the last one, break
|
||||||
if (reports->cfg.type == SRSRAN_CSI_REPORT_TYPE_NONE) {
|
if (reports->cfg.type == SRSRAN_CSI_REPORT_TYPE_NONE) {
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -387,13 +387,11 @@ static int pusch_nr_gen_mux_uci(srsran_pusch_nr_t* q, const srsran_uci_cfg_nr_t*
|
||||||
// the number of reserved resource elements for potential HARQ-ACK transmission is calculated according to Clause
|
// the number of reserved resource elements for potential HARQ-ACK transmission is calculated according to Clause
|
||||||
// 6.3.2.4.2.1, by setting O_ACK = 2 ;
|
// 6.3.2.4.2.1, by setting O_ACK = 2 ;
|
||||||
G_ack_rvd = srsran_uci_nr_pusch_ack_nof_bits(&cfg->pusch, 2);
|
G_ack_rvd = srsran_uci_nr_pusch_ack_nof_bits(&cfg->pusch, 2);
|
||||||
|
|
||||||
// Disable non reserved HARQ-ACK bits
|
|
||||||
G_ack = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Counters
|
// Counters
|
||||||
uint32_t m_ack_count = 0;
|
uint32_t m_ack_count = 0;
|
||||||
|
uint32_t m_rvd_count = 0;
|
||||||
uint32_t m_csi1_count = 0;
|
uint32_t m_csi1_count = 0;
|
||||||
uint32_t m_csi2_count = 0;
|
uint32_t m_csi2_count = 0;
|
||||||
uint32_t m_ulsch_count = 0;
|
uint32_t m_ulsch_count = 0;
|
||||||
|
@ -420,15 +418,26 @@ static int pusch_nr_gen_mux_uci(srsran_pusch_nr_t* q, const srsran_uci_cfg_nr_t*
|
||||||
// Compute HARQ-ACK bits multiplexing
|
// Compute HARQ-ACK bits multiplexing
|
||||||
uint32_t ack_d = 0;
|
uint32_t ack_d = 0;
|
||||||
uint32_t ack_m_re_count = 0;
|
uint32_t ack_m_re_count = 0;
|
||||||
|
uint32_t rvd_d = 0;
|
||||||
|
uint32_t rvd_m_re_count = 0;
|
||||||
if (l >= l1) {
|
if (l >= l1) {
|
||||||
if (cfg->ack.count <= 2 && m_ack_count < G_ack_rvd) {
|
if (cfg->ack.count <= 2 && m_rvd_count < G_ack_rvd) {
|
||||||
ack_d = 1;
|
rvd_d = 1;
|
||||||
ack_m_re_count = M_ulsch_sc;
|
rvd_m_re_count = M_ulsch_sc;
|
||||||
if (G_ack_rvd - m_ack_count < M_uci_sc * Nl * Qm) {
|
if (G_ack_rvd - m_rvd_count < M_uci_sc * Nl * Qm) {
|
||||||
ack_d = (M_uci_sc * Nl * Qm) / (G_ack_rvd - m_ack_count);
|
rvd_d = (M_uci_sc * Nl * Qm) / (G_ack_rvd - m_rvd_count);
|
||||||
ack_m_re_count = SRSRAN_CEIL(G_ack_rvd - m_ack_count, Nl * Qm);
|
rvd_m_re_count = SRSRAN_CEIL(G_ack_rvd - m_rvd_count, Nl * Qm);
|
||||||
|
}
|
||||||
|
M_uci_rvd = rvd_m_re_count;
|
||||||
|
|
||||||
|
if (m_ack_count < G_ack) {
|
||||||
|
ack_d = 1;
|
||||||
|
ack_m_re_count = M_uci_rvd;
|
||||||
|
if (G_ack - m_ack_count < M_uci_rvd * Nl * Qm) {
|
||||||
|
ack_d = (M_uci_rvd * Nl * Qm) / (G_ack - m_ack_count);
|
||||||
|
ack_m_re_count = SRSRAN_CEIL(G_ack - m_ack_count, Nl * Qm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
M_uci_rvd = ack_m_re_count;
|
|
||||||
} else if (m_ack_count < G_ack) {
|
} else if (m_ack_count < G_ack) {
|
||||||
ack_d = 1;
|
ack_d = 1;
|
||||||
ack_m_re_count = M_ulsch_sc;
|
ack_m_re_count = M_ulsch_sc;
|
||||||
|
@ -469,14 +478,14 @@ static int pusch_nr_gen_mux_uci(srsran_pusch_nr_t* q, const srsran_uci_cfg_nr_t*
|
||||||
// Leave the rest for UL-SCH
|
// Leave the rest for UL-SCH
|
||||||
uint32_t ulsch_m_re_count = M_uci_sc;
|
uint32_t ulsch_m_re_count = M_uci_sc;
|
||||||
|
|
||||||
for (uint32_t i = 0, csi1_i = 0, csi2_i = 0; i < cfg->pusch.M_pusch_sc[l]; i++) {
|
for (uint32_t i = 0, csi1_i = 0, csi2_i = 0, rvd_i = 0; i < cfg->pusch.M_pusch_sc[l]; i++) {
|
||||||
// Check if RE is reserved for ACK
|
// Check if RE is reserved
|
||||||
bool reserved = false;
|
bool reserved = false;
|
||||||
if (ack_m_re_count != 0 && i % ack_d == 0 && m_ack_count < G_ack_rvd) {
|
if (rvd_m_re_count != 0 && i % rvd_d == 0 && m_rvd_count < G_ack_rvd) {
|
||||||
reserved = true;
|
reserved = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ack_m_re_count != 0 && i % ack_d == 0 && m_ack_count < G_ack) {
|
if (G_ack_rvd == 0 && ack_m_re_count != 0 && i % ack_d == 0 && m_ack_count < G_ack) {
|
||||||
for (uint32_t j = 0; j < Nl * Qm; j++) {
|
for (uint32_t j = 0; j < Nl * Qm; j++) {
|
||||||
pos_ack[m_ack_count++] = m_all_count + j;
|
pos_ack[m_ack_count++] = m_all_count + j;
|
||||||
}
|
}
|
||||||
|
@ -507,15 +516,16 @@ static int pusch_nr_gen_mux_uci(srsran_pusch_nr_t* q, const srsran_uci_cfg_nr_t*
|
||||||
|
|
||||||
// Set reserved bits only if there are ACK bits
|
// Set reserved bits only if there are ACK bits
|
||||||
if (reserved) {
|
if (reserved) {
|
||||||
if (cfg->ack.count > 0) {
|
if (ack_m_re_count != 0 && rvd_i % ack_d == 0 && m_ack_count < G_ack) {
|
||||||
for (uint32_t j = 0; j < Nl * Qm; j++) {
|
for (uint32_t j = 0; j < Nl * Qm; j++) {
|
||||||
pos_ack[m_ack_count++] = m_all_count + j;
|
pos_ack[m_ack_count++] = m_all_count + j;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
m_ack_count += Nl * Qm;
|
|
||||||
}
|
|
||||||
ack_m_re_count--;
|
ack_m_re_count--;
|
||||||
}
|
}
|
||||||
|
m_rvd_count += Nl * Qm;
|
||||||
|
rvd_m_re_count--;
|
||||||
|
rvd_i++;
|
||||||
|
}
|
||||||
|
|
||||||
// Increment all bit counter
|
// Increment all bit counter
|
||||||
m_all_count += Nl * Qm;
|
m_all_count += Nl * Qm;
|
||||||
|
@ -540,8 +550,8 @@ static int pusch_nr_gen_mux_uci(srsran_pusch_nr_t* q, const srsran_uci_cfg_nr_t*
|
||||||
q->G_ulsch = m_ulsch_count;
|
q->G_ulsch = m_ulsch_count;
|
||||||
|
|
||||||
// Assert Number of bits
|
// Assert Number of bits
|
||||||
if (G_ack_rvd != 0 && G_ack_rvd != m_ack_count && cfg->ack.count > 0) {
|
if (G_ack_rvd != 0 && G_ack_rvd != m_rvd_count && cfg->ack.count <= 2) {
|
||||||
ERROR("Not matched %d!=%d", G_ack_rvd, m_ack_count);
|
ERROR("Not matched %d!=%d", G_ack_rvd, m_rvd_count);
|
||||||
}
|
}
|
||||||
if (G_ack != 0 && G_ack != m_ack_count) {
|
if (G_ack != 0 && G_ack != m_ack_count) {
|
||||||
ERROR("Not matched %d!=%d", G_ack, m_ack_count);
|
ERROR("Not matched %d!=%d", G_ack, m_ack_count);
|
||||||
|
@ -1063,11 +1073,12 @@ uint32_t srsran_pusch_nr_rx_info(const srsran_pusch_nr_t* q,
|
||||||
len += pusch_nr_grant_info(q, cfg, grant, res, &str[len], str_len - len);
|
len += pusch_nr_grant_info(q, cfg, grant, res, &str[len], str_len - len);
|
||||||
|
|
||||||
if (res != NULL && srsran_uci_nr_total_bits(&cfg->uci) > 0) {
|
if (res != NULL && srsran_uci_nr_total_bits(&cfg->uci) > 0) {
|
||||||
len = srsran_print_check(str, str_len, len, "UCI: ");
|
|
||||||
srsran_uci_data_nr_t uci_data = {};
|
srsran_uci_data_nr_t uci_data = {};
|
||||||
uci_data.cfg = cfg->uci;
|
uci_data.cfg = cfg->uci;
|
||||||
uci_data.value = res->uci;
|
uci_data.value = res->uci;
|
||||||
len += srsran_uci_nr_info(&uci_data, &str[len], str_len - len);
|
len += srsran_uci_nr_info(&uci_data, &str[len], str_len - len);
|
||||||
|
|
||||||
|
len = srsran_print_check(str, str_len, len, "valid=%c ", res->uci.valid ? 'y' : 'n');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (q->meas_time_en) {
|
if (q->meas_time_en) {
|
||||||
|
|
|
@ -103,6 +103,14 @@ int srsran_rf_open_devname(srsran_rf_t* rf, const char* devname, char* args, uin
|
||||||
{
|
{
|
||||||
rf->thread_gain_run = false;
|
rf->thread_gain_run = false;
|
||||||
|
|
||||||
|
bool no_rf_devs_detected = true;
|
||||||
|
printf("Available RF device list:");
|
||||||
|
for (unsigned int i = 0; available_devices[i]; i++) {
|
||||||
|
no_rf_devs_detected = false;
|
||||||
|
printf(" %s ", available_devices[i]->name);
|
||||||
|
}
|
||||||
|
printf("%s\n", no_rf_devs_detected ? " <none>" : "");
|
||||||
|
|
||||||
// Try to open the device if name is provided
|
// Try to open the device if name is provided
|
||||||
if (devname && devname[0] != '\0') {
|
if (devname && devname[0] != '\0') {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -113,21 +121,30 @@ int srsran_rf_open_devname(srsran_rf_t* rf, const char* devname, char* args, uin
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ERROR("RF device '%s' not found. Please check the available srsRAN CMAKE options to verify if this device is being "
|
||||||
|
"detected in your system",
|
||||||
|
devname);
|
||||||
// provided device not found, abort
|
// provided device not found, abort
|
||||||
return SRSRAN_ERROR;
|
return SRSRAN_ERROR;
|
||||||
} else {
|
}
|
||||||
|
|
||||||
// auto-mode, try to open in order of apperance in available_devices[] array
|
// auto-mode, try to open in order of apperance in available_devices[] array
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (available_devices[i] != NULL) {
|
while (available_devices[i] != NULL) {
|
||||||
|
printf("Trying to open RF device '%s'\n", available_devices[i]->name);
|
||||||
if (!available_devices[i]->srsran_rf_open_multi(args, &rf->handler, nof_channels)) {
|
if (!available_devices[i]->srsran_rf_open_multi(args, &rf->handler, nof_channels)) {
|
||||||
rf->dev = available_devices[i];
|
rf->dev = available_devices[i];
|
||||||
|
printf("RF device '%s' successfully opened\n", available_devices[i]->name);
|
||||||
return SRSRAN_SUCCESS;
|
return SRSRAN_SUCCESS;
|
||||||
}
|
}
|
||||||
|
printf("Unable to open RF device '%s'\n", available_devices[i]->name);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ERROR("No compatible RF frontend found");
|
ERROR(
|
||||||
|
"Failed to open a RF frontend device. Please check the available srsRAN CMAKE options to verify what RF frontend "
|
||||||
|
"devices have been detected in your system");
|
||||||
return SRSRAN_ERROR;
|
return SRSRAN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -287,7 +287,9 @@ int rf_zmq_open_multi(char* args, void** h, uint32_t nof_channels)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "[zmq] Error: RF device args are required for ZMQ no-RF module\n");
|
fprintf(stderr,
|
||||||
|
"[zmq] Error: No device 'args' option has been set. Please make sure to set this option to be able to "
|
||||||
|
"use the ZMQ no-RF module\n");
|
||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -548,7 +548,7 @@ bool radio::tx_dev(const uint32_t& device_idx, rf_buffer_interface& buffer, cons
|
||||||
// if the gap is bigger than TX_MAX_GAP_ZEROS, stop burst
|
// if the gap is bigger than TX_MAX_GAP_ZEROS, stop burst
|
||||||
if (fabs(srsran_timestamp_real(&ts_overlap)) > tx_max_gap_zeros) {
|
if (fabs(srsran_timestamp_real(&ts_overlap)) > tx_max_gap_zeros) {
|
||||||
logger.info("Detected RF gap of %.1f us. Sending end-of-burst.", srsran_timestamp_real(&ts_overlap) * 1.0e6);
|
logger.info("Detected RF gap of %.1f us. Sending end-of-burst.", srsran_timestamp_real(&ts_overlap) * 1.0e6);
|
||||||
tx_end();
|
tx_end_nolock();
|
||||||
} else {
|
} else {
|
||||||
logger.debug("Detected RF gap of %.1f us. Tx'ing zeroes.", srsran_timestamp_real(&ts_overlap) * 1.0e6);
|
logger.debug("Detected RF gap of %.1f us. Tx'ing zeroes.", srsran_timestamp_real(&ts_overlap) * 1.0e6);
|
||||||
// Otherwise, transmit zeros
|
// Otherwise, transmit zeros
|
||||||
|
@ -601,6 +601,12 @@ bool radio::tx_dev(const uint32_t& device_idx, rf_buffer_interface& buffer, cons
|
||||||
}
|
}
|
||||||
|
|
||||||
void radio::tx_end()
|
void radio::tx_end()
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(tx_mutex);
|
||||||
|
tx_end_nolock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void radio::tx_end_nolock()
|
||||||
{
|
{
|
||||||
if (!is_initialized) {
|
if (!is_initialized) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -248,20 +248,24 @@ bool rlc::has_data_locked(const uint32_t lcid)
|
||||||
return has_data(lcid);
|
return has_data(lcid);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t rlc::get_buffer_state(uint32_t lcid)
|
void rlc::get_buffer_state(uint32_t lcid, uint32_t& tx_queue, uint32_t& prio_tx_queue)
|
||||||
{
|
{
|
||||||
uint32_t ret = 0;
|
|
||||||
|
|
||||||
rwlock_read_guard lock(rwlock);
|
rwlock_read_guard lock(rwlock);
|
||||||
if (valid_lcid(lcid)) {
|
if (valid_lcid(lcid)) {
|
||||||
if (rlc_array.at(lcid)->is_suspended()) {
|
if (rlc_array.at(lcid)->is_suspended()) {
|
||||||
ret = 0;
|
tx_queue = 0;
|
||||||
|
prio_tx_queue = 0;
|
||||||
} else {
|
} else {
|
||||||
ret = rlc_array.at(lcid)->get_buffer_state();
|
rlc_array.at(lcid)->get_buffer_state(tx_queue, prio_tx_queue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
uint32_t rlc::get_buffer_state(uint32_t lcid)
|
||||||
|
{
|
||||||
|
uint32_t tx_queue = 0, prio_tx_queue = 0;
|
||||||
|
get_buffer_state(lcid, tx_queue, prio_tx_queue);
|
||||||
|
return tx_queue + prio_tx_queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t rlc::get_total_mch_buffer_state(uint32_t lcid)
|
uint32_t rlc::get_total_mch_buffer_state(uint32_t lcid)
|
||||||
|
@ -601,9 +605,9 @@ bool rlc::valid_lcid_mrb(uint32_t lcid)
|
||||||
void rlc::update_bsr(uint32_t lcid)
|
void rlc::update_bsr(uint32_t lcid)
|
||||||
{
|
{
|
||||||
if (bsr_callback) {
|
if (bsr_callback) {
|
||||||
uint32_t tx_queue = get_buffer_state(lcid);
|
uint32_t tx_queue = 0, prio_tx_queue = 0;
|
||||||
uint32_t retx_queue = 0; // todo: separate tx_queue and retx_queue
|
get_buffer_state(lcid, tx_queue, prio_tx_queue);
|
||||||
bsr_callback(lcid, tx_queue, retx_queue);
|
bsr_callback(lcid, tx_queue, prio_tx_queue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -267,6 +267,11 @@ uint32_t rlc_am_lte::get_buffer_state()
|
||||||
return tx.get_buffer_state();
|
return tx.get_buffer_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rlc_am_lte::get_buffer_state(uint32_t& tx_queue, uint32_t& prio_tx_queue)
|
||||||
|
{
|
||||||
|
tx.get_buffer_state(tx_queue, prio_tx_queue);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t rlc_am_lte::read_pdu(uint8_t* payload, uint32_t nof_bytes)
|
uint32_t rlc_am_lte::read_pdu(uint8_t* payload, uint32_t nof_bytes)
|
||||||
{
|
{
|
||||||
uint32_t read_bytes = tx.read_pdu(payload, nof_bytes);
|
uint32_t read_bytes = tx.read_pdu(payload, nof_bytes);
|
||||||
|
@ -347,7 +352,11 @@ bool rlc_am_lte::rlc_am_lte_tx::configure(const rlc_config_t& cfg_)
|
||||||
void rlc_am_lte::rlc_am_lte_tx::stop()
|
void rlc_am_lte::rlc_am_lte_tx::stop()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mutex);
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
stop_nolock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void rlc_am_lte::rlc_am_lte_tx::stop_nolock()
|
||||||
|
{
|
||||||
empty_queue_nolock();
|
empty_queue_nolock();
|
||||||
|
|
||||||
tx_enabled = false;
|
tx_enabled = false;
|
||||||
|
@ -400,7 +409,8 @@ void rlc_am_lte::rlc_am_lte_tx::empty_queue_nolock()
|
||||||
|
|
||||||
void rlc_am_lte::rlc_am_lte_tx::reestablish()
|
void rlc_am_lte::rlc_am_lte_tx::reestablish()
|
||||||
{
|
{
|
||||||
stop();
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
stop_nolock();
|
||||||
tx_enabled = true;
|
tx_enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -445,10 +455,19 @@ void rlc_am_lte::rlc_am_lte_tx::check_sn_reached_max_retx(uint32_t sn)
|
||||||
|
|
||||||
uint32_t rlc_am_lte::rlc_am_lte_tx::get_buffer_state()
|
uint32_t rlc_am_lte::rlc_am_lte_tx::get_buffer_state()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mutex);
|
uint32_t new_tx_queue = 0, prio_tx_queue = 0;
|
||||||
uint32_t n_bytes = 0;
|
get_buffer_state(new_tx_queue, prio_tx_queue);
|
||||||
|
return new_tx_queue + prio_tx_queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rlc_am_lte::rlc_am_lte_tx::get_buffer_state(uint32_t& n_bytes_newtx, uint32_t& n_bytes_prio)
|
||||||
|
{
|
||||||
|
n_bytes_newtx = 0;
|
||||||
|
n_bytes_prio = 0;
|
||||||
uint32_t n_sdus = 0;
|
uint32_t n_sdus = 0;
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
|
||||||
logger.debug("%s Buffer state - do_status=%s, status_prohibit_running=%s (%d/%d)",
|
logger.debug("%s Buffer state - do_status=%s, status_prohibit_running=%s (%d/%d)",
|
||||||
RB_NAME,
|
RB_NAME,
|
||||||
do_status() ? "yes" : "no",
|
do_status() ? "yes" : "no",
|
||||||
|
@ -458,8 +477,8 @@ uint32_t rlc_am_lte::rlc_am_lte_tx::get_buffer_state()
|
||||||
|
|
||||||
// Bytes needed for status report
|
// Bytes needed for status report
|
||||||
if (do_status() && not status_prohibit_timer.is_running()) {
|
if (do_status() && not status_prohibit_timer.is_running()) {
|
||||||
n_bytes += parent->rx.get_status_pdu_length();
|
n_bytes_prio += parent->rx.get_status_pdu_length();
|
||||||
logger.debug("%s Buffer state - total status report: %d bytes", RB_NAME, n_bytes);
|
logger.debug("%s Buffer state - total status report: %d bytes", RB_NAME, n_bytes_prio);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bytes needed for retx
|
// Bytes needed for retx
|
||||||
|
@ -477,8 +496,8 @@ uint32_t rlc_am_lte::rlc_am_lte_tx::get_buffer_state()
|
||||||
logger.error("In get_buffer_state(): Removing retx.sn=%d from queue", retx.sn);
|
logger.error("In get_buffer_state(): Removing retx.sn=%d from queue", retx.sn);
|
||||||
retx_queue.pop();
|
retx_queue.pop();
|
||||||
} else {
|
} else {
|
||||||
n_bytes += req_bytes;
|
n_bytes_prio += req_bytes;
|
||||||
logger.debug("Buffer state - retx: %d bytes", n_bytes);
|
logger.debug("Buffer state - retx: %d bytes", n_bytes_prio);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -486,25 +505,23 @@ uint32_t rlc_am_lte::rlc_am_lte_tx::get_buffer_state()
|
||||||
// Bytes needed for tx SDUs
|
// Bytes needed for tx SDUs
|
||||||
if (tx_window.size() < 1024) {
|
if (tx_window.size() < 1024) {
|
||||||
n_sdus = tx_sdu_queue.get_n_sdus();
|
n_sdus = tx_sdu_queue.get_n_sdus();
|
||||||
n_bytes += tx_sdu_queue.size_bytes();
|
n_bytes_newtx += tx_sdu_queue.size_bytes();
|
||||||
if (tx_sdu != NULL) {
|
if (tx_sdu != NULL) {
|
||||||
n_sdus++;
|
n_sdus++;
|
||||||
n_bytes += tx_sdu->N_bytes;
|
n_bytes_newtx += tx_sdu->N_bytes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Room needed for header extensions? (integer rounding)
|
// Room needed for header extensions? (integer rounding)
|
||||||
if (n_sdus > 1) {
|
if (n_sdus > 1) {
|
||||||
n_bytes += ((n_sdus - 1) * 1.5) + 0.5;
|
n_bytes_newtx += ((n_sdus - 1) * 1.5) + 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Room needed for fixed header of data PDUs
|
// Room needed for fixed header of data PDUs
|
||||||
if (n_bytes > 0 && n_sdus > 0) {
|
if (n_bytes_newtx > 0 && n_sdus > 0) {
|
||||||
n_bytes += 2; // Two bytes for fixed header with SN length = 10
|
n_bytes_newtx += 2; // Two bytes for fixed header with SN length = 10
|
||||||
logger.debug("%s Total buffer state - %d SDUs (%d B)", RB_NAME, n_sdus, n_bytes);
|
logger.debug("%s Total buffer state - %d SDUs (%d B)", RB_NAME, n_sdus, n_bytes_newtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
return n_bytes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int rlc_am_lte::rlc_am_lte_tx::write_sdu(unique_byte_buffer_t sdu)
|
int rlc_am_lte::rlc_am_lte_tx::write_sdu(unique_byte_buffer_t sdu)
|
||||||
|
@ -622,7 +639,9 @@ void rlc_am_lte::rlc_am_lte_tx::timer_expired(uint32_t timeout_id)
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
|
||||||
if (bsr_callback) {
|
if (bsr_callback) {
|
||||||
bsr_callback(parent->lcid, get_buffer_state(), 0);
|
uint32_t new_tx_queue = 0, prio_tx_queue = 0;
|
||||||
|
get_buffer_state(new_tx_queue, prio_tx_queue);
|
||||||
|
bsr_callback(parent->lcid, new_tx_queue, prio_tx_queue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -133,6 +133,12 @@ uint32_t rlc_tm::get_buffer_state()
|
||||||
return ul_queue.size_bytes();
|
return ul_queue.size_bytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rlc_tm::get_buffer_state(uint32_t& newtx_queue, uint32_t& prio_tx_queue)
|
||||||
|
{
|
||||||
|
newtx_queue = get_buffer_state();
|
||||||
|
prio_tx_queue = 0;
|
||||||
|
}
|
||||||
|
|
||||||
rlc_bearer_metrics_t rlc_tm::get_metrics()
|
rlc_bearer_metrics_t rlc_tm::get_metrics()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(metrics_mutex);
|
std::lock_guard<std::mutex> lock(metrics_mutex);
|
||||||
|
|
|
@ -143,6 +143,12 @@ uint32_t rlc_um_base::get_buffer_state()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rlc_um_base::get_buffer_state(uint32_t& newtx_queue, uint32_t& prio_tx_queue)
|
||||||
|
{
|
||||||
|
newtx_queue = get_buffer_state();
|
||||||
|
prio_tx_queue = 0;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t rlc_um_base::read_pdu(uint8_t* payload, uint32_t nof_bytes)
|
uint32_t rlc_um_base::read_pdu(uint8_t* payload, uint32_t nof_bytes)
|
||||||
{
|
{
|
||||||
if (tx && tx_enabled) {
|
if (tx && tx_enabled) {
|
||||||
|
|
|
@ -26,7 +26,9 @@
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#ifndef SRSRAN_TERM_TIMEOUT_S
|
||||||
#define SRSRAN_TERM_TIMEOUT_S (5)
|
#define SRSRAN_TERM_TIMEOUT_S (5)
|
||||||
|
#endif
|
||||||
|
|
||||||
/// Handler called after the user interrupts the program.
|
/// Handler called after the user interrupts the program.
|
||||||
static std::atomic<srsran_signal_hanlder> user_handler;
|
static std::atomic<srsran_signal_hanlder> user_handler;
|
||||||
|
|
|
@ -61,11 +61,12 @@ int test_socket_handler()
|
||||||
const char* server_addr = "127.0.100.1";
|
const char* server_addr = "127.0.100.1";
|
||||||
using namespace srsran::net_utils;
|
using namespace srsran::net_utils;
|
||||||
|
|
||||||
TESTASSERT(sctp_init_server(&server_socket, socket_type::seqpacket, server_addr, server_port));
|
TESTASSERT(sctp_init_socket(&server_socket, socket_type::seqpacket, server_addr, server_port));
|
||||||
|
TESTASSERT(server_socket.start_listen());
|
||||||
logger.info("Listening from fd=%d", server_socket.fd());
|
logger.info("Listening from fd=%d", server_socket.fd());
|
||||||
|
|
||||||
TESTASSERT(sctp_init_client(&client_socket, socket_type::seqpacket, "127.0.0.1", 0));
|
TESTASSERT(sctp_init_socket(&client_socket, socket_type::seqpacket, "127.0.0.1", 0));
|
||||||
TESTASSERT(sctp_init_client(&client_socket2, socket_type::seqpacket, "127.0.0.2", 0));
|
TESTASSERT(sctp_init_socket(&client_socket2, socket_type::seqpacket, "127.0.0.2", 0));
|
||||||
TESTASSERT(client_socket.connect_to(server_addr, server_port));
|
TESTASSERT(client_socket.connect_to(server_addr, server_port));
|
||||||
TESTASSERT(client_socket2.connect_to(server_addr, server_port));
|
TESTASSERT(client_socket2.connect_to(server_addr, server_port));
|
||||||
|
|
||||||
|
@ -123,6 +124,18 @@ int test_socket_handler()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int test_sctp_bind_error()
|
||||||
|
{
|
||||||
|
srsran::unique_socket sock;
|
||||||
|
TESTASSERT(not srsran::net_utils::sctp_init_socket(
|
||||||
|
&sock, srsran::net_utils::socket_type::seqpacket, "1.1.1.1", 8000)); // Bogus IP address
|
||||||
|
// should not be able to bind
|
||||||
|
TESTASSERT(srsran::net_utils::sctp_init_socket(
|
||||||
|
&sock, srsran::net_utils::socket_type::seqpacket, "127.0.0.1", 8000)); // Good IP address
|
||||||
|
// should be able to bind
|
||||||
|
return SRSRAN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
auto& logger = srslog::fetch_basic_logger("S1AP", false);
|
auto& logger = srslog::fetch_basic_logger("S1AP", false);
|
||||||
|
@ -132,6 +145,7 @@ int main()
|
||||||
srslog::init();
|
srslog::init();
|
||||||
|
|
||||||
TESTASSERT(test_socket_handler() == 0);
|
TESTASSERT(test_socket_handler() == 0);
|
||||||
|
TESTASSERT(test_sctp_bind_error() == 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,8 @@ public:
|
||||||
logger.info("Discard_count=%" PRIu64 "", discard_count);
|
logger.info("Discard_count=%" PRIu64 "", discard_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_suspended(uint32_t lcid) { return false; }
|
||||||
|
|
||||||
uint64_t rx_count = 0;
|
uint64_t rx_count = 0;
|
||||||
uint64_t discard_count = 0;
|
uint64_t discard_count = 0;
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,7 @@ private:
|
||||||
|
|
||||||
int encode_pdsch(stack_interface_phy_lte::dl_sched_grant_t* grants, uint32_t nof_grants);
|
int encode_pdsch(stack_interface_phy_lte::dl_sched_grant_t* grants, uint32_t nof_grants);
|
||||||
int encode_pmch(stack_interface_phy_lte::dl_sched_grant_t* grant, srsran_mbsfn_cfg_t* mbsfn_cfg);
|
int encode_pmch(stack_interface_phy_lte::dl_sched_grant_t* grant, srsran_mbsfn_cfg_t* mbsfn_cfg);
|
||||||
void decode_pusch_rnti(stack_interface_phy_lte::ul_sched_grant_t& ul_grant,
|
bool decode_pusch_rnti(stack_interface_phy_lte::ul_sched_grant_t& ul_grant,
|
||||||
srsran_ul_cfg_t& ul_cfg,
|
srsran_ul_cfg_t& ul_cfg,
|
||||||
srsran_pusch_res_t& pusch_res);
|
srsran_pusch_res_t& pusch_res);
|
||||||
void decode_pusch(stack_interface_phy_lte::ul_sched_grant_t* grants, uint32_t nof_pusch);
|
void decode_pusch(stack_interface_phy_lte::ul_sched_grant_t* grants, uint32_t nof_pusch);
|
||||||
|
|
|
@ -99,12 +99,6 @@ private:
|
||||||
uint32_t nof_prach_workers = 0;
|
uint32_t nof_prach_workers = 0;
|
||||||
double srate_hz = 0.0; ///< Current sampling rate in Hz
|
double srate_hz = 0.0; ///< Current sampling rate in Hz
|
||||||
|
|
||||||
// Current configuration
|
|
||||||
std::mutex common_cfg_mutex;
|
|
||||||
srsran_carrier_nr_t carrier = {};
|
|
||||||
srsran_pdcch_cfg_nr_t pdcch_cfg = {};
|
|
||||||
srsran_ssb_cfg_t ssb_cfg = {};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct args_t {
|
struct args_t {
|
||||||
double srate_hz = 0.0;
|
double srate_hz = 0.0;
|
||||||
|
|
|
@ -236,7 +236,7 @@ public:
|
||||||
void set_mch_period_stop(uint32_t stop);
|
void set_mch_period_stop(uint32_t stop);
|
||||||
|
|
||||||
// Getters and setters for ul grants which need to be shared between workers
|
// Getters and setters for ul grants which need to be shared between workers
|
||||||
const stack_interface_phy_lte::ul_sched_list_t& get_ul_grants(uint32_t tti);
|
const stack_interface_phy_lte::ul_sched_list_t get_ul_grants(uint32_t tti);
|
||||||
void set_ul_grants(uint32_t tti, const stack_interface_phy_lte::ul_sched_list_t& ul_grants);
|
void set_ul_grants(uint32_t tti, const stack_interface_phy_lte::ul_sched_list_t& ul_grants);
|
||||||
void clear_grants(uint16_t rnti);
|
void clear_grants(uint16_t rnti);
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#define SRSRAN_UE_BUFFER_MANAGER_H
|
#define SRSRAN_UE_BUFFER_MANAGER_H
|
||||||
|
|
||||||
#include "sched_config.h"
|
#include "sched_config.h"
|
||||||
|
#include "srsran/adt/span.h"
|
||||||
#include "srsran/common/common_lte.h"
|
#include "srsran/common/common_lte.h"
|
||||||
#include "srsran/common/common_nr.h"
|
#include "srsran/common/common_nr.h"
|
||||||
#include "srsran/srslog/srslog.h"
|
#include "srsran/srslog/srslog.h"
|
||||||
|
@ -37,7 +38,7 @@ template <bool isNR>
|
||||||
class ue_buffer_manager
|
class ue_buffer_manager
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
const static uint32_t MAX_LC_ID = isNR ? srsran::MAX_NR_NOF_BEARERS : srsran::MAX_LTE_LCID;
|
const static uint32_t MAX_LC_ID = isNR ? (srsran::MAX_NR_NOF_BEARERS - 1) : srsran::MAX_LTE_LCID;
|
||||||
const static uint32_t MAX_LCG_ID = isNR ? 7 : 3; // Should import from sched_interface and sched_nr_interface
|
const static uint32_t MAX_LCG_ID = isNR ? 7 : 3; // Should import from sched_interface and sched_nr_interface
|
||||||
const static uint32_t MAX_SRB_LC_ID = isNR ? srsran::MAX_NR_SRB_ID : srsran::MAX_LTE_SRB_ID;
|
const static uint32_t MAX_SRB_LC_ID = isNR ? srsran::MAX_NR_SRB_ID : srsran::MAX_LTE_SRB_ID;
|
||||||
const static uint32_t MAX_NOF_LCIDS = MAX_LC_ID + 1;
|
const static uint32_t MAX_NOF_LCIDS = MAX_LC_ID + 1;
|
||||||
|
@ -45,16 +46,18 @@ protected:
|
||||||
constexpr static uint32_t pbr_infinity = -1;
|
constexpr static uint32_t pbr_infinity = -1;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ue_buffer_manager(srslog::basic_logger& logger_);
|
explicit ue_buffer_manager(uint16_t rnti, srslog::basic_logger& logger_);
|
||||||
|
|
||||||
// Bearer configuration
|
// Bearer configuration
|
||||||
|
void config_lcids(srsran::const_span<mac_lc_ch_cfg_t> bearer_cfg_list);
|
||||||
void config_lcid(uint32_t lcid, const mac_lc_ch_cfg_t& bearer_cfg);
|
void config_lcid(uint32_t lcid, const mac_lc_ch_cfg_t& bearer_cfg);
|
||||||
|
|
||||||
// Buffer Status update
|
// Buffer Status update
|
||||||
void ul_bsr(uint32_t lcg_id, uint32_t val);
|
void ul_bsr(uint32_t lcg_id, uint32_t val);
|
||||||
void dl_buffer_state(uint8_t lcid, uint32_t tx_queue, uint32_t retx_queue);
|
void dl_buffer_state(uint8_t lcid, uint32_t tx_queue, uint32_t prio_tx_queue);
|
||||||
|
|
||||||
// Configuration getters
|
// Configuration getters
|
||||||
|
uint16_t get_rnti() const { return rnti; }
|
||||||
bool is_bearer_active(uint32_t lcid) const { return get_cfg(lcid).is_active(); }
|
bool is_bearer_active(uint32_t lcid) const { return get_cfg(lcid).is_active(); }
|
||||||
bool is_bearer_ul(uint32_t lcid) const { return get_cfg(lcid).is_ul(); }
|
bool is_bearer_ul(uint32_t lcid) const { return get_cfg(lcid).is_ul(); }
|
||||||
bool is_bearer_dl(uint32_t lcid) const { return get_cfg(lcid).is_dl(); }
|
bool is_bearer_dl(uint32_t lcid) const { return get_cfg(lcid).is_dl(); }
|
||||||
|
@ -67,13 +70,13 @@ public:
|
||||||
/// DL newtx buffer status for given LCID (no RLC overhead included)
|
/// DL newtx buffer status for given LCID (no RLC overhead included)
|
||||||
int get_dl_tx(uint32_t lcid) const { return is_bearer_dl(lcid) ? channels[lcid].buf_tx : 0; }
|
int get_dl_tx(uint32_t lcid) const { return is_bearer_dl(lcid) ? channels[lcid].buf_tx : 0; }
|
||||||
|
|
||||||
/// DL retx buffer status for given LCID (no RLC overhead included)
|
/// DL high prio tx buffer status for given LCID (no RLC overhead included)
|
||||||
int get_dl_retx(uint32_t lcid) const { return is_bearer_dl(lcid) ? channels[lcid].buf_retx : 0; }
|
int get_dl_prio_tx(uint32_t lcid) const { return is_bearer_dl(lcid) ? channels[lcid].buf_prio_tx : 0; }
|
||||||
|
|
||||||
/// Sum of DL RLC newtx and retx buffer status for given LCID (no RLC overhead included)
|
/// Sum of DL RLC newtx and high prio tx buffer status for given LCID (no RLC overhead included)
|
||||||
int get_dl_tx_total(uint32_t lcid) const { return get_dl_tx(lcid) + get_dl_retx(lcid); }
|
int get_dl_tx_total(uint32_t lcid) const { return get_dl_tx(lcid) + get_dl_prio_tx(lcid); }
|
||||||
|
|
||||||
/// Sum of DL RLC newtx and retx buffer status for all LCIDS
|
/// Sum of DL RLC newtx and high prio buffer status for all LCIDS
|
||||||
int get_dl_tx_total() const;
|
int get_dl_tx_total() const;
|
||||||
|
|
||||||
// UL BSR methods
|
// UL BSR methods
|
||||||
|
@ -86,12 +89,15 @@ public:
|
||||||
static bool is_lcg_valid(uint32_t lcg) { return lcg <= MAX_LCG_ID; }
|
static bool is_lcg_valid(uint32_t lcg) { return lcg <= MAX_LCG_ID; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
bool config_lcid_internal(uint32_t lcid, const mac_lc_ch_cfg_t& bearer_cfg);
|
||||||
|
|
||||||
srslog::basic_logger& logger;
|
srslog::basic_logger& logger;
|
||||||
|
uint16_t rnti;
|
||||||
|
|
||||||
struct logical_channel {
|
struct logical_channel {
|
||||||
mac_lc_ch_cfg_t cfg;
|
mac_lc_ch_cfg_t cfg;
|
||||||
int buf_tx = 0;
|
int buf_tx = 0;
|
||||||
int buf_retx = 0;
|
int buf_prio_tx = 0;
|
||||||
int Bj = 0;
|
int Bj = 0;
|
||||||
int bucket_size = 0;
|
int bucket_size = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -59,8 +59,8 @@ public:
|
||||||
void ul_bsr(uint16_t rnti, uint32_t lcg_id, uint32_t bsr) override;
|
void ul_bsr(uint16_t rnti, uint32_t lcg_id, uint32_t bsr) override;
|
||||||
void dl_buffer_state(uint16_t rnti, uint32_t lcid, uint32_t newtx, uint32_t retx);
|
void dl_buffer_state(uint16_t rnti, uint32_t lcid, uint32_t newtx, uint32_t retx);
|
||||||
|
|
||||||
int run_slot(slot_point pdsch_tti, uint32_t cc, dl_sched_res_t& result) override;
|
int run_slot(slot_point pdsch_tti, uint32_t cc, dl_res_t& result) override;
|
||||||
int get_ul_sched(slot_point pusch_tti, uint32_t cc, ul_sched_t& result) override;
|
int get_ul_sched(slot_point pusch_tti, uint32_t cc, ul_res_t& result) override;
|
||||||
|
|
||||||
void get_metrics(mac_metrics_t& metrics);
|
void get_metrics(mac_metrics_t& metrics);
|
||||||
|
|
||||||
|
|
|
@ -57,8 +57,8 @@ using ue_cc_cfg_t = sched_nr_interface::ue_cc_cfg_t;
|
||||||
using pdcch_cce_pos_list = srsran::bounded_vector<uint32_t, SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR>;
|
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>;
|
using bwp_cce_pos_list = std::array<std::array<pdcch_cce_pos_list, MAX_NOF_AGGR_LEVELS>, SRSRAN_NOF_SF_X_FRAME>;
|
||||||
using dl_sched_t = sched_nr_interface::dl_sched_t;
|
using dl_sched_t = sched_nr_interface::dl_sched_t;
|
||||||
using ul_sched_t = sched_nr_interface::ul_sched_t;
|
using ul_sched_t = sched_nr_interface::ul_res_t;
|
||||||
using dl_sched_res_t = sched_nr_interface::dl_sched_res_t;
|
using dl_sched_res_t = sched_nr_interface::dl_res_t;
|
||||||
|
|
||||||
/// Generate list of CCE locations for UE based on coreset and search space configurations
|
/// Generate list of CCE locations for UE based on coreset and search space configurations
|
||||||
void get_dci_locs(const srsran_coreset_t& coreset,
|
void get_dci_locs(const srsran_coreset_t& coreset,
|
||||||
|
|
|
@ -55,7 +55,7 @@ public:
|
||||||
|
|
||||||
int ack_info(uint32_t tb_idx, bool ack);
|
int ack_info(uint32_t tb_idx, bool ack);
|
||||||
|
|
||||||
void new_slot(slot_point slot_rx);
|
bool clear_if_maxretx(slot_point slot_rx);
|
||||||
void reset();
|
void reset();
|
||||||
bool new_tx(slot_point slot_tx, slot_point slot_ack, const prb_grant& grant, uint32_t mcs, uint32_t max_retx);
|
bool new_tx(slot_point slot_tx, slot_point slot_ack, const prb_grant& grant, uint32_t mcs, uint32_t max_retx);
|
||||||
bool new_retx(slot_point slot_tx, slot_point slot_ack, const prb_grant& grant);
|
bool new_retx(slot_point slot_tx, slot_point slot_ack, const prb_grant& grant);
|
||||||
|
@ -121,7 +121,7 @@ private:
|
||||||
class harq_entity
|
class harq_entity
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit harq_entity(uint32_t nprb, uint32_t nof_harq_procs = SCHED_NR_MAX_HARQ);
|
explicit harq_entity(uint16_t rnti, uint32_t nprb, uint32_t nof_harq_procs, srslog::basic_logger& logger);
|
||||||
void new_slot(slot_point slot_rx_);
|
void new_slot(slot_point slot_rx_);
|
||||||
|
|
||||||
int dl_ack_info(uint32_t pid, uint32_t tb_idx, bool ack) { return dl_harqs[pid].ack_info(tb_idx, ack); }
|
int dl_ack_info(uint32_t pid, uint32_t tb_idx, bool ack) { return dl_harqs[pid].ack_info(tb_idx, ack); }
|
||||||
|
@ -163,6 +163,9 @@ private:
|
||||||
return (it == ul_harqs.end()) ? nullptr : &(*it);
|
return (it == ul_harqs.end()) ? nullptr : &(*it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t rnti;
|
||||||
|
srslog::basic_logger& logger;
|
||||||
|
|
||||||
slot_point slot_rx;
|
slot_point slot_rx;
|
||||||
std::vector<dl_harq_proc> dl_harqs;
|
std::vector<dl_harq_proc> dl_harqs;
|
||||||
std::vector<ul_harq_proc> ul_harqs;
|
std::vector<ul_harq_proc> ul_harqs;
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "srsran/adt/bounded_vector.h"
|
#include "srsran/adt/bounded_vector.h"
|
||||||
#include "srsran/adt/optional.h"
|
#include "srsran/adt/optional.h"
|
||||||
#include "srsran/adt/span.h"
|
#include "srsran/adt/span.h"
|
||||||
|
#include "srsran/common/common_nr.h"
|
||||||
#include "srsran/common/phy_cfg_nr.h"
|
#include "srsran/common/phy_cfg_nr.h"
|
||||||
#include "srsran/common/slot_point.h"
|
#include "srsran/common/slot_point.h"
|
||||||
#include "srsran/interfaces/gnb_interfaces.h"
|
#include "srsran/interfaces/gnb_interfaces.h"
|
||||||
|
@ -39,7 +40,7 @@ const static size_t SCHED_NR_MAX_NOF_RBGS = 18;
|
||||||
const static size_t SCHED_NR_MAX_TB = 1;
|
const static size_t SCHED_NR_MAX_TB = 1;
|
||||||
const static size_t SCHED_NR_MAX_HARQ = SRSRAN_DEFAULT_HARQ_PROC_DL_NR;
|
const static size_t SCHED_NR_MAX_HARQ = SRSRAN_DEFAULT_HARQ_PROC_DL_NR;
|
||||||
const static size_t SCHED_NR_MAX_BWP_PER_CELL = 2;
|
const static size_t SCHED_NR_MAX_BWP_PER_CELL = 2;
|
||||||
const static size_t SCHED_NR_MAX_LCID = 32;
|
const static size_t SCHED_NR_MAX_LCID = srsran::MAX_NR_NOF_BEARERS;
|
||||||
const static size_t SCHED_NR_MAX_LC_GROUP = 7;
|
const static size_t SCHED_NR_MAX_LC_GROUP = 7;
|
||||||
|
|
||||||
struct sched_nr_ue_cc_cfg_t {
|
struct sched_nr_ue_cc_cfg_t {
|
||||||
|
@ -122,12 +123,13 @@ public:
|
||||||
///// Sched Result /////
|
///// Sched Result /////
|
||||||
|
|
||||||
using dl_sched_t = mac_interface_phy_nr::dl_sched_t;
|
using dl_sched_t = mac_interface_phy_nr::dl_sched_t;
|
||||||
using ul_sched_t = mac_interface_phy_nr::ul_sched_t;
|
using ul_res_t = mac_interface_phy_nr::ul_sched_t;
|
||||||
|
|
||||||
using sched_rar_list_t = srsran::bounded_vector<rar_t, MAX_GRANTS>;
|
using sched_rar_list_t = srsran::bounded_vector<rar_t, MAX_GRANTS>;
|
||||||
struct dl_sched_res_t {
|
struct dl_res_t {
|
||||||
sched_rar_list_t rar;
|
sched_rar_list_t& rar;
|
||||||
dl_sched_t dl_sched;
|
dl_sched_t& dl_sched;
|
||||||
|
dl_res_t(sched_rar_list_t& rar_, dl_sched_t& dl_sched_) : rar(rar_), dl_sched(dl_sched_) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual ~sched_nr_interface() = default;
|
virtual ~sched_nr_interface() = default;
|
||||||
|
@ -135,8 +137,8 @@ public:
|
||||||
virtual void ue_cfg(uint16_t rnti, const ue_cfg_t& ue_cfg) = 0;
|
virtual void ue_cfg(uint16_t rnti, const ue_cfg_t& ue_cfg) = 0;
|
||||||
virtual void ue_rem(uint16_t rnti) = 0;
|
virtual void ue_rem(uint16_t rnti) = 0;
|
||||||
virtual bool ue_exists(uint16_t rnti) = 0;
|
virtual bool ue_exists(uint16_t rnti) = 0;
|
||||||
virtual int run_slot(slot_point slot_rx, uint32_t cc, dl_sched_res_t& result) = 0;
|
virtual int run_slot(slot_point slot_rx, uint32_t cc, dl_res_t& result) = 0;
|
||||||
virtual int get_ul_sched(slot_point slot_rx, uint32_t cc, ul_sched_t& result) = 0;
|
virtual int get_ul_sched(slot_point slot_rx, uint32_t cc, ul_res_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 dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) = 0;
|
||||||
virtual void ul_crc_info(uint16_t rnti, uint32_t cc, uint32_t pid, bool crc) = 0;
|
virtual void ul_crc_info(uint16_t rnti, uint32_t cc, uint32_t pid, bool crc) = 0;
|
||||||
|
|
|
@ -81,7 +81,7 @@ private:
|
||||||
pdcch_grant_type_t alloc_type;
|
pdcch_grant_type_t alloc_type;
|
||||||
slot_ue* ue;
|
slot_ue* ue;
|
||||||
};
|
};
|
||||||
srsran::bounded_vector<alloc_record, MAX_GRANTS> dci_list;
|
srsran::bounded_vector<alloc_record, 2 * MAX_GRANTS> dci_list;
|
||||||
pdcch_dl_list_t& pdcch_dl_list;
|
pdcch_dl_list_t& pdcch_dl_list;
|
||||||
pdcch_ul_list_t& pdcch_ul_list;
|
pdcch_ul_list_t& pdcch_ul_list;
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ private:
|
||||||
/// Accumulation of all PDCCH masks for the current solution (DFS path)
|
/// Accumulation of all PDCCH masks for the current solution (DFS path)
|
||||||
coreset_bitmap total_mask, current_mask;
|
coreset_bitmap total_mask, current_mask;
|
||||||
};
|
};
|
||||||
using alloc_tree_dfs_t = srsran::bounded_vector<tree_node, MAX_GRANTS>;
|
using alloc_tree_dfs_t = std::vector<tree_node>;
|
||||||
alloc_tree_dfs_t dfs_tree, saved_dfs_tree;
|
alloc_tree_dfs_t dfs_tree, saved_dfs_tree;
|
||||||
|
|
||||||
srsran::span<const uint32_t> get_cce_loc_table(const alloc_record& record) const;
|
srsran::span<const uint32_t> get_cce_loc_table(const alloc_record& record) const;
|
||||||
|
|
|
@ -73,6 +73,10 @@ class ue_carrier
|
||||||
public:
|
public:
|
||||||
ue_carrier(uint16_t rnti, const ue_cfg_t& cfg, const cell_params_t& cell_params_);
|
ue_carrier(uint16_t rnti, const ue_cfg_t& cfg, const cell_params_t& cell_params_);
|
||||||
void set_cfg(const ue_cfg_t& ue_cfg);
|
void set_cfg(const ue_cfg_t& ue_cfg);
|
||||||
|
|
||||||
|
/// Called after CC Feedback has been processed
|
||||||
|
void new_slot(slot_point slot_tx);
|
||||||
|
|
||||||
slot_ue try_reserve(slot_point pdcch_slot, uint32_t dl_harq_bytes, uint32_t ul_harq_bytes);
|
slot_ue try_reserve(slot_point pdcch_slot, uint32_t dl_harq_bytes, uint32_t ul_harq_bytes);
|
||||||
|
|
||||||
const uint16_t rnti;
|
const uint16_t rnti;
|
||||||
|
|
|
@ -62,7 +62,7 @@ public:
|
||||||
uint32_t get_ul_buffer(uint16_t rnti) final;
|
uint32_t get_ul_buffer(uint16_t rnti) final;
|
||||||
uint32_t get_dl_buffer(uint16_t rnti) final;
|
uint32_t get_dl_buffer(uint16_t rnti) final;
|
||||||
|
|
||||||
int dl_rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t retx_queue) final;
|
int dl_rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t prio_tx_queue) final;
|
||||||
int dl_mac_buffer_state(uint16_t rnti, uint32_t ce_code, uint32_t nof_cmds = 1) final;
|
int dl_mac_buffer_state(uint16_t rnti, uint32_t ce_code, uint32_t nof_cmds = 1) final;
|
||||||
|
|
||||||
int dl_ack_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t tb_idx, bool ack) final;
|
int dl_ack_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t tb_idx, bool ack) final;
|
||||||
|
|
|
@ -276,10 +276,10 @@ public:
|
||||||
* @param rnti user rnti
|
* @param rnti user rnti
|
||||||
* @param lc_id logical channel id for which the buffer update is concerned
|
* @param lc_id logical channel id for which the buffer update is concerned
|
||||||
* @param tx_queue number of pending bytes for new DL RLC transmissions
|
* @param tx_queue number of pending bytes for new DL RLC transmissions
|
||||||
* @param retx_queue number of pending bytes concerning RLC retransmissions
|
* @param prio_tx_queue number of pending bytes concerning RLC retransmissions and status PDUs
|
||||||
* @return error code
|
* @return error code
|
||||||
*/
|
*/
|
||||||
virtual int dl_rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t retx_queue) = 0;
|
virtual int dl_rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t prio_tx_queue) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enqueue MAC CEs for DL transmission
|
* Enqueue MAC CEs for DL transmission
|
||||||
|
|
|
@ -35,7 +35,7 @@ class lch_ue_manager : private ue_buffer_manager<false>
|
||||||
using base_type = ue_buffer_manager<false>;
|
using base_type = ue_buffer_manager<false>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
lch_ue_manager() : ue_buffer_manager(srslog::fetch_basic_logger("MAC")) {}
|
explicit lch_ue_manager(uint16_t rnti) : ue_buffer_manager(rnti, srslog::fetch_basic_logger("MAC")) {}
|
||||||
void set_cfg(const sched_interface::ue_cfg_t& cfg_);
|
void set_cfg(const sched_interface::ue_cfg_t& cfg_);
|
||||||
void new_tti();
|
void new_tti();
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ public:
|
||||||
using base_type::dl_buffer_state;
|
using base_type::dl_buffer_state;
|
||||||
using base_type::get_bsr;
|
using base_type::get_bsr;
|
||||||
using base_type::get_bsr_state;
|
using base_type::get_bsr_state;
|
||||||
using base_type::get_dl_retx;
|
using base_type::get_dl_prio_tx;
|
||||||
using base_type::get_dl_tx;
|
using base_type::get_dl_tx;
|
||||||
using base_type::get_dl_tx_total;
|
using base_type::get_dl_tx_total;
|
||||||
using base_type::is_bearer_active;
|
using base_type::is_bearer_active;
|
||||||
|
@ -60,7 +60,7 @@ public:
|
||||||
bool has_pending_dl_txs() const;
|
bool has_pending_dl_txs() const;
|
||||||
int get_dl_tx_total_with_overhead(uint32_t lcid) const;
|
int get_dl_tx_total_with_overhead(uint32_t lcid) const;
|
||||||
int get_dl_tx_with_overhead(uint32_t lcid) const;
|
int get_dl_tx_with_overhead(uint32_t lcid) const;
|
||||||
int get_dl_retx_with_overhead(uint32_t lcid) const;
|
int get_dl_prio_tx_with_overhead(uint32_t lcid) const;
|
||||||
|
|
||||||
int get_bsr_with_overhead(uint32_t lcid) const;
|
int get_bsr_with_overhead(uint32_t lcid) const;
|
||||||
int get_max_prio_lcid() const;
|
int get_max_prio_lcid() const;
|
||||||
|
@ -70,7 +70,7 @@ public:
|
||||||
srsran::deque<ce_cmd> pending_ces;
|
srsran::deque<ce_cmd> pending_ces;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int alloc_retx_bytes(uint8_t lcid, int rem_bytes);
|
int alloc_prio_tx_bytes(uint8_t lcid, int rem_bytes);
|
||||||
int alloc_tx_bytes(uint8_t lcid, int rem_bytes);
|
int alloc_tx_bytes(uint8_t lcid, int rem_bytes);
|
||||||
|
|
||||||
size_t prio_idx = 0;
|
size_t prio_idx = 0;
|
||||||
|
|
|
@ -113,7 +113,15 @@ public:
|
||||||
class ue
|
class ue
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ue(rrc_nr* parent_, uint16_t rnti_, const sched_nr_ue_cfg_t& uecfg);
|
enum activity_timeout_type_t {
|
||||||
|
MSG3_RX_TIMEOUT = 0, ///< Msg3 has its own timeout to quickly remove fake UEs from random PRACHs
|
||||||
|
UE_INACTIVITY_TIMEOUT, ///< (currently unused) UE inactivity timeout (usually bigger than reestablishment timeout)
|
||||||
|
MSG5_RX_TIMEOUT, ///< (currently unused) for receiving RRCConnectionSetupComplete/RRCReestablishmentComplete
|
||||||
|
nulltype
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @param [in] start_msg3_timer: indicates whether the UE is created as part of a RACH process
|
||||||
|
ue(rrc_nr* parent_, uint16_t rnti_, const sched_nr_ue_cfg_t& uecfg, bool start_msg3_timer = true);
|
||||||
|
|
||||||
void send_connection_setup();
|
void send_connection_setup();
|
||||||
void send_dl_ccch(asn1::rrc_nr::dl_ccch_msg_s* dl_dcch_msg);
|
void send_dl_ccch(asn1::rrc_nr::dl_ccch_msg_s* dl_dcch_msg);
|
||||||
|
@ -128,14 +136,23 @@ public:
|
||||||
bool is_endc() { return endc; }
|
bool is_endc() { return endc; }
|
||||||
uint16_t get_eutra_rnti() { return eutra_rnti; }
|
uint16_t get_eutra_rnti() { return eutra_rnti; }
|
||||||
void get_metrics(rrc_ue_metrics_t& ue_metrics) { ue_metrics = {}; /*TODO fill RRC metrics*/ };
|
void get_metrics(rrc_ue_metrics_t& ue_metrics) { ue_metrics = {}; /*TODO fill RRC metrics*/ };
|
||||||
|
|
||||||
// setters
|
// setters
|
||||||
|
|
||||||
int pack_rrc_reconfiguration();
|
int pack_rrc_reconfiguration();
|
||||||
void deactivate_bearers();
|
void deactivate_bearers();
|
||||||
|
|
||||||
|
/// methods to handle activity timer
|
||||||
|
std::string to_string(const activity_timeout_type_t& type);
|
||||||
|
void set_activity_timeout(activity_timeout_type_t type);
|
||||||
|
void set_activity(bool enabled = true);
|
||||||
|
void activity_timer_expired(const activity_timeout_type_t type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
rrc_nr* parent = nullptr;
|
rrc_nr* parent = nullptr;
|
||||||
uint16_t rnti = SRSRAN_INVALID_RNTI;
|
uint16_t rnti = SRSRAN_INVALID_RNTI;
|
||||||
|
/// for basic DL/UL activity timeout
|
||||||
|
srsran::unique_timer activity_timer;
|
||||||
|
|
||||||
int pack_rrc_reconfiguration(asn1::dyn_octstring& packed_rrc_reconfig);
|
int pack_rrc_reconfiguration(asn1::dyn_octstring& packed_rrc_reconfig);
|
||||||
int pack_secondary_cell_group_cfg(asn1::dyn_octstring& packed_secondary_cell_config);
|
int pack_secondary_cell_group_cfg(asn1::dyn_octstring& packed_secondary_cell_config);
|
||||||
|
@ -231,8 +248,10 @@ private:
|
||||||
|
|
||||||
uint32_t nof_si_messages = 0;
|
uint32_t nof_si_messages = 0;
|
||||||
|
|
||||||
// Private Methods
|
/// Private Methods
|
||||||
void handle_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu);
|
void handle_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu);
|
||||||
|
/// This gets called by rrc_nr::sgnb_addition_request and WILL NOT TRIGGER the RX MSG3 activity timer
|
||||||
|
int add_user(uint16_t rnti, const sched_nr_ue_cfg_t& uecfg, bool start_msg3_timer);
|
||||||
|
|
||||||
// logging
|
// logging
|
||||||
typedef enum { Rx = 0, Tx } direction_t;
|
typedef enum { Rx = 0, Tx } direction_t;
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <unordered_map>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "srsenb/hdr/common/common_enb.h"
|
#include "srsenb/hdr/common/common_enb.h"
|
||||||
|
@ -131,7 +132,7 @@ private:
|
||||||
pdcp_interface_gtpu* pdcp = nullptr;
|
pdcp_interface_gtpu* pdcp = nullptr;
|
||||||
srslog::basic_logger& logger;
|
srslog::basic_logger& logger;
|
||||||
|
|
||||||
rnti_map_t<ue_bearer_tunnel_list> ue_teidin_db;
|
std::unordered_map<uint16_t, ue_bearer_tunnel_list> ue_teidin_db;
|
||||||
tunnel_list_t tunnels;
|
tunnel_list_t tunnels;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -86,6 +86,7 @@ private:
|
||||||
void discard_sdu(uint32_t lcid, uint32_t discard_sn);
|
void discard_sdu(uint32_t lcid, uint32_t discard_sn);
|
||||||
bool rb_is_um(uint32_t lcid);
|
bool rb_is_um(uint32_t lcid);
|
||||||
bool sdu_queue_is_full(uint32_t lcid);
|
bool sdu_queue_is_full(uint32_t lcid);
|
||||||
|
bool is_suspended(uint32_t lcid);
|
||||||
};
|
};
|
||||||
|
|
||||||
class user_interface_gtpu : public srsue::gw_interface_pdcp
|
class user_interface_gtpu : public srsue::gw_interface_pdcp
|
||||||
|
|
|
@ -62,6 +62,7 @@ public:
|
||||||
bool has_bearer(uint16_t rnti, uint32_t lcid);
|
bool has_bearer(uint16_t rnti, uint32_t lcid);
|
||||||
bool suspend_bearer(uint16_t rnti, uint32_t lcid);
|
bool suspend_bearer(uint16_t rnti, uint32_t lcid);
|
||||||
bool resume_bearer(uint16_t rnti, uint32_t lcid);
|
bool resume_bearer(uint16_t rnti, uint32_t lcid);
|
||||||
|
bool is_suspended(uint16_t rnti, uint32_t lcid);
|
||||||
void reestablish(uint16_t rnti) final;
|
void reestablish(uint16_t rnti) final;
|
||||||
|
|
||||||
// rlc_interface_pdcp
|
// rlc_interface_pdcp
|
||||||
|
|
|
@ -84,6 +84,7 @@ cell_list =
|
||||||
pci = 2;
|
pci = 2;
|
||||||
//direct_forward_path_available = false;
|
//direct_forward_path_available = false;
|
||||||
//allowed_meas_bw = 6;
|
//allowed_meas_bw = 6;
|
||||||
|
//cell_individual_offset = 0;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -780,9 +780,10 @@ static int parse_meas_cell_list(rrc_meas_cfg_t* meas_cfg, Setting& root)
|
||||||
cell.earfcn = root[i]["dl_earfcn"];
|
cell.earfcn = root[i]["dl_earfcn"];
|
||||||
cell.pci = (unsigned int)root[i]["pci"] % SRSRAN_NUM_PCI;
|
cell.pci = (unsigned int)root[i]["pci"] % SRSRAN_NUM_PCI;
|
||||||
cell.eci = (unsigned int)root[i]["eci"];
|
cell.eci = (unsigned int)root[i]["eci"];
|
||||||
cell.q_offset = 0; // LIBLTE_RRC_Q_OFFSET_RANGE_DB_0; // TODO
|
|
||||||
parse_default_field(cell.direct_forward_path_available, root[i], "direct_forward_path_available", false);
|
parse_default_field(cell.direct_forward_path_available, root[i], "direct_forward_path_available", false);
|
||||||
parse_default_field(cell.allowed_meas_bw, root[i], "allowed_meas_bw", 6u);
|
parse_default_field(cell.allowed_meas_bw, root[i], "allowed_meas_bw", 6u);
|
||||||
|
asn1_parsers::default_number_to_enum(
|
||||||
|
cell.cell_individual_offset, root[i], "cell_individual_offset", asn1::rrc::q_offset_range_opts::db0);
|
||||||
srsran_assert(srsran::is_lte_cell_nof_prb(cell.allowed_meas_bw), "Invalid measurement Bandwidth");
|
srsran_assert(srsran::is_lte_cell_nof_prb(cell.allowed_meas_bw), "Invalid measurement Bandwidth");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -504,6 +504,13 @@ static void execute_cmd(metrics_stdout* metrics, srsenb::enb_command_interface*
|
||||||
|
|
||||||
// Set cell gain
|
// Set cell gain
|
||||||
control->cmd_cell_gain(cell_id, gain_db);
|
control->cmd_cell_gain(cell_id, gain_db);
|
||||||
|
} else if (cmd[0] == "flush") {
|
||||||
|
if (cmd.size() != 1) {
|
||||||
|
cout << "Usage: " << cmd[0] << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
srslog::flush();
|
||||||
|
cout << "Flushed log file buffers" << endl;
|
||||||
} else {
|
} else {
|
||||||
cout << "Available commands: " << endl;
|
cout << "Available commands: " << endl;
|
||||||
cout << " t: starts console trace" << endl;
|
cout << " t: starts console trace" << endl;
|
||||||
|
@ -511,6 +518,7 @@ static void execute_cmd(metrics_stdout* metrics, srsenb::enb_command_interface*
|
||||||
cout << " cell_gain: set relative cell gain" << endl;
|
cout << " cell_gain: set relative cell gain" << endl;
|
||||||
cout << " sleep: pauses the commmand line operation for a given time in seconds" << endl;
|
cout << " sleep: pauses the commmand line operation for a given time in seconds" << endl;
|
||||||
cout << " p: starts MAC padding" << endl;
|
cout << " p: starts MAC padding" << endl;
|
||||||
|
cout << " flush: flushes the buffers for the log file" << endl;
|
||||||
cout << endl;
|
cout << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -262,7 +262,7 @@ void cc_worker::work_dl(const srsran_dl_sf_cfg_t& dl_sf_cfg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cc_worker::decode_pusch_rnti(stack_interface_phy_lte::ul_sched_grant_t& ul_grant,
|
bool cc_worker::decode_pusch_rnti(stack_interface_phy_lte::ul_sched_grant_t& ul_grant,
|
||||||
srsran_ul_cfg_t& ul_cfg,
|
srsran_ul_cfg_t& ul_cfg,
|
||||||
srsran_pusch_res_t& pusch_res)
|
srsran_pusch_res_t& pusch_res)
|
||||||
{
|
{
|
||||||
|
@ -270,19 +270,19 @@ void cc_worker::decode_pusch_rnti(stack_interface_phy_lte::ul_sched_grant_t& ul_
|
||||||
|
|
||||||
// Invalid RNTI
|
// Invalid RNTI
|
||||||
if (rnti == SRSRAN_INVALID_RNTI) {
|
if (rnti == SRSRAN_INVALID_RNTI) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// RNTI does not exist
|
// RNTI does not exist
|
||||||
if (ue_db.count(rnti) == 0) {
|
if (ue_db.count(rnti) == 0) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get UE configuration
|
// Get UE configuration
|
||||||
if (phy->ue_db.get_ul_config(rnti, cc_idx, ul_cfg) < SRSRAN_SUCCESS) {
|
if (phy->ue_db.get_ul_config(rnti, cc_idx, ul_cfg) < SRSRAN_SUCCESS) {
|
||||||
// It could happen that the UL configuration is missing due to intra-enb HO which is not an error
|
// It could happen that the UL configuration is missing due to intra-enb HO which is not an error
|
||||||
Info("Failed retrieving UL configuration for cc=%d rnti=0x%x", cc_idx, rnti);
|
Info("Failed retrieving UL configuration for cc=%d rnti=0x%x", cc_idx, rnti);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill UCI configuration
|
// Fill UCI configuration
|
||||||
|
@ -293,7 +293,7 @@ void cc_worker::decode_pusch_rnti(stack_interface_phy_lte::ul_sched_grant_t& ul_
|
||||||
srsran_pusch_grant_t& grant = ul_cfg.pusch.grant;
|
srsran_pusch_grant_t& grant = ul_cfg.pusch.grant;
|
||||||
if (srsran_ra_ul_dci_to_grant(&enb_ul.cell, &ul_sf, &ul_cfg.hopping, &ul_grant.dci, &grant)) {
|
if (srsran_ra_ul_dci_to_grant(&enb_ul.cell, &ul_sf, &ul_cfg.hopping, &ul_grant.dci, &grant)) {
|
||||||
Error("Computing PUSCH dci for RNTI %x", rnti);
|
Error("Computing PUSCH dci for RNTI %x", rnti);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle Format0 adaptive retx
|
// Handle Format0 adaptive retx
|
||||||
|
@ -302,7 +302,7 @@ void cc_worker::decode_pusch_rnti(stack_interface_phy_lte::ul_sched_grant_t& ul_
|
||||||
int rv_idx = grant.tb.rv;
|
int rv_idx = grant.tb.rv;
|
||||||
if (phy->ue_db.get_last_ul_tb(rnti, cc_idx, ul_grant.pid, grant.tb) < SRSRAN_SUCCESS) {
|
if (phy->ue_db.get_last_ul_tb(rnti, cc_idx, ul_grant.pid, grant.tb) < SRSRAN_SUCCESS) {
|
||||||
Error("Error retrieving last UL TB for RNTI %x, CC %d, PID %d", rnti, cc_idx, ul_grant.pid);
|
Error("Error retrieving last UL TB for RNTI %x, CC %d, PID %d", rnti, cc_idx, ul_grant.pid);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
grant.tb.rv = rv_idx;
|
grant.tb.rv = rv_idx;
|
||||||
Info("Adaptive retx: rnti=0x%x, pid=%d, rv_idx=%d, mcs=%d, old_tbs=%d",
|
Info("Adaptive retx: rnti=0x%x, pid=%d, rv_idx=%d, mcs=%d, old_tbs=%d",
|
||||||
|
@ -323,7 +323,7 @@ void cc_worker::decode_pusch_rnti(stack_interface_phy_lte::ul_sched_grant_t& ul_
|
||||||
if (pusch_res.data) {
|
if (pusch_res.data) {
|
||||||
if (srsran_enb_ul_get_pusch(&enb_ul, &ul_sf, &ul_cfg.pusch, &pusch_res)) {
|
if (srsran_enb_ul_get_pusch(&enb_ul, &ul_sf, &ul_cfg.pusch, &pusch_res)) {
|
||||||
Error("Decoding PUSCH for RNTI %x", rnti);
|
Error("Decoding PUSCH for RNTI %x", rnti);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Save PHICH scheduling for this user. Each user can have just 1 PUSCH dci per TTI
|
// Save PHICH scheduling for this user. Each user can have just 1 PUSCH dci per TTI
|
||||||
|
@ -353,6 +353,7 @@ void cc_worker::decode_pusch_rnti(stack_interface_phy_lte::ul_sched_grant_t& ul_
|
||||||
// Save metrics stats
|
// Save metrics stats
|
||||||
ue_db[rnti]->metrics_ul(ul_grant.dci.tb.mcs_idx, 0, enb_ul.chest_res.snr_db, pusch_res.avg_iterations_block);
|
ue_db[rnti]->metrics_ul(ul_grant.dci.tb.mcs_idx, 0, enb_ul.chest_res.snr_db, pusch_res.avg_iterations_block);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cc_worker::decode_pusch(stack_interface_phy_lte::ul_sched_grant_t* grants, uint32_t nof_pusch)
|
void cc_worker::decode_pusch(stack_interface_phy_lte::ul_sched_grant_t* grants, uint32_t nof_pusch)
|
||||||
|
@ -367,7 +368,9 @@ void cc_worker::decode_pusch(stack_interface_phy_lte::ul_sched_grant_t* grants,
|
||||||
srsran_ul_cfg_t ul_cfg = {};
|
srsran_ul_cfg_t ul_cfg = {};
|
||||||
|
|
||||||
// Decodes PUSCH for the given grant
|
// Decodes PUSCH for the given grant
|
||||||
decode_pusch_rnti(ul_grant, ul_cfg, pusch_res);
|
if (!decode_pusch_rnti(ul_grant, ul_cfg, pusch_res)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Notify MAC new received data and HARQ Indication value
|
// Notify MAC new received data and HARQ Indication value
|
||||||
if (ul_grant.data != nullptr) {
|
if (ul_grant.data != nullptr) {
|
||||||
|
|
|
@ -157,6 +157,11 @@ bool slot_worker::work_ul()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ul_sched.pucch.empty() && ul_sched.pusch.empty()) {
|
||||||
|
// early exit if nothing has been scheduled
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Demodulate
|
// Demodulate
|
||||||
if (srsran_gnb_ul_fft(&gnb_ul) < SRSRAN_SUCCESS) {
|
if (srsran_gnb_ul_fft(&gnb_ul) < SRSRAN_SUCCESS) {
|
||||||
logger.error("Error in demodulation");
|
logger.error("Error in demodulation");
|
||||||
|
|
|
@ -98,27 +98,6 @@ slot_worker* worker_pool::wait_worker(uint32_t tti)
|
||||||
{
|
{
|
||||||
slot_worker* w = (slot_worker*)pool.wait_worker(tti);
|
slot_worker* w = (slot_worker*)pool.wait_worker(tti);
|
||||||
|
|
||||||
// Only if a worker was available
|
|
||||||
if (w != nullptr) {
|
|
||||||
srsran_carrier_nr_t carrier_;
|
|
||||||
srsran_pdcch_cfg_nr_t pdcch_cfg_;
|
|
||||||
srsran_ssb_cfg_t ssb_cfg_;
|
|
||||||
|
|
||||||
// Copy configuration
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> lock(common_cfg_mutex);
|
|
||||||
carrier_ = carrier;
|
|
||||||
pdcch_cfg_ = pdcch_cfg;
|
|
||||||
ssb_cfg_ = ssb_cfg;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set worker configuration
|
|
||||||
if (not w->set_common_cfg(carrier_, pdcch_cfg_, ssb_cfg_)) {
|
|
||||||
logger.error("Error setting common config");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save current TTI
|
// Save current TTI
|
||||||
current_tti = tti;
|
current_tti = tti;
|
||||||
|
|
||||||
|
@ -162,15 +141,28 @@ int worker_pool::set_common_cfg(const phy_interface_rrc_nr::common_cfg_t& common
|
||||||
prach.init(0, cell, prach_cfg, &prach_stack_adaptor, logger, 0, nof_prach_workers);
|
prach.init(0, cell, prach_cfg, &prach_stack_adaptor, logger, 0, nof_prach_workers);
|
||||||
prach.set_max_prach_offset_us(1000);
|
prach.set_max_prach_offset_us(1000);
|
||||||
|
|
||||||
// Save current configuration
|
// Setup SSB sampling rate and scaling
|
||||||
{
|
srsran_ssb_cfg_t ssb_cfg = common_cfg.ssb;
|
||||||
std::unique_lock<std::mutex> lock(common_cfg_mutex);
|
|
||||||
carrier = common_cfg.carrier;
|
|
||||||
pdcch_cfg = common_cfg.pdcch;
|
|
||||||
ssb_cfg = common_cfg.ssb;
|
|
||||||
ssb_cfg.srate_hz = srate_hz;
|
ssb_cfg.srate_hz = srate_hz;
|
||||||
ssb_cfg.scaling =
|
ssb_cfg.scaling =
|
||||||
srsran_convert_dB_to_amplitude(srsran_gnb_dl_get_maximum_signal_power_dBfs(common_cfg.carrier.nof_prb));
|
srsran_convert_dB_to_amplitude(srsran_gnb_dl_get_maximum_signal_power_dBfs(common_cfg.carrier.nof_prb));
|
||||||
|
|
||||||
|
// For each worker set configuration
|
||||||
|
for (uint32_t i = 0; i < pool.get_nof_workers(); i++) {
|
||||||
|
// Reserve worker from pool
|
||||||
|
slot_worker* w = (slot_worker*)pool.wait_worker_id(i);
|
||||||
|
if (w == nullptr) {
|
||||||
|
// Skip worker if invalid pointer
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup worker common configuration
|
||||||
|
if (not w->set_common_cfg(common_cfg.carrier, common_cfg.pdcch, ssb_cfg)) {
|
||||||
|
return SRSRAN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release worker
|
||||||
|
w->release();
|
||||||
}
|
}
|
||||||
|
|
||||||
return SRSRAN_SUCCESS;
|
return SRSRAN_SUCCESS;
|
||||||
|
|
|
@ -94,7 +94,7 @@ void phy_common::clear_grants(uint16_t rnti)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const stack_interface_phy_lte::ul_sched_list_t& phy_common::get_ul_grants(uint32_t tti)
|
const stack_interface_phy_lte::ul_sched_list_t phy_common::get_ul_grants(uint32_t tti)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(grant_mutex);
|
std::lock_guard<std::mutex> lock(grant_mutex);
|
||||||
return ul_grants[tti];
|
return ul_grants[tti];
|
||||||
|
|
|
@ -793,6 +793,7 @@ int phy_ue_db::set_ul_grant_available(uint32_t tti, const stack_interface_phy_lt
|
||||||
// Check that eNb Cell/Carrier is active for the given RNTI
|
// Check that eNb Cell/Carrier is active for the given RNTI
|
||||||
if (_assert_active_enb_cc(rnti, enb_cc_idx) != SRSRAN_SUCCESS) {
|
if (_assert_active_enb_cc(rnti, enb_cc_idx) != SRSRAN_SUCCESS) {
|
||||||
ret = SRSRAN_ERROR;
|
ret = SRSRAN_ERROR;
|
||||||
|
srslog::fetch_basic_logger("PHY").error("Error setting grant for rnti=0x%x, cc=%d\n", rnti, enb_cc_idx);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Rise Grant available flag
|
// Rise Grant available flag
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "srsenb/hdr/stack/mac/common/ue_buffer_manager.h"
|
#include "srsenb/hdr/stack/mac/common/ue_buffer_manager.h"
|
||||||
|
#include "srsran/adt/bounded_vector.h"
|
||||||
#include "srsran/common/string_helpers.h"
|
#include "srsran/common/string_helpers.h"
|
||||||
#include "srsran/srslog/bundled/fmt/format.h"
|
#include "srsran/srslog/bundled/fmt/format.h"
|
||||||
#include "srsran/srslog/bundled/fmt/ranges.h"
|
#include "srsran/srslog/bundled/fmt/ranges.h"
|
||||||
|
@ -27,21 +28,71 @@
|
||||||
namespace srsenb {
|
namespace srsenb {
|
||||||
|
|
||||||
template <bool isNR>
|
template <bool isNR>
|
||||||
ue_buffer_manager<isNR>::ue_buffer_manager(srslog::basic_logger& logger_) : logger(logger_)
|
ue_buffer_manager<isNR>::ue_buffer_manager(uint16_t rnti_, srslog::basic_logger& logger_) : logger(logger_), rnti(rnti_)
|
||||||
{
|
{
|
||||||
std::fill(lcg_bsr.begin(), lcg_bsr.end(), 0);
|
std::fill(lcg_bsr.begin(), lcg_bsr.end(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <bool isNR>
|
||||||
|
void ue_buffer_manager<isNR>::config_lcids(srsran::const_span<mac_lc_ch_cfg_t> bearer_cfg_list)
|
||||||
|
{
|
||||||
|
bool log_enabled = logger.info.enabled();
|
||||||
|
srsran::bounded_vector<uint32_t, MAX_NOF_LCIDS> changed_list;
|
||||||
|
|
||||||
|
for (uint32_t lcid = 0; is_lcid_valid(lcid); ++lcid) {
|
||||||
|
if (config_lcid_internal(lcid, bearer_cfg_list[lcid]) and log_enabled) {
|
||||||
|
// add to the changed_list the lcids that have been updated with new parameters
|
||||||
|
changed_list.push_back(lcid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log configurations of the LCIDs for which there were param updates
|
||||||
|
if (not changed_list.empty()) {
|
||||||
|
fmt::memory_buffer fmtbuf;
|
||||||
|
for (uint32_t i = 0; i < changed_list.size(); ++i) {
|
||||||
|
uint32_t lcid = changed_list[i];
|
||||||
|
fmt::format_to(fmtbuf,
|
||||||
|
"{}{{lcid={}, mode={}, prio={}, lcg={}}}",
|
||||||
|
i > 0 ? ", " : "",
|
||||||
|
lcid,
|
||||||
|
to_string(channels[lcid].cfg.direction),
|
||||||
|
channels[lcid].cfg.priority,
|
||||||
|
channels[lcid].cfg.group);
|
||||||
|
}
|
||||||
|
logger.info("SCHED: rnti=0x%x, new lcid configuration: [%s]", rnti, srsran::to_c_str(fmtbuf));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <bool isNR>
|
template <bool isNR>
|
||||||
void ue_buffer_manager<isNR>::config_lcid(uint32_t lcid, const mac_lc_ch_cfg_t& bearer_cfg)
|
void ue_buffer_manager<isNR>::config_lcid(uint32_t lcid, const mac_lc_ch_cfg_t& bearer_cfg)
|
||||||
|
{
|
||||||
|
bool cfg_changed = config_lcid_internal(lcid, bearer_cfg);
|
||||||
|
if (cfg_changed) {
|
||||||
|
logger.info("SCHED: rnti=0x%x, lcid=%d configured: mode=%s, prio=%d, lcg=%d",
|
||||||
|
rnti,
|
||||||
|
lcid,
|
||||||
|
to_string(channels[lcid].cfg.direction),
|
||||||
|
channels[lcid].cfg.priority,
|
||||||
|
channels[lcid].cfg.group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief configure MAC logical channel. The function checks if the configuration is valid
|
||||||
|
* and whether there was any change compared to previous value
|
||||||
|
* @return true if the lcid was updated with new parameters. False in case of case of error or no update.
|
||||||
|
*/
|
||||||
|
template <bool isNR>
|
||||||
|
bool ue_buffer_manager<isNR>::config_lcid_internal(uint32_t lcid, const mac_lc_ch_cfg_t& bearer_cfg)
|
||||||
{
|
{
|
||||||
if (not is_lcid_valid(lcid)) {
|
if (not is_lcid_valid(lcid)) {
|
||||||
logger.warning("Configuring bearer with invalid logical channel id=%d", lcid);
|
logger.warning("SCHED: Configuring rnti=0x%x bearer with invalid lcid=%d", rnti, lcid);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
if (not is_lcg_valid(bearer_cfg.group)) {
|
if (not is_lcg_valid(bearer_cfg.group)) {
|
||||||
logger.warning("Configuring bearer with invalid logical channel group id=%d", bearer_cfg.group);
|
logger.warning(
|
||||||
return;
|
"SCHED: Configuring rnti=0x%x bearer with invalid logical channel group id=%d", rnti, bearer_cfg.group);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update bearer config
|
// update bearer config
|
||||||
|
@ -54,12 +105,9 @@ void ue_buffer_manager<isNR>::config_lcid(uint32_t lcid, const mac_lc_ch_cfg_t&
|
||||||
channels[lcid].bucket_size = channels[lcid].cfg.bsd * channels[lcid].cfg.pbr;
|
channels[lcid].bucket_size = channels[lcid].cfg.bsd * channels[lcid].cfg.pbr;
|
||||||
channels[lcid].Bj = 0;
|
channels[lcid].Bj = 0;
|
||||||
}
|
}
|
||||||
logger.info("SCHED: bearer configured: lcid=%d, mode=%s, prio=%d, lcg=%d",
|
return true;
|
||||||
lcid,
|
|
||||||
to_string(channels[lcid].cfg.direction),
|
|
||||||
channels[lcid].cfg.priority,
|
|
||||||
channels[lcid].cfg.group);
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool isNR>
|
template <bool isNR>
|
||||||
|
@ -108,7 +156,7 @@ template <bool isNR>
|
||||||
void ue_buffer_manager<isNR>::ul_bsr(uint32_t lcg_id, uint32_t val)
|
void ue_buffer_manager<isNR>::ul_bsr(uint32_t lcg_id, uint32_t val)
|
||||||
{
|
{
|
||||||
if (not is_lcg_valid(lcg_id)) {
|
if (not is_lcg_valid(lcg_id)) {
|
||||||
logger.warning("The provided logical channel group id=%d is not valid", lcg_id);
|
logger.warning("SCHED: The provided lcg_id=%d for rnti=0x%x is not valid", lcg_id, rnti);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lcg_bsr[lcg_id] = val;
|
lcg_bsr[lcg_id] = val;
|
||||||
|
@ -116,24 +164,25 @@ void ue_buffer_manager<isNR>::ul_bsr(uint32_t lcg_id, uint32_t val)
|
||||||
if (logger.debug.enabled()) {
|
if (logger.debug.enabled()) {
|
||||||
fmt::memory_buffer str_buffer;
|
fmt::memory_buffer str_buffer;
|
||||||
fmt::format_to(str_buffer, "{}", lcg_bsr);
|
fmt::format_to(str_buffer, "{}", lcg_bsr);
|
||||||
logger.debug("SCHED: lcg_id=%d, bsr=%d. Current state=%s", lcg_id, val, srsran::to_c_str(str_buffer));
|
logger.debug(
|
||||||
|
"SCHED: rnti=0x%x, lcg_id=%d, bsr=%d. Current state=%s", rnti, lcg_id, val, srsran::to_c_str(str_buffer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool isNR>
|
template <bool isNR>
|
||||||
void ue_buffer_manager<isNR>::dl_buffer_state(uint8_t lcid, uint32_t tx_queue, uint32_t retx_queue)
|
void ue_buffer_manager<isNR>::dl_buffer_state(uint8_t lcid, uint32_t tx_queue, uint32_t prio_tx_queue)
|
||||||
{
|
{
|
||||||
if (not is_lcid_valid(lcid)) {
|
if (not is_lcid_valid(lcid)) {
|
||||||
logger.warning("The provided lcid=%d is not valid", lcid);
|
logger.warning("The provided lcid=%d is not valid", lcid);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (lcid <= MAX_SRB_LC_ID and
|
if (lcid <= MAX_SRB_LC_ID and
|
||||||
(channels[lcid].buf_tx != (int)tx_queue or channels[lcid].buf_retx != (int)retx_queue)) {
|
(channels[lcid].buf_tx != (int)tx_queue or channels[lcid].buf_prio_tx != (int)prio_tx_queue)) {
|
||||||
logger.info("SCHED: DL lcid=%d buffer_state=%d,%d", lcid, tx_queue, retx_queue);
|
logger.info("SCHED: rnti=0x%x DL lcid=%d buffer_state=%d,%d", rnti, lcid, tx_queue, prio_tx_queue);
|
||||||
} else {
|
} else {
|
||||||
logger.debug("SCHED: DL lcid=%d buffer_state=%d,%d", lcid, tx_queue, retx_queue);
|
logger.debug("SCHED: rnti=0x%x DL lcid=%d buffer_state=%d,%d", rnti, lcid, tx_queue, prio_tx_queue);
|
||||||
}
|
}
|
||||||
channels[lcid].buf_retx = retx_queue;
|
channels[lcid].buf_prio_tx = prio_tx_queue;
|
||||||
channels[lcid].buf_tx = tx_queue;
|
channels[lcid].buf_tx = tx_queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -225,10 +225,7 @@ int mac::ue_rem(uint16_t rnti)
|
||||||
int mac::ue_set_crnti(uint16_t temp_crnti, uint16_t crnti, const sched_interface::ue_cfg_t& cfg)
|
int mac::ue_set_crnti(uint16_t temp_crnti, uint16_t crnti, const sched_interface::ue_cfg_t& cfg)
|
||||||
{
|
{
|
||||||
srsran::rwlock_read_guard lock(rwlock);
|
srsran::rwlock_read_guard lock(rwlock);
|
||||||
if (temp_crnti != crnti) {
|
if (temp_crnti == crnti) {
|
||||||
// if C-RNTI is changed, it corresponds to older user. Handover scenario.
|
|
||||||
ue_db[crnti]->reset();
|
|
||||||
} else {
|
|
||||||
// Schedule ConRes Msg4
|
// Schedule ConRes Msg4
|
||||||
scheduler.dl_mac_buffer_state(crnti, (uint32_t)srsran::dl_sch_lcid::CON_RES_ID);
|
scheduler.dl_mac_buffer_state(crnti, (uint32_t)srsran::dl_sch_lcid::CON_RES_ID);
|
||||||
}
|
}
|
||||||
|
|
|
@ -305,15 +305,17 @@ int mac_nr::get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched
|
||||||
logger.set_context(slot_cfg.idx - TX_ENB_DELAY);
|
logger.set_context(slot_cfg.idx - TX_ENB_DELAY);
|
||||||
|
|
||||||
slot_point pdsch_slot = srsran::slot_point{NUMEROLOGY_IDX, slot_cfg.idx};
|
slot_point pdsch_slot = srsran::slot_point{NUMEROLOGY_IDX, slot_cfg.idx};
|
||||||
sched_nr_interface::dl_sched_res_t dl_res;
|
|
||||||
|
|
||||||
// Run Scheduler
|
// Run Scheduler
|
||||||
|
sched_nr_interface::sched_rar_list_t rar_list;
|
||||||
|
sched_nr_interface::dl_res_t dl_res(rar_list, dl_sched);
|
||||||
|
|
||||||
int ret = sched.run_slot(pdsch_slot, 0, dl_res);
|
int ret = sched.run_slot(pdsch_slot, 0, dl_res);
|
||||||
if (ret != SRSRAN_SUCCESS) {
|
if (ret != SRSRAN_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
dl_sched = dl_res.dl_sched;
|
|
||||||
|
|
||||||
|
// Generate MAC DL PDUs
|
||||||
uint32_t rar_count = 0;
|
uint32_t rar_count = 0;
|
||||||
srsran::rwlock_read_guard rw_lock(rwmutex);
|
srsran::rwlock_read_guard rw_lock(rwmutex);
|
||||||
for (pdsch_t& pdsch : dl_sched.pdsch) {
|
for (pdsch_t& pdsch : dl_sched.pdsch) {
|
||||||
|
|
|
@ -140,10 +140,10 @@ void sched_nr::ue_cfg_impl(uint16_t rnti, const ue_cfg_t& uecfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate {pdcch_slot,cc} scheduling decision
|
/// Generate {pdcch_slot,cc} scheduling decision
|
||||||
int sched_nr::run_slot(slot_point slot_dl, uint32_t cc, dl_sched_res_t& result)
|
int sched_nr::run_slot(slot_point slot_dl, uint32_t cc, dl_res_t& result)
|
||||||
{
|
{
|
||||||
// Copy UL results to intermediate buffer
|
// Copy UL results to intermediate buffer
|
||||||
ul_sched_t& ul_res = pending_results->add_ul_result(slot_dl, cc);
|
ul_res_t& ul_res = pending_results->add_ul_result(slot_dl, cc);
|
||||||
|
|
||||||
// Generate {slot_idx,cc} result
|
// Generate {slot_idx,cc} result
|
||||||
sched_workers->run_slot(slot_dl, cc, result, ul_res);
|
sched_workers->run_slot(slot_dl, cc, result, ul_res);
|
||||||
|
@ -152,7 +152,7 @@ int sched_nr::run_slot(slot_point slot_dl, uint32_t cc, dl_sched_res_t& result)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fetch {ul_slot,cc} UL scheduling decision
|
/// Fetch {ul_slot,cc} UL scheduling decision
|
||||||
int sched_nr::get_ul_sched(slot_point slot_ul, uint32_t cc, ul_sched_t& result)
|
int sched_nr::get_ul_sched(slot_point slot_ul, uint32_t cc, ul_res_t& result)
|
||||||
{
|
{
|
||||||
if (not pending_results->has_ul_result(slot_ul, cc)) {
|
if (not pending_results->has_ul_result(slot_ul, cc)) {
|
||||||
// sched result hasn't been generated
|
// sched result hasn't been generated
|
||||||
|
|
|
@ -142,7 +142,7 @@ void ra_sched::run_slot(bwp_slot_allocator& slot_alloc)
|
||||||
if (pdcch_slot >= rar.rar_win.stop()) {
|
if (pdcch_slot >= rar.rar_win.stop()) {
|
||||||
fmt::memory_buffer str_buffer;
|
fmt::memory_buffer str_buffer;
|
||||||
fmt::format_to(str_buffer,
|
fmt::format_to(str_buffer,
|
||||||
"SCHED: Could not transmit RAR within the window Window={}, PRACH={}, RAR={}",
|
"SCHED: Could not transmit RAR within the window={}, PRACH={}, RAR={}",
|
||||||
rar.rar_win,
|
rar.rar_win,
|
||||||
rar.prach_slot,
|
rar.prach_slot,
|
||||||
pdcch_slot);
|
pdcch_slot);
|
||||||
|
|
|
@ -119,6 +119,13 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t
|
||||||
if (ret != alloc_result::success) {
|
if (ret != alloc_result::success) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
if (bwp_pdcch_slot.rar.full()) {
|
||||||
|
return alloc_result::no_grant_space;
|
||||||
|
}
|
||||||
|
if (pending_rars.size() > MAX_GRANTS) {
|
||||||
|
logger.error("SCHED: Trying to allocate too many Msg3 grants in a single slot (%zd)", pending_rars.size());
|
||||||
|
return alloc_result::invalid_grant_params;
|
||||||
|
}
|
||||||
|
|
||||||
// Check DL RB collision
|
// Check DL RB collision
|
||||||
if (bwp_pdcch_slot.dl_prbs.collides(interv)) {
|
if (bwp_pdcch_slot.dl_prbs.collides(interv)) {
|
||||||
|
@ -218,6 +225,10 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, const prb_grant& dl_gr
|
||||||
if (result != alloc_result::success) {
|
if (result != alloc_result::success) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
if (bwp_uci_slot.pending_acks.full()) {
|
||||||
|
logger.warning("SCHED: PDSCH allocation for rnti=0x%x failed due to lack of space for respective ACK", ue.rnti);
|
||||||
|
return alloc_result::no_grant_space;
|
||||||
|
}
|
||||||
if (bwp_pdsch_slot.dl_prbs.collides(dl_grant)) {
|
if (bwp_pdsch_slot.dl_prbs.collides(dl_grant)) {
|
||||||
return alloc_result::sch_collision;
|
return alloc_result::sch_collision;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,11 +37,13 @@ int harq_proc::ack_info(uint32_t tb_idx, bool ack)
|
||||||
return ack ? tb[tb_idx].tbs : 0;
|
return ack ? tb[tb_idx].tbs : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void harq_proc::new_slot(slot_point slot_rx)
|
bool harq_proc::clear_if_maxretx(slot_point slot_rx)
|
||||||
{
|
{
|
||||||
if (has_pending_retx(slot_rx) and nof_retx() + 1 >= max_nof_retx()) {
|
if (has_pending_retx(slot_rx) and nof_retx() + 1 > max_nof_retx()) {
|
||||||
tb[0].active = false;
|
tb[0].active = false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void harq_proc::reset()
|
void harq_proc::reset()
|
||||||
|
@ -129,14 +131,14 @@ bool dl_harq_proc::new_tx(slot_point slot_tx,
|
||||||
uint32_t max_retx)
|
uint32_t max_retx)
|
||||||
{
|
{
|
||||||
if (harq_proc::new_tx(slot_tx, slot_ack, grant, mcs, max_retx)) {
|
if (harq_proc::new_tx(slot_tx, slot_ack, grant, mcs, max_retx)) {
|
||||||
softbuffer->reset();
|
|
||||||
pdu->clear();
|
pdu->clear();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
harq_entity::harq_entity(uint32_t nprb, uint32_t nof_harq_procs)
|
harq_entity::harq_entity(uint16_t rnti_, uint32_t nprb, uint32_t nof_harq_procs, srslog::basic_logger& logger_) :
|
||||||
|
rnti(rnti_), logger(logger_)
|
||||||
{
|
{
|
||||||
// Create HARQs
|
// Create HARQs
|
||||||
dl_harqs.reserve(nof_harq_procs);
|
dl_harqs.reserve(nof_harq_procs);
|
||||||
|
@ -151,10 +153,20 @@ void harq_entity::new_slot(slot_point slot_rx_)
|
||||||
{
|
{
|
||||||
slot_rx = slot_rx_;
|
slot_rx = slot_rx_;
|
||||||
for (harq_proc& dl_h : dl_harqs) {
|
for (harq_proc& dl_h : dl_harqs) {
|
||||||
dl_h.new_slot(slot_rx);
|
if (dl_h.clear_if_maxretx(slot_rx)) {
|
||||||
|
logger.info("SCHED: discarding rnti=0x%x, DL TB pid=%d. Cause: Maximum number of retx exceeded (%d)",
|
||||||
|
rnti,
|
||||||
|
dl_h.pid,
|
||||||
|
dl_h.max_nof_retx());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (harq_proc& ul_h : ul_harqs) {
|
for (harq_proc& ul_h : ul_harqs) {
|
||||||
ul_h.new_slot(slot_rx);
|
if (ul_h.clear_if_maxretx(slot_rx)) {
|
||||||
|
logger.info("SCHED: discarding rnti=0x%x, UL TB pid=%d. Cause: Maximum number of retx exceeded (%d)",
|
||||||
|
rnti,
|
||||||
|
ul_h.pid,
|
||||||
|
ul_h.max_nof_retx());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,7 @@ bool coreset_region::alloc_dci(pdcch_grant_type_t alloc_type,
|
||||||
srsran_assert((user == nullptr) xor
|
srsran_assert((user == nullptr) xor
|
||||||
(alloc_type == pdcch_grant_type_t::dl_data or alloc_type == pdcch_grant_type_t::ul_data),
|
(alloc_type == pdcch_grant_type_t::dl_data or alloc_type == pdcch_grant_type_t::ul_data),
|
||||||
"UE should be only provided for DL or UL data allocations");
|
"UE should be only provided for DL or UL data allocations");
|
||||||
|
srsran_assert(not dci_list.full(), "SCHED: Unable to allocate DCI");
|
||||||
saved_dfs_tree.clear();
|
saved_dfs_tree.clear();
|
||||||
|
|
||||||
alloc_record record;
|
alloc_record record;
|
||||||
|
@ -89,13 +90,13 @@ bool coreset_region::alloc_dci(pdcch_grant_type_t alloc_type,
|
||||||
dci_list.push_back(record);
|
dci_list.push_back(record);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (dfs_tree.empty()) {
|
if (saved_dfs_tree.empty()) {
|
||||||
saved_dfs_tree = dfs_tree;
|
saved_dfs_tree = dfs_tree;
|
||||||
}
|
}
|
||||||
} while (get_next_dfs());
|
} while (get_next_dfs());
|
||||||
|
|
||||||
// Revert steps to initial state, before dci record allocation was attempted
|
// Revert steps to initial state, before dci record allocation was attempted
|
||||||
dfs_tree = saved_dfs_tree;
|
dfs_tree.swap(saved_dfs_tree);
|
||||||
if (record.alloc_type == pdcch_grant_type_t::ul_data) {
|
if (record.alloc_type == pdcch_grant_type_t::ul_data) {
|
||||||
pdcch_ul_list.pop_back();
|
pdcch_ul_list.pop_back();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -43,6 +43,10 @@ void sched_nzp_csi_rs(srsran::const_span<srsran_csi_rs_nzp_set_t> nzp_csi_rs_set
|
||||||
|
|
||||||
// Check if the resource is scheduled for this slot
|
// Check if the resource is scheduled for this slot
|
||||||
if (srsran_csi_rs_send(&nzp_csi_resource.periodicity, &slot_cfg)) {
|
if (srsran_csi_rs_send(&nzp_csi_resource.periodicity, &slot_cfg)) {
|
||||||
|
if (csi_rs_list.full()) {
|
||||||
|
srslog::fetch_basic_logger("MAC-NR").error("SCHED: Failed to allocate NZP-CSI RS");
|
||||||
|
return;
|
||||||
|
}
|
||||||
csi_rs_list.push_back(nzp_csi_resource);
|
csi_rs_list.push_back(nzp_csi_resource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,6 +55,10 @@ void sched_nzp_csi_rs(srsran::const_span<srsran_csi_rs_nzp_set_t> nzp_csi_rs_set
|
||||||
|
|
||||||
void sched_ssb_basic(const slot_point& sl_point, uint32_t ssb_periodicity, ssb_list& ssb_list)
|
void sched_ssb_basic(const slot_point& sl_point, uint32_t ssb_periodicity, ssb_list& ssb_list)
|
||||||
{
|
{
|
||||||
|
if (ssb_list.full()) {
|
||||||
|
srslog::fetch_basic_logger("MAC-NR").error("SCHED: Failed to allocate SSB");
|
||||||
|
return;
|
||||||
|
}
|
||||||
// If the periodicity is 0, it means that the parameter was not passed by the upper layers.
|
// If the periodicity is 0, it means that the parameter was not passed by the upper layers.
|
||||||
// In that case, we use default value of 5ms (see Clause 4.1, TS 38.213)
|
// In that case, we use default value of 5ms (see Clause 4.1, TS 38.213)
|
||||||
if (ssb_periodicity == 0) {
|
if (ssb_periodicity == 0) {
|
||||||
|
|
|
@ -35,7 +35,7 @@ ue_carrier::ue_carrier(uint16_t rnti_, const ue_cfg_t& uecfg_, const cell_params
|
||||||
cc(cell_params_.cc),
|
cc(cell_params_.cc),
|
||||||
bwp_cfg(rnti_, cell_params_.bwps[0], uecfg_),
|
bwp_cfg(rnti_, cell_params_.bwps[0], uecfg_),
|
||||||
cell_params(cell_params_),
|
cell_params(cell_params_),
|
||||||
harq_ent(cell_params_.nof_prb())
|
harq_ent(rnti_, cell_params_.nof_prb(), SCHED_NR_MAX_HARQ, cell_params_.bwps[0].logger)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void ue_carrier::set_cfg(const ue_cfg_t& ue_cfg)
|
void ue_carrier::set_cfg(const ue_cfg_t& ue_cfg)
|
||||||
|
@ -43,6 +43,11 @@ void ue_carrier::set_cfg(const ue_cfg_t& ue_cfg)
|
||||||
bwp_cfg = bwp_ue_cfg(rnti, cell_params.bwps[0], ue_cfg);
|
bwp_cfg = bwp_ue_cfg(rnti, cell_params.bwps[0], ue_cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ue_carrier::new_slot(slot_point slot_tx)
|
||||||
|
{
|
||||||
|
harq_ent.new_slot(slot_tx - TX_ENB_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
slot_ue ue_carrier::try_reserve(slot_point pdcch_slot, uint32_t dl_pending_bytes, uint32_t ul_pending_bytes)
|
slot_ue ue_carrier::try_reserve(slot_point pdcch_slot, uint32_t dl_pending_bytes, uint32_t ul_pending_bytes)
|
||||||
{
|
{
|
||||||
slot_point slot_rx = pdcch_slot - TX_ENB_DELAY;
|
slot_point slot_rx = pdcch_slot - TX_ENB_DELAY;
|
||||||
|
@ -87,7 +92,7 @@ slot_ue ue_carrier::try_reserve(slot_point pdcch_slot, uint32_t dl_pending_bytes
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ue::ue(uint16_t rnti_, const ue_cfg_t& cfg, const sched_params& sched_cfg_) :
|
ue::ue(uint16_t rnti_, const ue_cfg_t& cfg, const sched_params& sched_cfg_) :
|
||||||
rnti(rnti_), sched_cfg(sched_cfg_), buffers(srslog::fetch_basic_logger(sched_cfg_.sched_cfg.logger_name))
|
rnti(rnti_), sched_cfg(sched_cfg_), buffers(rnti_, srslog::fetch_basic_logger(sched_cfg_.sched_cfg.logger_name))
|
||||||
{
|
{
|
||||||
set_cfg(cfg);
|
set_cfg(cfg);
|
||||||
}
|
}
|
||||||
|
@ -105,23 +110,13 @@ void ue::set_cfg(const ue_cfg_t& cfg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t lcid = 0; lcid < cfg.ue_bearers.size(); ++lcid) {
|
buffers.config_lcids(cfg.ue_bearers);
|
||||||
buffers.config_lcid(lcid, cfg.ue_bearers[lcid]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ue::new_slot(slot_point pdcch_slot)
|
void ue::new_slot(slot_point pdcch_slot)
|
||||||
{
|
{
|
||||||
last_pdcch_slot = pdcch_slot;
|
last_pdcch_slot = pdcch_slot;
|
||||||
|
|
||||||
for (auto& ue_cc_cfg : ue_cfg.carriers) {
|
|
||||||
auto& cc = carriers[ue_cc_cfg.cc];
|
|
||||||
if (cc != nullptr) {
|
|
||||||
// Update CC HARQ state
|
|
||||||
cc->harq_ent.new_slot(pdcch_slot - TX_ENB_DELAY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compute pending DL/UL bytes for {rnti, pdcch_slot}
|
// Compute pending DL/UL bytes for {rnti, pdcch_slot}
|
||||||
if (sched_cfg.sched_cfg.auto_refill_buffer) {
|
if (sched_cfg.sched_cfg.auto_refill_buffer) {
|
||||||
dl_pending_bytes = 1000000;
|
dl_pending_bytes = 1000000;
|
||||||
|
@ -153,10 +148,7 @@ void ue::new_slot(slot_point pdcch_slot)
|
||||||
|
|
||||||
slot_ue ue::try_reserve(slot_point pdcch_slot, uint32_t cc)
|
slot_ue ue::try_reserve(slot_point pdcch_slot, uint32_t cc)
|
||||||
{
|
{
|
||||||
if (carriers[cc] == nullptr) {
|
srsran_assert(carriers[cc] != nullptr, "try_reserve() called for inexistent rnti=0x%x,cc=%d", rnti, cc);
|
||||||
return slot_ue();
|
|
||||||
}
|
|
||||||
|
|
||||||
return carriers[cc]->try_reserve(pdcch_slot, dl_pending_bytes, ul_pending_bytes);
|
return carriers[cc]->try_reserve(pdcch_slot, dl_pending_bytes, ul_pending_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,9 @@ void slot_cc_worker::run(slot_point pdcch_slot, ue_map_t& ue_db)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update UE CC state
|
||||||
|
u.carriers[cfg.cc]->new_slot(pdcch_slot);
|
||||||
|
|
||||||
// info for a given UE on a slot to be process
|
// info for a given UE on a slot to be process
|
||||||
slot_ues.insert(rnti, u.try_reserve(pdcch_slot, cfg.cc));
|
slot_ues.insert(rnti, u.try_reserve(pdcch_slot, cfg.cc));
|
||||||
if (slot_ues[rnti].empty()) {
|
if (slot_ues[rnti].empty()) {
|
||||||
|
@ -189,6 +192,10 @@ void slot_cc_worker::postprocess_decisions()
|
||||||
}
|
}
|
||||||
if (not has_pusch) {
|
if (not has_pusch) {
|
||||||
// If any UCI information is triggered, schedule PUCCH
|
// If any UCI information is triggered, schedule PUCCH
|
||||||
|
if (bwp_slot.pucch.full()) {
|
||||||
|
logger.warning("SCHED: Cannot fit pending UCI into PUCCH");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
bwp_slot.pucch.emplace_back();
|
bwp_slot.pucch.emplace_back();
|
||||||
mac_interface_phy_nr::pucch_t& pucch = bwp_slot.pucch.back();
|
mac_interface_phy_nr::pucch_t& pucch = bwp_slot.pucch.back();
|
||||||
|
|
||||||
|
|
|
@ -174,9 +174,9 @@ uint32_t sched::get_ul_buffer(uint16_t rnti)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sched::dl_rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t retx_queue)
|
int sched::dl_rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t prio_tx_queue)
|
||||||
{
|
{
|
||||||
return ue_db_access_locked(rnti, [&](sched_ue& ue) { ue.dl_buffer_state(lc_id, tx_queue, retx_queue); });
|
return ue_db_access_locked(rnti, [&](sched_ue& ue) { ue.dl_buffer_state(lc_id, tx_queue, prio_tx_queue); });
|
||||||
}
|
}
|
||||||
|
|
||||||
int sched::dl_mac_buffer_state(uint16_t rnti, uint32_t ce_code, uint32_t nof_cmds)
|
int sched::dl_mac_buffer_state(uint16_t rnti, uint32_t ce_code, uint32_t nof_cmds)
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace srsenb {
|
||||||
*******************************************************/
|
*******************************************************/
|
||||||
|
|
||||||
sched_ue::sched_ue(uint16_t rnti_, const std::vector<sched_cell_params_t>& cell_list_params_, const ue_cfg_t& cfg_) :
|
sched_ue::sched_ue(uint16_t rnti_, const std::vector<sched_cell_params_t>& cell_list_params_, const ue_cfg_t& cfg_) :
|
||||||
logger(srslog::fetch_basic_logger("MAC")), rnti(rnti_)
|
logger(srslog::fetch_basic_logger("MAC")), rnti(rnti_), lch_handler(rnti_)
|
||||||
{
|
{
|
||||||
cells.reserve(cell_list_params_.size());
|
cells.reserve(cell_list_params_.size());
|
||||||
for (auto& c : cell_list_params_) {
|
for (auto& c : cell_list_params_) {
|
||||||
|
|
|
@ -66,9 +66,7 @@ uint32_t get_ul_mac_sdu_size_with_overhead(uint32_t rlc_pdu_bytes)
|
||||||
|
|
||||||
void lch_ue_manager::set_cfg(const sched_interface::ue_cfg_t& cfg)
|
void lch_ue_manager::set_cfg(const sched_interface::ue_cfg_t& cfg)
|
||||||
{
|
{
|
||||||
for (uint32_t lcid = 0; is_lcid_valid(lcid); lcid++) {
|
config_lcids(cfg.ue_bearers);
|
||||||
config_lcid(lcid, cfg.ue_bearers[lcid]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void lch_ue_manager::new_tti()
|
void lch_ue_manager::new_tti()
|
||||||
|
@ -87,15 +85,18 @@ void lch_ue_manager::new_tti()
|
||||||
void lch_ue_manager::ul_buffer_add(uint8_t lcid, uint32_t bytes)
|
void lch_ue_manager::ul_buffer_add(uint8_t lcid, uint32_t bytes)
|
||||||
{
|
{
|
||||||
if (lcid >= sched_interface::MAX_LC) {
|
if (lcid >= sched_interface::MAX_LC) {
|
||||||
logger.warning("The provided lcid=%d is not valid", lcid);
|
logger.warning("SCHED: The provided lcid=%d for rnti=0x%x is not valid", lcid, rnti);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lcg_bsr[channels[lcid].cfg.group] += bytes;
|
lcg_bsr[channels[lcid].cfg.group] += bytes;
|
||||||
if (logger.debug.enabled()) {
|
if (logger.debug.enabled()) {
|
||||||
fmt::memory_buffer str_buffer;
|
fmt::memory_buffer str_buffer;
|
||||||
fmt::format_to(str_buffer, "{}", get_bsr_state());
|
fmt::format_to(str_buffer, "{}", get_bsr_state());
|
||||||
logger.debug(
|
logger.debug("SCHED: rnti=0x%x UL buffer update=%d, lcg_id=%d, bsr=%s",
|
||||||
"SCHED: UL buffer update=%d, lcg_id=%d, bsr=%s", bytes, channels[lcid].cfg.group, srsran::to_c_str(str_buffer));
|
rnti,
|
||||||
|
bytes,
|
||||||
|
channels[lcid].cfg.group,
|
||||||
|
srsran::to_c_str(str_buffer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,9 +104,9 @@ int lch_ue_manager::get_max_prio_lcid() const
|
||||||
{
|
{
|
||||||
int min_prio_val = std::numeric_limits<int>::max(), prio_lcid = -1;
|
int min_prio_val = std::numeric_limits<int>::max(), prio_lcid = -1;
|
||||||
|
|
||||||
// Prioritize retxs
|
// Prioritized Txs first (e.g. Retxs, status PDUs)
|
||||||
for (uint32_t lcid = 0; is_lcid_valid(lcid); ++lcid) {
|
for (uint32_t lcid = 0; is_lcid_valid(lcid); ++lcid) {
|
||||||
if (get_dl_retx(lcid) > 0 and channels[lcid].cfg.priority < min_prio_val) {
|
if (get_dl_prio_tx(lcid) > 0 and channels[lcid].cfg.priority < min_prio_val) {
|
||||||
min_prio_val = channels[lcid].cfg.priority;
|
min_prio_val = channels[lcid].cfg.priority;
|
||||||
prio_lcid = lcid;
|
prio_lcid = lcid;
|
||||||
}
|
}
|
||||||
|
@ -156,10 +157,10 @@ int lch_ue_manager::alloc_rlc_pdu(sched_interface::dl_sched_pdu_t* rlc_pdu, int
|
||||||
return alloc_bytes;
|
return alloc_bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
// try first to allocate retxs
|
// try first to allocate high priority txs (e.g. retxs, status pdus)
|
||||||
alloc_bytes = alloc_retx_bytes(lcid, rem_bytes);
|
alloc_bytes = alloc_prio_tx_bytes(lcid, rem_bytes);
|
||||||
|
|
||||||
// if no retx alloc, try newtx
|
// if no prio tx alloc, try newtx
|
||||||
if (alloc_bytes == 0) {
|
if (alloc_bytes == 0) {
|
||||||
alloc_bytes = alloc_tx_bytes(lcid, rem_bytes);
|
alloc_bytes = alloc_tx_bytes(lcid, rem_bytes);
|
||||||
}
|
}
|
||||||
|
@ -177,15 +178,15 @@ int lch_ue_manager::alloc_rlc_pdu(sched_interface::dl_sched_pdu_t* rlc_pdu, int
|
||||||
return alloc_bytes;
|
return alloc_bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lch_ue_manager::alloc_retx_bytes(uint8_t lcid, int rem_bytes)
|
int lch_ue_manager::alloc_prio_tx_bytes(uint8_t lcid, int rem_bytes)
|
||||||
{
|
{
|
||||||
const int rlc_overhead = (lcid == 0) ? 0 : RLC_MAX_HEADER_SIZE_NO_LI;
|
const int rlc_overhead = (lcid == 0) ? 0 : RLC_MAX_HEADER_SIZE_NO_LI;
|
||||||
if (rem_bytes <= rlc_overhead) {
|
if (rem_bytes <= rlc_overhead) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int rem_bytes_no_header = rem_bytes - rlc_overhead;
|
int rem_bytes_no_header = rem_bytes - rlc_overhead;
|
||||||
int alloc = std::min(rem_bytes_no_header, get_dl_retx(lcid));
|
int alloc = std::min(rem_bytes_no_header, get_dl_prio_tx(lcid));
|
||||||
channels[lcid].buf_retx -= alloc;
|
channels[lcid].buf_prio_tx -= alloc;
|
||||||
return alloc + (alloc > 0 ? rlc_overhead : 0);
|
return alloc + (alloc > 0 ? rlc_overhead : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +221,7 @@ bool lch_ue_manager::has_pending_dl_txs() const
|
||||||
|
|
||||||
int lch_ue_manager::get_dl_tx_total_with_overhead(uint32_t lcid) const
|
int lch_ue_manager::get_dl_tx_total_with_overhead(uint32_t lcid) const
|
||||||
{
|
{
|
||||||
return get_dl_retx_with_overhead(lcid) + get_dl_tx_with_overhead(lcid);
|
return get_dl_prio_tx_with_overhead(lcid) + get_dl_tx_with_overhead(lcid);
|
||||||
}
|
}
|
||||||
|
|
||||||
int lch_ue_manager::get_dl_tx_with_overhead(uint32_t lcid) const
|
int lch_ue_manager::get_dl_tx_with_overhead(uint32_t lcid) const
|
||||||
|
@ -228,9 +229,9 @@ int lch_ue_manager::get_dl_tx_with_overhead(uint32_t lcid) const
|
||||||
return get_dl_mac_sdu_size_with_overhead(lcid, get_dl_tx(lcid));
|
return get_dl_mac_sdu_size_with_overhead(lcid, get_dl_tx(lcid));
|
||||||
}
|
}
|
||||||
|
|
||||||
int lch_ue_manager::get_dl_retx_with_overhead(uint32_t lcid) const
|
int lch_ue_manager::get_dl_prio_tx_with_overhead(uint32_t lcid) const
|
||||||
{
|
{
|
||||||
return get_dl_mac_sdu_size_with_overhead(lcid, get_dl_retx(lcid));
|
return get_dl_mac_sdu_size_with_overhead(lcid, get_dl_prio_tx(lcid));
|
||||||
}
|
}
|
||||||
|
|
||||||
int lch_ue_manager::get_bsr_with_overhead(uint32_t lcg) const
|
int lch_ue_manager::get_bsr_with_overhead(uint32_t lcg) const
|
||||||
|
|
|
@ -620,7 +620,7 @@ bool ngap::connect_amf()
|
||||||
logger.info("Connecting to AMF %s:%d", args.amf_addr.c_str(), int(AMF_PORT));
|
logger.info("Connecting to AMF %s:%d", args.amf_addr.c_str(), int(AMF_PORT));
|
||||||
|
|
||||||
// Init SCTP socket and bind it
|
// Init SCTP socket and bind it
|
||||||
if (not sctp_init_client(&amf_socket, socket_type::seqpacket, args.ngc_bind_addr.c_str(), 0)) {
|
if (not sctp_init_socket(&amf_socket, socket_type::seqpacket, args.ngc_bind_addr.c_str(), 0)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
logger.info("SCTP socket opened. fd=%d", amf_socket.fd());
|
logger.info("SCTP socket opened. fd=%d", amf_socket.fd());
|
||||||
|
|
|
@ -166,11 +166,15 @@ rrc_nr_cfg_t rrc_nr::update_default_cfg(const rrc_nr_cfg_t& current)
|
||||||
return cfg_default;
|
return cfg_default;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function is called from PRACH worker (can wait)
|
/* @brief PRIVATE function, gets called by sgnb_addition_request
|
||||||
int rrc_nr::add_user(uint16_t rnti, const sched_nr_ue_cfg_t& uecfg)
|
*
|
||||||
|
* This function WILL NOT TRIGGER the RX MSG3 activity timer
|
||||||
|
*/
|
||||||
|
int rrc_nr::add_user(uint16_t rnti, const sched_nr_ue_cfg_t& uecfg, bool start_msg3_timer)
|
||||||
{
|
{
|
||||||
if (users.count(rnti) == 0) {
|
if (users.count(rnti) == 0) {
|
||||||
users.insert(std::make_pair(rnti, std::unique_ptr<ue>(new ue(this, rnti, uecfg))));
|
// If in the ue ctor, "start_msg3_timer" is set to true, this will start the MSG3 RX TIMEOUT at ue creation
|
||||||
|
users.insert(std::make_pair(rnti, std::unique_ptr<ue>(new ue(this, rnti, uecfg, start_msg3_timer))));
|
||||||
rlc->add_user(rnti);
|
rlc->add_user(rnti);
|
||||||
pdcp->add_user(rnti);
|
pdcp->add_user(rnti);
|
||||||
logger.info("Added new user rnti=0x%x", rnti);
|
logger.info("Added new user rnti=0x%x", rnti);
|
||||||
|
@ -181,6 +185,16 @@ int rrc_nr::add_user(uint16_t rnti, const sched_nr_ue_cfg_t& uecfg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* @brief PUBLIC function, gets called by mac_nr::rach_detected
|
||||||
|
*
|
||||||
|
* This function is called from PRACH worker (can wait) and WILL TRIGGER the RX MSG3 activity timer
|
||||||
|
*/
|
||||||
|
int rrc_nr::add_user(uint16_t rnti, const sched_nr_ue_cfg_t& uecfg)
|
||||||
|
{
|
||||||
|
// Set "triggered_by_rach" to true to start the MSG3 RX TIMEOUT
|
||||||
|
return add_user(rnti, uecfg, true);
|
||||||
|
}
|
||||||
|
|
||||||
void rrc_nr::rem_user(uint16_t rnti)
|
void rrc_nr::rem_user(uint16_t rnti)
|
||||||
{
|
{
|
||||||
auto user_it = users.find(rnti);
|
auto user_it = users.find(rnti);
|
||||||
|
@ -516,7 +530,7 @@ void rrc_nr::sgnb_addition_request(uint16_t eutra_rnti, const sgnb_addition_req_
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (add_user(nr_rnti, uecfg) != SRSRAN_SUCCESS) {
|
if (add_user(nr_rnti, uecfg, false) != SRSRAN_SUCCESS) {
|
||||||
logger.error("Failed to allocate RNTI at RRC");
|
logger.error("Failed to allocate RNTI at RRC");
|
||||||
rrc_eutra->sgnb_addition_reject(eutra_rnti);
|
rrc_eutra->sgnb_addition_reject(eutra_rnti);
|
||||||
return;
|
return;
|
||||||
|
@ -554,11 +568,82 @@ void rrc_nr::sgnb_release_request(uint16_t nr_rnti)
|
||||||
Every function in UE class is called from a mutex environment thus does not
|
Every function in UE class is called from a mutex environment thus does not
|
||||||
need extra protection.
|
need extra protection.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
rrc_nr::ue::ue(rrc_nr* parent_, uint16_t rnti_, const sched_nr_ue_cfg_t& uecfg_) :
|
rrc_nr::ue::ue(rrc_nr* parent_, uint16_t rnti_, const sched_nr_ue_cfg_t& uecfg_, bool start_msg3_timer) :
|
||||||
parent(parent_), rnti(rnti_), uecfg(uecfg_)
|
parent(parent_), rnti(rnti_), uecfg(uecfg_)
|
||||||
{
|
{
|
||||||
// Derive UE cfg from rrc_cfg_nr_t
|
// Derive UE cfg from rrc_cfg_nr_t
|
||||||
uecfg.phy_cfg.pdcch = parent->cfg.cell_list[0].phy_cell.pdcch;
|
uecfg.phy_cfg.pdcch = parent->cfg.cell_list[0].phy_cell.pdcch;
|
||||||
|
|
||||||
|
// Set timer for MSG3_RX_TIMEOUT or UE_INACTIVITY_TIMEOUT
|
||||||
|
activity_timer = parent->task_sched.get_unique_timer();
|
||||||
|
start_msg3_timer ? set_activity_timeout(MSG3_RX_TIMEOUT) : set_activity_timeout(UE_INACTIVITY_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rrc_nr::ue::set_activity_timeout(activity_timeout_type_t type)
|
||||||
|
{
|
||||||
|
uint32_t deadline_ms = 0;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case MSG3_RX_TIMEOUT:
|
||||||
|
// TODO: Retrieve the parameters from somewhere(RRC?) - Currently hardcoded to 100ms
|
||||||
|
deadline_ms = 100;
|
||||||
|
break;
|
||||||
|
case UE_INACTIVITY_TIMEOUT:
|
||||||
|
// TODO: Add a value for the inactivity timeout - currently no activity set this case
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
parent->logger.error("Unknown timeout type %d", type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Currently we only set the timer for the MSG3_RX_TIMEOUT case
|
||||||
|
activity_timer.set(deadline_ms, [this, type](uint32_t tid) { activity_timer_expired(type); });
|
||||||
|
parent->logger.debug("Setting timer for %s for rnti=0x%x to %dms", to_string(type).c_str(), rnti, deadline_ms);
|
||||||
|
|
||||||
|
set_activity();
|
||||||
|
}
|
||||||
|
|
||||||
|
void rrc_nr::ue::set_activity(bool enabled)
|
||||||
|
{
|
||||||
|
if (not enabled) {
|
||||||
|
if (activity_timer.is_running()) {
|
||||||
|
parent->logger.debug("Inactivity timer interrupted for rnti=0x%x", rnti);
|
||||||
|
}
|
||||||
|
activity_timer.stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// re-start activity timer with current timeout value
|
||||||
|
activity_timer.run();
|
||||||
|
parent->logger.debug("Activity registered for rnti=0x%x (timeout_value=%dms)", rnti, activity_timer.duration());
|
||||||
|
}
|
||||||
|
|
||||||
|
void rrc_nr::ue::activity_timer_expired(const activity_timeout_type_t type)
|
||||||
|
{
|
||||||
|
parent->logger.info("Activity timer for rnti=0x%x expired after %d ms", rnti, activity_timer.time_elapsed());
|
||||||
|
|
||||||
|
state = rrc_nr_state_t::RRC_IDLE;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case UE_INACTIVITY_TIMEOUT:
|
||||||
|
// TODO: Add action to be executed
|
||||||
|
break;
|
||||||
|
case MSG3_RX_TIMEOUT:
|
||||||
|
// MSG3 timeout, no need to notify NGAP or LTE stack. Just remove UE
|
||||||
|
parent->rem_user(rnti);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Unhandled activity timeout, just remove UE and log an error
|
||||||
|
parent->rem_user(rnti);
|
||||||
|
parent->logger.error(
|
||||||
|
"Unhandled reason for activity timer expiration. rnti=0x%x, cause %d", rnti, static_cast<unsigned>(type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string rrc_nr::ue::to_string(const activity_timeout_type_t& type)
|
||||||
|
{
|
||||||
|
constexpr static const char* options[] = {"Msg3 reception", "UE inactivity", "UE reestablishment"};
|
||||||
|
return srsran::enum_to_text(options, (uint32_t)activity_timeout_type_t::nulltype, (uint32_t)type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rrc_nr::ue::send_connection_setup()
|
void rrc_nr::ue::send_connection_setup()
|
||||||
|
@ -1312,6 +1397,10 @@ void rrc_nr::ue::crnti_ce_received()
|
||||||
// send SgNB addition complete for ENDC users
|
// send SgNB addition complete for ENDC users
|
||||||
parent->rrc_eutra->sgnb_addition_complete(eutra_rnti, rnti);
|
parent->rrc_eutra->sgnb_addition_complete(eutra_rnti, rnti);
|
||||||
|
|
||||||
|
// stop RX MSG3 activity timer on MAC CE RNTI reception
|
||||||
|
activity_timer.stop();
|
||||||
|
parent->logger.debug("Received MAC CE-RNTI for 0x%x - stopping MSG3 timer", rnti);
|
||||||
|
|
||||||
// Add DRB1 to MAC
|
// Add DRB1 to MAC
|
||||||
for (auto& drb : cell_group_cfg.rlc_bearer_to_add_mod_list) {
|
for (auto& drb : cell_group_cfg.rlc_bearer_to_add_mod_list) {
|
||||||
uecfg.ue_bearers[drb.lc_ch_id].direction = mac_lc_ch_cfg_t::BOTH;
|
uecfg.ue_bearers[drb.lc_ch_id].direction = mac_lc_ch_cfg_t::BOTH;
|
||||||
|
|
|
@ -93,7 +93,7 @@ std::tuple<bool, meas_obj_t*, cells_to_add_mod_s*> add_cell_enb_cfg(meas_obj_lis
|
||||||
bool inserted_flag = true;
|
bool inserted_flag = true;
|
||||||
|
|
||||||
cells_to_add_mod_s new_cell;
|
cells_to_add_mod_s new_cell;
|
||||||
asn1::number_to_enum(new_cell.cell_individual_offset, (uint8_t)cellcfg.q_offset);
|
new_cell.cell_individual_offset = cellcfg.cell_individual_offset;
|
||||||
new_cell.pci = cellcfg.pci;
|
new_cell.pci = cellcfg.pci;
|
||||||
|
|
||||||
std::pair<meas_obj_t*, meas_cell_t*> ret = find_cell(meas_obj_list, cellcfg.earfcn, cellcfg.pci);
|
std::pair<meas_obj_t*, meas_cell_t*> ret = find_cell(meas_obj_list, cellcfg.earfcn, cellcfg.pci);
|
||||||
|
|
|
@ -488,7 +488,8 @@ bool s1ap::connect_mme()
|
||||||
logger.info("Connecting to MME %s:%d", args.mme_addr.c_str(), int(MME_PORT));
|
logger.info("Connecting to MME %s:%d", args.mme_addr.c_str(), int(MME_PORT));
|
||||||
|
|
||||||
// Init SCTP socket and bind it
|
// Init SCTP socket and bind it
|
||||||
if (not sctp_init_client(&mme_socket, socket_type::seqpacket, args.s1c_bind_addr.c_str(), args.s1c_bind_port)) {
|
if (not srsran::net_utils::sctp_init_socket(
|
||||||
|
&mme_socket, socket_type::seqpacket, args.s1c_bind_addr.c_str(), args.s1c_bind_port)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
logger.info("SCTP socket opened. fd=%d", mme_socket.fd());
|
logger.info("SCTP socket opened. fd=%d", mme_socket.fd());
|
||||||
|
|
|
@ -59,10 +59,8 @@ const gtpu_tunnel_manager::tunnel* gtpu_tunnel_manager::find_tunnel(uint32_t tei
|
||||||
|
|
||||||
gtpu_tunnel_manager::ue_bearer_tunnel_list* gtpu_tunnel_manager::find_rnti_tunnels(uint16_t rnti)
|
gtpu_tunnel_manager::ue_bearer_tunnel_list* gtpu_tunnel_manager::find_rnti_tunnels(uint16_t rnti)
|
||||||
{
|
{
|
||||||
if (not ue_teidin_db.contains(rnti)) {
|
auto it = ue_teidin_db.find(rnti);
|
||||||
return nullptr;
|
return it != ue_teidin_db.end() ? &ue_teidin_db[rnti] : nullptr;
|
||||||
}
|
|
||||||
return &ue_teidin_db[rnti];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
srsran::span<gtpu_tunnel_manager::bearer_teid_pair>
|
srsran::span<gtpu_tunnel_manager::bearer_teid_pair>
|
||||||
|
@ -101,9 +99,9 @@ gtpu_tunnel_manager::add_tunnel(uint16_t rnti, uint32_t eps_bearer_id, uint32_t
|
||||||
tun->teid_out = teidout;
|
tun->teid_out = teidout;
|
||||||
tun->spgw_addr = spgw_addr;
|
tun->spgw_addr = spgw_addr;
|
||||||
|
|
||||||
if (not ue_teidin_db.contains(rnti)) {
|
if (ue_teidin_db.find(rnti) == ue_teidin_db.end()) {
|
||||||
auto ret = ue_teidin_db.insert(rnti, ue_bearer_tunnel_list());
|
auto ret = ue_teidin_db.emplace(rnti, ue_bearer_tunnel_list());
|
||||||
if (ret.is_error()) {
|
if (!ret.second) {
|
||||||
logger.error("Failed to allocate rnti=0x%x", rnti);
|
logger.error("Failed to allocate rnti=0x%x", rnti);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -142,7 +140,7 @@ bool gtpu_tunnel_manager::update_rnti(uint16_t old_rnti, uint16_t new_rnti)
|
||||||
logger.info("Modifying bearer rnti. Old rnti: 0x%x, new rnti: 0x%x", old_rnti, new_rnti);
|
logger.info("Modifying bearer rnti. Old rnti: 0x%x, new rnti: 0x%x", old_rnti, new_rnti);
|
||||||
|
|
||||||
// create new RNTI and update TEIDs of old rnti to reflect new rnti
|
// create new RNTI and update TEIDs of old rnti to reflect new rnti
|
||||||
if (new_rnti_ptr == nullptr and not ue_teidin_db.insert(new_rnti, ue_bearer_tunnel_list())) {
|
if (new_rnti_ptr == nullptr and not ue_teidin_db.insert({new_rnti, ue_bearer_tunnel_list()}).second) {
|
||||||
logger.error("Failure to create new rnti=0x%x", new_rnti);
|
logger.error("Failure to create new rnti=0x%x", new_rnti);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -195,7 +193,8 @@ bool gtpu_tunnel_manager::remove_tunnel(uint32_t teidin)
|
||||||
|
|
||||||
bool gtpu_tunnel_manager::remove_rnti(uint16_t rnti)
|
bool gtpu_tunnel_manager::remove_rnti(uint16_t rnti)
|
||||||
{
|
{
|
||||||
if (not ue_teidin_db.contains(rnti)) {
|
auto it = ue_teidin_db.find(rnti);
|
||||||
|
if (it == ue_teidin_db.end()) {
|
||||||
logger.warning("Removing rnti. rnti=0x%x not found.", rnti);
|
logger.warning("Removing rnti. rnti=0x%x not found.", rnti);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -226,6 +226,11 @@ bool pdcp::user_interface_rlc::rb_is_um(uint32_t lcid)
|
||||||
return rlc->rb_is_um(rnti, lcid);
|
return rlc->rb_is_um(rnti, lcid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool pdcp::user_interface_rlc::is_suspended(uint32_t lcid)
|
||||||
|
{
|
||||||
|
return rlc->is_suspended(rnti, lcid);
|
||||||
|
}
|
||||||
|
|
||||||
bool pdcp::user_interface_rlc::sdu_queue_is_full(uint32_t lcid)
|
bool pdcp::user_interface_rlc::sdu_queue_is_full(uint32_t lcid)
|
||||||
{
|
{
|
||||||
return rlc->sdu_queue_is_full(rnti, lcid);
|
return rlc->sdu_queue_is_full(rnti, lcid);
|
||||||
|
|
|
@ -159,6 +159,17 @@ bool rlc::suspend_bearer(uint16_t rnti, uint32_t lcid)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool rlc::is_suspended(uint16_t rnti, uint32_t lcid)
|
||||||
|
{
|
||||||
|
pthread_rwlock_rdlock(&rwlock);
|
||||||
|
bool result = false;
|
||||||
|
if (users.count(rnti)) {
|
||||||
|
result = users[rnti].rlc->is_suspended(lcid);
|
||||||
|
}
|
||||||
|
pthread_rwlock_unlock(&rwlock);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bool rlc::resume_bearer(uint16_t rnti, uint32_t lcid)
|
bool rlc::resume_bearer(uint16_t rnti, uint32_t lcid)
|
||||||
{
|
{
|
||||||
pthread_rwlock_rdlock(&rwlock);
|
pthread_rwlock_rdlock(&rwlock);
|
||||||
|
@ -182,10 +193,10 @@ void rlc::reestablish(uint16_t rnti)
|
||||||
|
|
||||||
// In the eNodeB, there is no polling for buffer state from the scheduler.
|
// In the eNodeB, there is no polling for buffer state from the scheduler.
|
||||||
// This function is called by UE RLC instance every time the tx/retx buffers are updated
|
// This function is called by UE RLC instance every time the tx/retx buffers are updated
|
||||||
void rlc::update_bsr(uint32_t rnti, uint32_t lcid, uint32_t tx_queue, uint32_t retx_queue)
|
void rlc::update_bsr(uint32_t rnti, uint32_t lcid, uint32_t tx_queue, uint32_t prio_tx_queue)
|
||||||
{
|
{
|
||||||
logger.debug("Buffer state: rnti=0x%x, lcid=%d, tx_queue=%d", rnti, lcid, tx_queue);
|
logger.debug("Buffer state: rnti=0x%x, lcid=%d, tx_queue=%d, prio_tx_queue=%d", rnti, lcid, tx_queue, prio_tx_queue);
|
||||||
mac->rlc_buffer_state(rnti, lcid, tx_queue, retx_queue);
|
mac->rlc_buffer_state(rnti, lcid, tx_queue, prio_tx_queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
int rlc::read_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes)
|
int rlc::read_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes)
|
||||||
|
|
|
@ -39,6 +39,7 @@ public:
|
||||||
void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu) override { last_sdu = std::move(sdu); }
|
void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu) override { last_sdu = std::move(sdu); }
|
||||||
bool has_bearer(uint16_t rnti, uint32_t lcid) override { return false; }
|
bool has_bearer(uint16_t rnti, uint32_t lcid) override { return false; }
|
||||||
bool suspend_bearer(uint16_t rnti, uint32_t lcid) override { return true; }
|
bool suspend_bearer(uint16_t rnti, uint32_t lcid) override { return true; }
|
||||||
|
bool is_suspended(uint16_t rnti, uint32_t lcid) override { return false; }
|
||||||
bool resume_bearer(uint16_t rnti, uint32_t lcid) override { return true; }
|
bool resume_bearer(uint16_t rnti, uint32_t lcid) override { return true; }
|
||||||
void reestablish(uint16_t rnti) override {}
|
void reestablish(uint16_t rnti) override {}
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,7 @@ void test_single_prach()
|
||||||
auto run_slot = [&alloc, &rasched, &pdcch_slot, &slot_ues, &u]() -> const bwp_slot_grid* {
|
auto run_slot = [&alloc, &rasched, &pdcch_slot, &slot_ues, &u]() -> const bwp_slot_grid* {
|
||||||
mac_logger.set_context(pdcch_slot.to_uint());
|
mac_logger.set_context(pdcch_slot.to_uint());
|
||||||
u.new_slot(pdcch_slot);
|
u.new_slot(pdcch_slot);
|
||||||
|
u.carriers[0]->new_slot(pdcch_slot);
|
||||||
slot_ues.clear();
|
slot_ues.clear();
|
||||||
slot_ue sfu = u.try_reserve(pdcch_slot, 0);
|
slot_ue sfu = u.try_reserve(pdcch_slot, 0);
|
||||||
if (not sfu.empty()) {
|
if (not sfu.empty()) {
|
||||||
|
|
|
@ -51,8 +51,8 @@ int sched_nr_ue_sim::update(const sched_nr_cc_result_view& cc_out)
|
||||||
{
|
{
|
||||||
update_dl_harqs(cc_out);
|
update_dl_harqs(cc_out);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < cc_out.dl_cc_result->dl_sched.pdcch_dl.size(); ++i) {
|
for (uint32_t i = 0; i < cc_out.dl_cc_result.dl_sched.pdcch_dl.size(); ++i) {
|
||||||
const auto& data = cc_out.dl_cc_result->dl_sched.pdcch_dl[i];
|
const auto& data = cc_out.dl_cc_result.dl_sched.pdcch_dl[i];
|
||||||
if (data.dci.ctx.rnti != ctxt.rnti) {
|
if (data.dci.ctx.rnti != ctxt.rnti) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -73,8 +73,8 @@ int sched_nr_ue_sim::update(const sched_nr_cc_result_view& cc_out)
|
||||||
void sched_nr_ue_sim::update_dl_harqs(const sched_nr_cc_result_view& cc_out)
|
void sched_nr_ue_sim::update_dl_harqs(const sched_nr_cc_result_view& cc_out)
|
||||||
{
|
{
|
||||||
uint32_t cc = cc_out.cc;
|
uint32_t cc = cc_out.cc;
|
||||||
for (uint32_t i = 0; i < cc_out.dl_cc_result->dl_sched.pdcch_dl.size(); ++i) {
|
for (uint32_t i = 0; i < cc_out.dl_cc_result.dl_sched.pdcch_dl.size(); ++i) {
|
||||||
const auto& data = cc_out.dl_cc_result->dl_sched.pdcch_dl[i];
|
const auto& data = cc_out.dl_cc_result.dl_sched.pdcch_dl[i];
|
||||||
if (data.dci.ctx.rnti != ctxt.rnti) {
|
if (data.dci.ctx.rnti != ctxt.rnti) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -216,7 +216,9 @@ void sched_nr_base_tester::run_slot(slot_point slot_tx)
|
||||||
void sched_nr_base_tester::generate_cc_result(uint32_t cc)
|
void sched_nr_base_tester::generate_cc_result(uint32_t cc)
|
||||||
{
|
{
|
||||||
// Run scheduler
|
// Run scheduler
|
||||||
sched_ptr->run_slot(current_slot_tx, cc, cc_results[cc].dl_res);
|
sched_nr_interface::dl_res_t dl_sched(cc_results[cc].rar, cc_results[cc].dl_res);
|
||||||
|
sched_ptr->run_slot(current_slot_tx, cc, dl_sched);
|
||||||
|
cc_results[cc].rar = dl_sched.rar;
|
||||||
sched_ptr->get_ul_sched(current_slot_tx, cc, cc_results[cc].ul_res);
|
sched_ptr->get_ul_sched(current_slot_tx, cc, cc_results[cc].ul_res);
|
||||||
auto tp2 = std::chrono::steady_clock::now();
|
auto tp2 = std::chrono::steady_clock::now();
|
||||||
cc_results[cc].cc_latency_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(tp2 - slot_start_tp);
|
cc_results[cc].cc_latency_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(tp2 - slot_start_tp);
|
||||||
|
@ -238,17 +240,14 @@ void sched_nr_base_tester::process_results()
|
||||||
// Derived class-defined tests
|
// Derived class-defined tests
|
||||||
process_slot_result(slot_ctxt, cc_results);
|
process_slot_result(slot_ctxt, cc_results);
|
||||||
|
|
||||||
sched_nr_cc_result_view cc_out;
|
|
||||||
cc_out.slot = current_slot_tx;
|
|
||||||
for (uint32_t cc = 0; cc < cell_params.size(); ++cc) {
|
for (uint32_t cc = 0; cc < cell_params.size(); ++cc) {
|
||||||
cc_out.cc = cc;
|
sched_nr_cc_result_view cc_out{
|
||||||
cc_out.dl_cc_result = &cc_results[cc].dl_res;
|
current_slot_tx, cc, cc_results[cc].rar, cc_results[cc].dl_res, cc_results[cc].ul_res};
|
||||||
cc_out.ul_cc_result = &cc_results[cc].ul_res;
|
|
||||||
|
|
||||||
// Run common tests
|
// Run common tests
|
||||||
test_dl_pdcch_consistency(cc_out.dl_cc_result->dl_sched.pdcch_dl);
|
test_dl_pdcch_consistency(cc_out.dl_cc_result.dl_sched.pdcch_dl);
|
||||||
test_pdsch_consistency(cc_out.dl_cc_result->dl_sched.pdsch);
|
test_pdsch_consistency(cc_out.dl_cc_result.dl_sched.pdsch);
|
||||||
test_ssb_scheduled_grant(cc_out.slot, cell_params[cc_out.cc].cfg, cc_out.dl_cc_result->dl_sched.ssb);
|
test_ssb_scheduled_grant(cc_out.slot, cell_params[cc_out.cc].cfg, cc_out.dl_cc_result.dl_sched.ssb);
|
||||||
|
|
||||||
// Run UE-dedicated tests
|
// Run UE-dedicated tests
|
||||||
test_dl_sched_result(slot_ctxt, cc_out);
|
test_dl_sched_result(slot_ctxt, cc_out);
|
||||||
|
|
|
@ -50,8 +50,16 @@ struct ue_nr_harq_ctxt_t {
|
||||||
struct sched_nr_cc_result_view {
|
struct sched_nr_cc_result_view {
|
||||||
slot_point slot;
|
slot_point slot;
|
||||||
uint32_t cc;
|
uint32_t cc;
|
||||||
const sched_nr_interface::dl_sched_res_t* dl_cc_result;
|
const sched_nr_interface::dl_res_t dl_cc_result;
|
||||||
const sched_nr_interface::ul_sched_t* ul_cc_result;
|
const sched_nr_interface::ul_res_t* ul_cc_result;
|
||||||
|
|
||||||
|
sched_nr_cc_result_view(slot_point slot_,
|
||||||
|
uint32_t cc_,
|
||||||
|
sched_nr_interface::sched_rar_list_t& rar,
|
||||||
|
sched_nr_interface::dl_sched_t& dl_res,
|
||||||
|
sched_nr_interface::ul_res_t& ul_res) :
|
||||||
|
slot(slot_), cc(cc_), dl_cc_result(rar, dl_res), ul_cc_result(&ul_res)
|
||||||
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ue_nr_cc_ctxt_t {
|
struct ue_nr_cc_ctxt_t {
|
||||||
|
@ -119,8 +127,9 @@ public:
|
||||||
struct cc_result_t {
|
struct cc_result_t {
|
||||||
slot_point slot_tx;
|
slot_point slot_tx;
|
||||||
uint32_t cc;
|
uint32_t cc;
|
||||||
sched_nr_interface::dl_sched_res_t dl_res;
|
sched_nr_interface::dl_sched_t dl_res;
|
||||||
sched_nr_interface::ul_sched_t ul_res;
|
sched_nr_interface::sched_rar_list_t rar;
|
||||||
|
sched_nr_interface::ul_res_t ul_res;
|
||||||
std::chrono::nanoseconds cc_latency_ns;
|
std::chrono::nanoseconds cc_latency_ns;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -45,12 +45,17 @@ public:
|
||||||
})->cc_latency_ns.count();
|
})->cc_latency_ns.count();
|
||||||
|
|
||||||
for (auto& cc_out : cc_list) {
|
for (auto& cc_out : cc_list) {
|
||||||
pdsch_count += cc_out.dl_res.dl_sched.pdcch_dl.size();
|
pdsch_count += cc_out.dl_res.pdcch_dl.size();
|
||||||
cc_res_count++;
|
cc_res_count++;
|
||||||
|
|
||||||
TESTASSERT(cc_out.dl_res.dl_sched.pdcch_dl.size() <= 1);
|
bool is_dl_slot = srsran_duplex_nr_is_dl(&cell_params[cc_out.cc].cfg.duplex, 0, current_slot_tx.slot_idx());
|
||||||
if (srsran_duplex_nr_is_dl(&cell_params[cc_out.cc].cfg.duplex, 0, current_slot_tx.slot_idx())) {
|
|
||||||
TESTASSERT(cc_out.dl_res.dl_sched.pdcch_dl.size() == 1 or not cc_out.dl_res.dl_sched.ssb.empty());
|
if (is_dl_slot) {
|
||||||
|
if (cc_out.dl_res.ssb.empty()) {
|
||||||
|
TESTASSERT(slot_ctxt.ue_db.empty() or cc_out.dl_res.pdcch_dl.size() == 1);
|
||||||
|
} else {
|
||||||
|
TESTASSERT(cc_out.dl_res.pdcch_dl.size() == 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,12 +90,13 @@ void run_sched_nr_test(uint32_t nof_workers)
|
||||||
}
|
}
|
||||||
sched_nr_tester tester(cfg, cells_cfg, test_name, nof_workers);
|
sched_nr_tester tester(cfg, cells_cfg, test_name, nof_workers);
|
||||||
|
|
||||||
sched_nr_interface::ue_cfg_t uecfg = get_default_ue_cfg(nof_sectors);
|
|
||||||
tester.add_user(rnti, uecfg, slot_point{0, 0}, 0);
|
|
||||||
|
|
||||||
for (uint32_t nof_slots = 0; nof_slots < max_nof_ttis; ++nof_slots) {
|
for (uint32_t nof_slots = 0; nof_slots < max_nof_ttis; ++nof_slots) {
|
||||||
slot_point slot_rx(0, nof_slots % 10240);
|
slot_point slot_rx(0, nof_slots % 10240);
|
||||||
slot_point slot_tx = slot_rx + TX_ENB_DELAY;
|
slot_point slot_tx = slot_rx + TX_ENB_DELAY;
|
||||||
|
if (slot_rx.to_uint() == 9) {
|
||||||
|
sched_nr_interface::ue_cfg_t uecfg = get_default_ue_cfg(nof_sectors);
|
||||||
|
tester.add_user(rnti, uecfg, slot_rx, 0);
|
||||||
|
}
|
||||||
tester.run_slot(slot_tx);
|
tester.run_slot(slot_tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ using namespace srsenb::sched_nr_impl;
|
||||||
void test_dl_sched_result(const sim_nr_enb_ctxt_t& enb_ctxt, const sched_nr_cc_result_view& cc_out)
|
void test_dl_sched_result(const sim_nr_enb_ctxt_t& enb_ctxt, const sched_nr_cc_result_view& cc_out)
|
||||||
{
|
{
|
||||||
slot_point pdcch_slot = cc_out.slot;
|
slot_point pdcch_slot = cc_out.slot;
|
||||||
const pdcch_dl_list_t& pdcchs = cc_out.dl_cc_result->dl_sched.pdcch_dl;
|
const pdcch_dl_list_t& pdcchs = cc_out.dl_cc_result.dl_sched.pdcch_dl;
|
||||||
|
|
||||||
// Iterate over UE PDCCH allocations
|
// Iterate over UE PDCCH allocations
|
||||||
for (const pdcch_dl_t& pdcch : pdcchs) {
|
for (const pdcch_dl_t& pdcch : pdcchs) {
|
||||||
|
|
|
@ -53,7 +53,7 @@ int test_pdu_alloc_successful(srsenb::lch_ue_manager& lch_handler,
|
||||||
|
|
||||||
int test_retx_until_empty(srsenb::lch_ue_manager& lch_handler, int lcid, uint32_t rlc_payload_size)
|
int test_retx_until_empty(srsenb::lch_ue_manager& lch_handler, int lcid, uint32_t rlc_payload_size)
|
||||||
{
|
{
|
||||||
int start_rlc_bytes = lch_handler.get_dl_retx(lcid);
|
int start_rlc_bytes = lch_handler.get_dl_prio_tx(lcid);
|
||||||
int nof_pdus = ceil(static_cast<float>(start_rlc_bytes) / static_cast<float>(rlc_payload_size));
|
int nof_pdus = ceil(static_cast<float>(start_rlc_bytes) / static_cast<float>(rlc_payload_size));
|
||||||
int rem_rlc_bytes = start_rlc_bytes;
|
int rem_rlc_bytes = start_rlc_bytes;
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ int test_retx_until_empty(srsenb::lch_ue_manager& lch_handler, int lcid, uint32_
|
||||||
uint32_t expected_payload_size = std::min(rlc_payload_size, (uint32_t)rem_rlc_bytes);
|
uint32_t expected_payload_size = std::min(rlc_payload_size, (uint32_t)rem_rlc_bytes);
|
||||||
TESTASSERT(test_pdu_alloc_successful(lch_handler, pdu, lcid, expected_payload_size) == SRSRAN_SUCCESS);
|
TESTASSERT(test_pdu_alloc_successful(lch_handler, pdu, lcid, expected_payload_size) == SRSRAN_SUCCESS);
|
||||||
rem_rlc_bytes -= expected_payload_size;
|
rem_rlc_bytes -= expected_payload_size;
|
||||||
TESTASSERT(lch_handler.get_dl_retx(lcid) == rem_rlc_bytes);
|
TESTASSERT(lch_handler.get_dl_prio_tx(lcid) == rem_rlc_bytes);
|
||||||
}
|
}
|
||||||
return start_rlc_bytes;
|
return start_rlc_bytes;
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ int test_newtx_until_empty(srsenb::lch_ue_manager& lch_handler, int lcid, uint32
|
||||||
|
|
||||||
int test_lc_ch_pbr_infinity()
|
int test_lc_ch_pbr_infinity()
|
||||||
{
|
{
|
||||||
srsenb::lch_ue_manager lch_handler;
|
srsenb::lch_ue_manager lch_handler{0x46};
|
||||||
|
|
||||||
srsenb::sched_interface::ue_cfg_t ue_cfg = generate_default_ue_cfg();
|
srsenb::sched_interface::ue_cfg_t ue_cfg = generate_default_ue_cfg();
|
||||||
ue_cfg = generate_setup_ue_cfg(ue_cfg);
|
ue_cfg = generate_setup_ue_cfg(ue_cfg);
|
||||||
|
@ -106,15 +106,15 @@ int test_lc_ch_pbr_infinity()
|
||||||
lch_handler.dl_buffer_state(drb_to_lcid(lte_drb::drb2), 5000, 10000);
|
lch_handler.dl_buffer_state(drb_to_lcid(lte_drb::drb2), 5000, 10000);
|
||||||
|
|
||||||
// TEST1 - retx of SRB1 is prioritized. Do not transmit other bearers until there are no SRB1 retxs
|
// TEST1 - retx of SRB1 is prioritized. Do not transmit other bearers until there are no SRB1 retxs
|
||||||
int nof_pending_bytes = lch_handler.get_dl_retx(srb_to_lcid(lte_srb::srb1));
|
int nof_pending_bytes = lch_handler.get_dl_prio_tx(srb_to_lcid(lte_srb::srb1));
|
||||||
TESTASSERT(test_retx_until_empty(lch_handler, srb_to_lcid(lte_srb::srb1), 500) == nof_pending_bytes);
|
TESTASSERT(test_retx_until_empty(lch_handler, srb_to_lcid(lte_srb::srb1), 500) == nof_pending_bytes);
|
||||||
|
|
||||||
// TEST2 - the DRB2 has lower prio level than SRB1, but has retxs
|
// TEST2 - the DRB2 has lower prio level than SRB1, but has retxs
|
||||||
nof_pending_bytes = lch_handler.get_dl_retx(drb_to_lcid(lte_drb::drb2));
|
nof_pending_bytes = lch_handler.get_dl_prio_tx(drb_to_lcid(lte_drb::drb2));
|
||||||
TESTASSERT(test_retx_until_empty(lch_handler, drb_to_lcid(lte_drb::drb2), 500) == nof_pending_bytes);
|
TESTASSERT(test_retx_until_empty(lch_handler, drb_to_lcid(lte_drb::drb2), 500) == nof_pending_bytes);
|
||||||
|
|
||||||
// TEST3 - the DRB1 has lower prio level, but has retxs
|
// TEST3 - the DRB1 has lower prio level, but has retxs
|
||||||
nof_pending_bytes = lch_handler.get_dl_retx(drb_to_lcid(lte_drb::drb1));
|
nof_pending_bytes = lch_handler.get_dl_prio_tx(drb_to_lcid(lte_drb::drb1));
|
||||||
TESTASSERT(test_retx_until_empty(lch_handler, drb_to_lcid(lte_drb::drb1), 500) == nof_pending_bytes);
|
TESTASSERT(test_retx_until_empty(lch_handler, drb_to_lcid(lte_drb::drb1), 500) == nof_pending_bytes);
|
||||||
|
|
||||||
// TEST4 - The SRB1 newtx buffer is emptied before other bearers newtxs
|
// TEST4 - The SRB1 newtx buffer is emptied before other bearers newtxs
|
||||||
|
@ -134,7 +134,7 @@ int test_lc_ch_pbr_infinity()
|
||||||
|
|
||||||
int test_lc_ch_pbr_finite()
|
int test_lc_ch_pbr_finite()
|
||||||
{
|
{
|
||||||
srsenb::lch_ue_manager lch_handler;
|
srsenb::lch_ue_manager lch_handler{0x46};
|
||||||
sched_interface::dl_sched_pdu_t pdu;
|
sched_interface::dl_sched_pdu_t pdu;
|
||||||
|
|
||||||
srsenb::sched_interface::ue_cfg_t ue_cfg = generate_default_ue_cfg();
|
srsenb::sched_interface::ue_cfg_t ue_cfg = generate_default_ue_cfg();
|
||||||
|
@ -163,11 +163,11 @@ int test_lc_ch_pbr_finite()
|
||||||
lch_handler.dl_buffer_state(drb_to_lcid(lte_drb::drb2), 50000, 0);
|
lch_handler.dl_buffer_state(drb_to_lcid(lte_drb::drb2), 50000, 0);
|
||||||
|
|
||||||
// TEST1 - SRB1 retxs are emptied first
|
// TEST1 - SRB1 retxs are emptied first
|
||||||
int nof_pending_bytes = lch_handler.get_dl_retx(srb_to_lcid(lte_srb::srb1));
|
int nof_pending_bytes = lch_handler.get_dl_prio_tx(srb_to_lcid(lte_srb::srb1));
|
||||||
TESTASSERT(test_retx_until_empty(lch_handler, srb_to_lcid(lte_srb::srb1), 500) == nof_pending_bytes);
|
TESTASSERT(test_retx_until_empty(lch_handler, srb_to_lcid(lte_srb::srb1), 500) == nof_pending_bytes);
|
||||||
|
|
||||||
// TEST2 - DRB1 retxs are emptied
|
// TEST2 - DRB1 retxs are emptied
|
||||||
nof_pending_bytes = lch_handler.get_dl_retx(drb_to_lcid(lte_drb::drb1));
|
nof_pending_bytes = lch_handler.get_dl_prio_tx(drb_to_lcid(lte_drb::drb1));
|
||||||
TESTASSERT(test_retx_until_empty(lch_handler, drb_to_lcid(lte_drb::drb1), 500) == nof_pending_bytes);
|
TESTASSERT(test_retx_until_empty(lch_handler, drb_to_lcid(lte_drb::drb1), 500) == nof_pending_bytes);
|
||||||
|
|
||||||
// TEST3 - SRB1 newtxs are emptied (PBR==infinity)
|
// TEST3 - SRB1 newtxs are emptied (PBR==infinity)
|
||||||
|
|
|
@ -47,7 +47,7 @@ int test_correct_meascfg_insertion()
|
||||||
cell3 = cell1;
|
cell3 = cell1;
|
||||||
cell3.earfcn = 2850;
|
cell3.earfcn = 2850;
|
||||||
cell4 = cell1;
|
cell4 = cell1;
|
||||||
cell4.q_offset = 1;
|
cell4.cell_individual_offset = asn1::rrc::q_offset_range_opts::db1;
|
||||||
|
|
||||||
report_cfg_eutra_s rep1 = generate_rep1();
|
report_cfg_eutra_s rep1 = generate_rep1();
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ int test_correct_meascfg_calculation()
|
||||||
meas_cell_cfg_t cell1{}, cell2{};
|
meas_cell_cfg_t cell1{}, cell2{};
|
||||||
cell1.earfcn = 3400;
|
cell1.earfcn = 3400;
|
||||||
cell1.pci = 1;
|
cell1.pci = 1;
|
||||||
cell1.q_offset = 0;
|
cell1.cell_individual_offset = asn1::rrc::q_offset_range_opts::db0;
|
||||||
cell1.eci = 0x19C01;
|
cell1.eci = 0x19C01;
|
||||||
cell2 = cell1;
|
cell2 = cell1;
|
||||||
cell2.pci = 2;
|
cell2.pci = 2;
|
||||||
|
@ -178,7 +178,7 @@ int test_correct_meascfg_calculation()
|
||||||
TESTASSERT(result_meascfg.report_cfg_to_add_mod_list.size() == 0);
|
TESTASSERT(result_meascfg.report_cfg_to_add_mod_list.size() == 0);
|
||||||
|
|
||||||
// TEST 3: Cell is added to cellsToAddModList if just a field was updated
|
// TEST 3: Cell is added to cellsToAddModList if just a field was updated
|
||||||
cell1.q_offset = 5;
|
cell1.cell_individual_offset = asn1::rrc::q_offset_range_opts::db5;
|
||||||
src_var = target_var;
|
src_var = target_var;
|
||||||
add_cell_enb_cfg(target_var.meas_obj_to_add_mod_list, cell1);
|
add_cell_enb_cfg(target_var.meas_obj_to_add_mod_list, cell1);
|
||||||
TESTASSERT(compute_diff_meascfg(src_var, target_var, result_meascfg));
|
TESTASSERT(compute_diff_meascfg(src_var, target_var, result_meascfg));
|
||||||
|
|
|
@ -184,7 +184,7 @@ meas_cell_cfg_t generate_cell1()
|
||||||
meas_cell_cfg_t cell1{};
|
meas_cell_cfg_t cell1{};
|
||||||
cell1.earfcn = 3400;
|
cell1.earfcn = 3400;
|
||||||
cell1.pci = 1;
|
cell1.pci = 1;
|
||||||
cell1.q_offset = 0;
|
cell1.cell_individual_offset = asn1::rrc::q_offset_range_opts::db0;
|
||||||
cell1.eci = 0x19C01;
|
cell1.eci = 0x19C01;
|
||||||
return cell1;
|
return cell1;
|
||||||
}
|
}
|
||||||
|
@ -207,7 +207,7 @@ report_cfg_eutra_s generate_rep1()
|
||||||
|
|
||||||
bool is_cell_cfg_equal(const meas_cell_cfg_t& cfg, const cells_to_add_mod_s& cell)
|
bool is_cell_cfg_equal(const meas_cell_cfg_t& cfg, const cells_to_add_mod_s& cell)
|
||||||
{
|
{
|
||||||
return cfg.pci == cell.pci and cell.cell_individual_offset.to_number() == (int8_t)round(cfg.q_offset);
|
return cfg.pci == cell.pci and cell.cell_individual_offset == cell.cell_individual_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace srsenb
|
} // namespace srsenb
|
||||||
|
|
|
@ -87,8 +87,12 @@ int s1ap::init(const s1ap_args_t& s1ap_args)
|
||||||
|
|
||||||
// Get pointer to GTP-C class
|
// Get pointer to GTP-C class
|
||||||
m_mme_gtpc = mme_gtpc::get_instance();
|
m_mme_gtpc = mme_gtpc::get_instance();
|
||||||
|
|
||||||
// Initialize S1-MME
|
// Initialize S1-MME
|
||||||
m_s1mme = enb_listen();
|
m_s1mme = enb_listen();
|
||||||
|
if (m_s1mme == SRSRAN_ERROR) {
|
||||||
|
return SRSRAN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
// Init PCAP
|
// Init PCAP
|
||||||
m_pcap_enable = s1ap_args.pcap_enable;
|
m_pcap_enable = s1ap_args.pcap_enable;
|
||||||
|
|
|
@ -83,7 +83,8 @@ private:
|
||||||
|
|
||||||
srslog::basic_logger& logger;
|
srslog::basic_logger& logger;
|
||||||
srsran_cell_t serving_cell = {}; ///< Current serving cell in the EARFCN, to avoid reporting it
|
srsran_cell_t serving_cell = {}; ///< Current serving cell in the EARFCN, to avoid reporting it
|
||||||
uint32_t current_earfcn = 0; ///< Current EARFCN
|
std::atomic<uint32_t> current_earfcn = {0}; ///< Current EARFCN
|
||||||
|
std::mutex mutex;
|
||||||
|
|
||||||
/// LTE-based measuring objects
|
/// LTE-based measuring objects
|
||||||
scell_recv scell_rx; ///< Secondary cell searcher
|
scell_recv scell_rx; ///< Secondary cell searcher
|
||||||
|
|
|
@ -127,7 +127,7 @@ private:
|
||||||
lockable_grant cur_grant;
|
lockable_grant cur_grant;
|
||||||
|
|
||||||
uint32_t pid;
|
uint32_t pid;
|
||||||
uint32_t current_tx_nb;
|
std::atomic<uint32_t> current_tx_nb = {0};
|
||||||
uint32_t current_irv;
|
uint32_t current_irv;
|
||||||
bool harq_feedback;
|
bool harq_feedback;
|
||||||
bool is_grant_configured;
|
bool is_grant_configured;
|
||||||
|
|
|
@ -97,6 +97,8 @@ private:
|
||||||
|
|
||||||
std::unique_ptr<byte_buffer_t> harq_buffer = nullptr;
|
std::unique_ptr<byte_buffer_t> harq_buffer = nullptr;
|
||||||
|
|
||||||
|
void save_grant(const mac_interface_phy_nr::mac_nr_grant_ul_t& grant);
|
||||||
|
|
||||||
void generate_tx(mac_interface_phy_nr::tb_action_ul_t* action);
|
void generate_tx(mac_interface_phy_nr::tb_action_ul_t* action);
|
||||||
void generate_new_tx(const mac_interface_phy_nr::mac_nr_grant_ul_t& grant,
|
void generate_new_tx(const mac_interface_phy_nr::mac_nr_grant_ul_t& grant,
|
||||||
mac_interface_phy_nr::tb_action_ul_t* action);
|
mac_interface_phy_nr::tb_action_ul_t* action);
|
||||||
|
@ -113,6 +115,8 @@ private:
|
||||||
srsran::ul_harq_cfg_t harq_cfg = {};
|
srsran::ul_harq_cfg_t harq_cfg = {};
|
||||||
ul_harq_metrics_t metrics = {};
|
ul_harq_metrics_t metrics = {};
|
||||||
std::mutex metrics_mutex;
|
std::mutex metrics_mutex;
|
||||||
|
|
||||||
|
const static uint8_t NDI_NOT_SET = 100;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::unique_ptr<ul_harq_entity_nr> ul_harq_entity_nr_ptr;
|
typedef std::unique_ptr<ul_harq_entity_nr> ul_harq_entity_nr_ptr;
|
||||||
|
|
|
@ -654,6 +654,9 @@ static void* input_loop(void*)
|
||||||
} else if (key == "rlf") {
|
} else if (key == "rlf") {
|
||||||
simulate_rlf.store(true, std::memory_order_relaxed);
|
simulate_rlf.store(true, std::memory_order_relaxed);
|
||||||
cout << "Sending Radio Link Failure" << endl;
|
cout << "Sending Radio Link Failure" << endl;
|
||||||
|
} else if (key == "flush") {
|
||||||
|
srslog::flush();
|
||||||
|
cout << "Flushed log file buffers" << endl;
|
||||||
} else if (key == "q") {
|
} else if (key == "q") {
|
||||||
// let the signal handler do the job
|
// let the signal handler do the job
|
||||||
raise(SIGTERM);
|
raise(SIGTERM);
|
||||||
|
|
|
@ -315,12 +315,14 @@ bool phy_common::is_any_ul_pending_ack()
|
||||||
#define tti_pusch_hi(sf) \
|
#define tti_pusch_hi(sf) \
|
||||||
(sf->tti + \
|
(sf->tti + \
|
||||||
(cell.frame_type == SRSRAN_FDD ? FDD_HARQ_DELAY_UL_MS \
|
(cell.frame_type == SRSRAN_FDD ? FDD_HARQ_DELAY_UL_MS \
|
||||||
: I_phich ? 7 : k_pusch[sf->tdd_config.sf_config][sf->tti % 10]) + \
|
: I_phich ? 7 \
|
||||||
|
: k_pusch[sf->tdd_config.sf_config][sf->tti % 10]) + \
|
||||||
(FDD_HARQ_DELAY_DL_MS - FDD_HARQ_DELAY_UL_MS))
|
(FDD_HARQ_DELAY_DL_MS - FDD_HARQ_DELAY_UL_MS))
|
||||||
#define tti_pusch_gr(sf) \
|
#define tti_pusch_gr(sf) \
|
||||||
(sf->tti + \
|
(sf->tti + \
|
||||||
(cell.frame_type == SRSRAN_FDD ? FDD_HARQ_DELAY_UL_MS \
|
(cell.frame_type == SRSRAN_FDD ? FDD_HARQ_DELAY_UL_MS \
|
||||||
: dci->ul_idx == 1 ? 7 : k_pusch[sf->tdd_config.sf_config][sf->tti % 10]) + \
|
: dci->ul_idx == 1 ? 7 \
|
||||||
|
: k_pusch[sf->tdd_config.sf_config][sf->tti % 10]) + \
|
||||||
(FDD_HARQ_DELAY_DL_MS - FDD_HARQ_DELAY_UL_MS))
|
(FDD_HARQ_DELAY_DL_MS - FDD_HARQ_DELAY_UL_MS))
|
||||||
|
|
||||||
// SF->TTI is at which Format0 dci is received
|
// SF->TTI is at which Format0 dci is received
|
||||||
|
@ -897,8 +899,11 @@ void phy_common::reset()
|
||||||
reset_radio();
|
reset_radio();
|
||||||
|
|
||||||
sr.reset();
|
sr.reset();
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(meas_mutex);
|
||||||
cur_pathloss = 0;
|
cur_pathloss = 0;
|
||||||
cur_pusch_power = 0;
|
cur_pusch_power = 0;
|
||||||
|
}
|
||||||
last_ri = 0;
|
last_ri = 0;
|
||||||
|
|
||||||
// Reset all measurements
|
// Reset all measurements
|
||||||
|
|
|
@ -51,8 +51,11 @@ void intra_measure_lte::init(uint32_t cc_idx, const args_t& args)
|
||||||
|
|
||||||
void intra_measure_lte::set_primary_cell(uint32_t earfcn, srsran_cell_t cell)
|
void intra_measure_lte::set_primary_cell(uint32_t earfcn, srsran_cell_t cell)
|
||||||
{
|
{
|
||||||
current_earfcn = earfcn;
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
serving_cell = cell;
|
serving_cell = cell;
|
||||||
|
}
|
||||||
|
current_earfcn = earfcn;
|
||||||
set_current_sf_len((uint32_t)SRSRAN_SF_LEN_PRB(cell.nof_prb));
|
set_current_sf_len((uint32_t)SRSRAN_SF_LEN_PRB(cell.nof_prb));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,8 +63,14 @@ bool intra_measure_lte::measure_rat(measure_context_t context, std::vector<cf_t>
|
||||||
{
|
{
|
||||||
std::set<uint32_t> cells_to_measure = context.active_pci;
|
std::set<uint32_t> cells_to_measure = context.active_pci;
|
||||||
|
|
||||||
|
srsran_cell_t serving_cell_copy{};
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
serving_cell_copy = serving_cell;
|
||||||
|
}
|
||||||
|
|
||||||
// Detect new cells using PSS/SSS
|
// Detect new cells using PSS/SSS
|
||||||
scell_rx.find_cells(buffer.data(), serving_cell, context.meas_len_ms, cells_to_measure);
|
scell_rx.find_cells(buffer.data(), serving_cell_copy, context.meas_len_ms, cells_to_measure);
|
||||||
|
|
||||||
// Initialise empty neighbour cell list
|
// Initialise empty neighbour cell list
|
||||||
std::vector<phy_meas_t> neighbour_cells = {};
|
std::vector<phy_meas_t> neighbour_cells = {};
|
||||||
|
@ -71,10 +80,10 @@ bool intra_measure_lte::measure_rat(measure_context_t context, std::vector<cf_t>
|
||||||
// Use Cell Reference signal to measure cells in the time domain for all known active PCI
|
// Use Cell Reference signal to measure cells in the time domain for all known active PCI
|
||||||
for (const uint32_t& id : cells_to_measure) {
|
for (const uint32_t& id : cells_to_measure) {
|
||||||
// Do not measure serving cell here since it's measured by workers
|
// Do not measure serving cell here since it's measured by workers
|
||||||
if (id == serving_cell.id) {
|
if (id == serving_cell_copy.id) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
srsran_cell_t cell = serving_cell;
|
srsran_cell_t cell = serving_cell_copy;
|
||||||
cell.id = id;
|
cell.id = id;
|
||||||
|
|
||||||
if (srsran_refsignal_dl_sync_set_cell(&refsignal_dl_sync, cell) < SRSRAN_SUCCESS) {
|
if (srsran_refsignal_dl_sync_set_cell(&refsignal_dl_sync, cell) < SRSRAN_SUCCESS) {
|
||||||
|
|
|
@ -50,6 +50,12 @@ void bsr_proc::init(sr_proc* sr_, rlc_interface_mac* rlc_, srsran::ext_task_sche
|
||||||
|
|
||||||
void bsr_proc::print_state()
|
void bsr_proc::print_state()
|
||||||
{
|
{
|
||||||
|
if (!logger.info.enabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
|
||||||
char str[128];
|
char str[128];
|
||||||
str[0] = '\0';
|
str[0] = '\0';
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue