nr,gnb,sched: centralized all feedback/event management (cc-specific and non-cc-specific) into a single class

master
Francisco 3 years ago committed by Francisco Paisana
parent 7c146c5198
commit 1a56629a72

@ -44,8 +44,8 @@ public:
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); int ul_bsr(uint32_t lcg_id, uint32_t val);
void dl_buffer_state(uint8_t lcid, uint32_t tx_queue, uint32_t prio_tx_queue); int 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; } uint16_t get_rnti() const { return rnti; }

@ -65,8 +65,8 @@ 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 int dl_ack_info(uint32_t pid, uint32_t tb_idx, bool ack);
void new_slot(slot_point slot_tx); int ul_crc_info(uint32_t pid, bool crc);
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);
@ -83,6 +83,7 @@ public:
mac_ue_metrics_t metrics = {}; mac_ue_metrics_t metrics = {};
private: private:
srslog::basic_logger& logger;
bwp_ue_cfg bwp_cfg; bwp_ue_cfg bwp_cfg;
const cell_params_t& cell_params; const cell_params_t& cell_params;
}; };

@ -30,41 +30,9 @@ struct mac_metrics_t;
namespace sched_nr_impl { namespace sched_nr_impl {
/// Class to manage the locking, storing and processing of carrier-specific feedback (UE-specific or common)
class carrier_feedback_manager
{
public:
using feedback_callback_t = srsran::move_callback<void(ue_carrier&)>;
struct feedback_t {
uint16_t rnti;
feedback_callback_t fdbk;
};
explicit carrier_feedback_manager(const cell_params_t& cell_cfg);
/// Enqueue cell-specific event not directly at a given UE (e.g. PRACH)
void enqueue_common_event(srsran::move_callback<void()> ev);
/// Enqueue feedback directed at a given UE in a given cell (e.g. ACKs, CQI)
void enqueue_ue_feedback(uint16_t rnti, feedback_callback_t fdbk);
/// Run all pending feedback. This should be called at the beginning of a TTI
void run(ue_map_t& ue_db);
private:
const cell_params_t& cfg;
srslog::basic_logger& logger;
std::mutex feedback_mutex;
srsran::deque<feedback_t> pending_feedback, tmp_feedback_to_run;
srsran::deque<srsran::move_callback<void()> > pending_events, tmp_events_to_run;
};
class cc_worker class cc_worker
{ {
public: public:
using feedback_callback_t = srsran::move_callback<void(ue_carrier&)>;
explicit cc_worker(const cell_params_t& params); explicit cc_worker(const cell_params_t& params);
void dl_rach_info(const sched_nr_interface::rar_info_t& rar_info); void dl_rach_info(const sched_nr_interface::rar_info_t& rar_info);
@ -75,8 +43,6 @@ public:
const cell_params_t& cfg; const cell_params_t& cfg;
srslog::basic_logger& logger; srslog::basic_logger& logger;
carrier_feedback_manager pending_feedback;
// cc-specific resources // cc-specific resources
srsran::bounded_vector<bwp_manager, SCHED_NR_MAX_BWP_PER_CELL> bwps; srsran::bounded_vector<bwp_manager, SCHED_NR_MAX_BWP_PER_CELL> bwps;
@ -92,15 +58,6 @@ private:
slot_ue_map_t slot_ues; slot_ue_map_t slot_ues;
}; };
class sched_worker_manager
{
public:
void get_metrics(mac_metrics_t& metrics);
private:
void get_metrics_nolocking(mac_metrics_t& metrics);
};
} // namespace sched_nr_impl } // namespace sched_nr_impl
} // namespace srsenb } // namespace srsenb

@ -32,7 +32,6 @@ public:
// Inherited methods from ue_buffer_manager base class // Inherited methods from ue_buffer_manager base class
using base_type::config_lcid; using base_type::config_lcid;
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_prio_tx; using base_type::get_dl_prio_tx;
@ -42,8 +41,9 @@ public:
using base_type::is_bearer_dl; using base_type::is_bearer_dl;
using base_type::is_bearer_ul; using base_type::is_bearer_ul;
using base_type::is_lcg_active; using base_type::is_lcg_active;
using base_type::ul_bsr;
void dl_buffer_state(uint8_t lcid, uint32_t tx_queue, uint32_t prio_tx_queue);
void ul_bsr(uint32_t lcg_id, uint32_t val);
void ul_buffer_add(uint8_t lcid, uint32_t bytes); void ul_buffer_add(uint8_t lcid, uint32_t bytes);
int alloc_rlc_pdu(sched_interface::dl_sched_pdu_t* lcid, int rem_bytes); int alloc_rlc_pdu(sched_interface::dl_sched_pdu_t* lcid, int rem_bytes);

@ -15,6 +15,9 @@
#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"
extern "C" {
#include "srsran/config.h"
}
namespace srsenb { namespace srsenb {
@ -144,37 +147,26 @@ int ue_buffer_manager<isNR>::get_bsr() const
} }
template <bool isNR> template <bool isNR>
void ue_buffer_manager<isNR>::ul_bsr(uint32_t lcg_id, uint32_t val) int 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("SCHED: The provided lcg_id=%d for rnti=0x%x is not valid", lcg_id, rnti); logger.warning("SCHED: The provided lcg_id=%d for rnti=0x%x is not valid", lcg_id, rnti);
return; return SRSRAN_ERROR;
} }
lcg_bsr[lcg_id] = val; lcg_bsr[lcg_id] = val;
return SRSRAN_SUCCESS;
if (logger.debug.enabled()) {
fmt::memory_buffer str_buffer;
fmt::format_to(str_buffer, "{}", lcg_bsr);
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 prio_tx_queue) int 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 SRSRAN_ERROR;
}
if (lcid <= MAX_SRB_LC_ID and
(channels[lcid].buf_tx != (int)tx_queue or channels[lcid].buf_prio_tx != (int)prio_tx_queue)) {
logger.info("SCHED: rnti=0x%x DL lcid=%d buffer_state=%d,%d", rnti, lcid, tx_queue, prio_tx_queue);
} else {
logger.debug("SCHED: rnti=0x%x DL lcid=%d buffer_state=%d,%d", rnti, lcid, tx_queue, prio_tx_queue);
} }
channels[lcid].buf_prio_tx = prio_tx_queue; channels[lcid].buf_prio_tx = prio_tx_queue;
channels[lcid].buf_tx = tx_queue; channels[lcid].buf_tx = tx_queue;
return SRSRAN_SUCCESS;
} }
// Explicit instantiation // Explicit instantiation

@ -85,9 +85,9 @@ public:
{ {
if (log_enabled and event_fmtbuf.size() > 0) { if (log_enabled and event_fmtbuf.size() > 0) {
if (cc < 0) { if (cc < 0) {
sched_logger.debug("SCHED: Processed slot events: [%s]", srsran::to_c_str(event_fmtbuf)); sched_logger.debug("SCHED: slot events: [%s]", srsran::to_c_str(event_fmtbuf));
} else { } else {
sched_logger.debug("SCHED: Processed slot events, cc=%d: [%s]", cc, srsran::to_c_str(event_fmtbuf)); sched_logger.debug("SCHED: slot events, cc=%d: [%s]", cc, srsran::to_c_str(event_fmtbuf));
} }
} }
} }
@ -102,13 +102,6 @@ public:
fmt::format_to(event_fmtbuf, fmt, std::forward<Args>(args)...); fmt::format_to(event_fmtbuf, fmt, std::forward<Args>(args)...);
} }
} }
template <typename... Args>
void push_warning(const char* fmt, Args&&... args)
{
fmt::memory_buffer fmtbuf;
fmt::format_to(fmtbuf, fmt, std::forward<Args>(args)...);
sched_logger.warning("SCHED: %s", srsran::to_c_str(fmtbuf));
}
private: private:
bool log_enabled; bool log_enabled;
@ -117,7 +110,9 @@ public:
fmt::memory_buffer event_fmtbuf; fmt::memory_buffer event_fmtbuf;
}; };
explicit event_manager(srslog::basic_logger& logger_) : sched_logger(logger_) {} explicit event_manager(sched_params& params) :
sched_logger(srslog::fetch_basic_logger(params.sched_cfg.logger_name)), carriers(params.cells.size())
{}
/// Enqueue an event that does not map into a ue method (e.g. rem_user, add_user) /// Enqueue an event that does not map into a ue method (e.g. rem_user, add_user)
void enqueue_event(const char* event_name, srsran::move_callback<void(logger&)> ev) void enqueue_event(const char* event_name, srsran::move_callback<void(logger&)> ev)
@ -135,7 +130,19 @@ public:
next_slot_ue_events.emplace_back(rnti, event_name, std::move(callback)); next_slot_ue_events.emplace_back(rnti, event_name, std::move(callback));
} }
/// Process all events that are directed at CA-enabled UEs /// Enqueue feedback directed at a given UE in a given cell (e.g. ACKs, CQI)
void enqueue_ue_cc_feedback(const char* event_name,
uint16_t rnti,
uint32_t cc,
srsran::move_callback<void(ue_carrier&, logger&)> callback)
{
srsran_assert(rnti != SRSRAN_INVALID_RNTI, "Invalid rnti=0x%x passed to event manager", rnti);
srsran_assert(cc < carriers.size(), "Invalid cc=%d passed to event manager", cc);
std::lock_guard<std::mutex> lock(carriers[cc].event_cc_mutex);
carriers[cc].next_slot_ue_events.emplace_back(rnti, cc, event_name, std::move(callback));
}
/// Process all events that are not specific to a carrier or that are directed at CA-enabled UEs
/// Note: non-CA UEs are updated later in get_dl_sched, to leverage parallelism /// Note: non-CA UEs are updated later in get_dl_sched, to leverage parallelism
void process_common(ue_map_t& ues) void process_common(ue_map_t& ues)
{ {
@ -169,9 +176,16 @@ public:
} }
/// Process events synchronized during slot_indication() that are directed at non CA-enabled UEs /// Process events synchronized during slot_indication() that are directed at non CA-enabled UEs
void process_single_cc_ue_events(ue_map_t& ues, uint32_t cc) void process_cc_events(ue_map_t& ues, uint32_t cc)
{ {
logger evlogger(cc, sched_logger); logger evlogger(cc, sched_logger);
{
carriers[cc].current_slot_ue_events.clear();
std::lock_guard<std::mutex> lock(carriers[cc].event_cc_mutex);
carriers[cc].current_slot_ue_events.swap(carriers[cc].next_slot_ue_events);
}
for (ue_event_t& ev : current_slot_ue_events) { for (ue_event_t& ev : current_slot_ue_events) {
if (ev.rnti == SRSRAN_INVALID_RNTI) { if (ev.rnti == SRSRAN_INVALID_RNTI) {
// events already processed // events already processed
@ -186,6 +200,15 @@ public:
ev.rnti = SRSRAN_INVALID_RNTI; ev.rnti = SRSRAN_INVALID_RNTI;
} }
} }
for (ue_cc_event_t& ev : carriers[cc].current_slot_ue_events) {
auto ue_it = ues.find(ev.rnti);
if (ue_it != ues.end() and ue_it->second->carriers[cc] != nullptr) {
ev.callback(*ue_it->second->carriers[cc], evlogger);
} else {
sched_logger.warning("SCHED: \"%s\" called for inexistent rnti=0x%x,cc=%d.", ev.event_name, ev.rnti, ev.cc);
}
}
} }
private: private:
@ -204,12 +227,29 @@ private:
rnti(rnti_), event_name(event_name_), callback(std::move(c)) rnti(rnti_), event_name(event_name_), callback(std::move(c))
{} {}
}; };
struct ue_cc_event_t {
uint16_t rnti;
uint32_t cc;
const char* event_name;
srsran::move_callback<void(ue_carrier&, logger&)> callback;
ue_cc_event_t(uint16_t rnti_,
uint32_t cc_,
const char* event_name_,
srsran::move_callback<void(ue_carrier&, logger&)> c) :
rnti(rnti_), cc(cc_), event_name(event_name_), callback(std::move(c))
{}
};
srslog::basic_logger& sched_logger; srslog::basic_logger& sched_logger;
std::mutex event_mutex; std::mutex event_mutex;
srsran::deque<ue_event_t> next_slot_ue_events, current_slot_ue_events;
srsran::deque<event_t> next_slot_events, current_slot_events; srsran::deque<event_t> next_slot_events, current_slot_events;
srsran::deque<ue_event_t> next_slot_ue_events, current_slot_ue_events;
struct cc_events {
std::mutex event_cc_mutex;
srsran::deque<ue_cc_event_t> next_slot_ue_events, current_slot_ue_events;
};
std::vector<cc_events> carriers;
}; };
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -303,8 +343,7 @@ int sched_nr::config(const sched_args_t& sched_cfg, srsran::const_span<cell_cfg_
} }
pending_results.reset(new ul_sched_result_buffer(cell_list.size())); pending_results.reset(new ul_sched_result_buffer(cell_list.size()));
pending_events.reset(new event_manager{cfg});
pending_events.reset(new event_manager{*logger});
// Initiate cell-specific schedulers // Initiate cell-specific schedulers
cc_workers.resize(cfg.cells.size()); cc_workers.resize(cfg.cells.size());
@ -318,13 +357,11 @@ int sched_nr::config(const sched_args_t& sched_cfg, srsran::const_span<cell_cfg_
void sched_nr::ue_cfg(uint16_t rnti, const ue_cfg_t& uecfg) void sched_nr::ue_cfg(uint16_t rnti, const ue_cfg_t& uecfg)
{ {
srsran_assert(assert_ue_cfg_valid(rnti, uecfg) == SRSRAN_SUCCESS, "Invalid UE configuration"); srsran_assert(assert_ue_cfg_valid(rnti, uecfg) == SRSRAN_SUCCESS, "Invalid UE configuration");
logger->info("SCHED: New user rnti=0x%x, cc=%d", rnti, cfg.cells[0].cc);
pending_events->enqueue_event("ue_cfg", [this, rnti, uecfg](event_manager::logger& ev_logger) { pending_events->enqueue_event("ue_cfg", [this, rnti, uecfg](event_manager::logger& ev_logger) {
if (ue_cfg_impl(rnti, uecfg) == SRSRAN_SUCCESS) { if (ue_cfg_impl(rnti, uecfg) == SRSRAN_SUCCESS) {
ev_logger.push("ue_cfg(0x{:x})", rnti); ev_logger.push("ue_cfg(0x{:x})", rnti);
} else { } else {
ev_logger.push_warning("Failed to create UE object for rnti=0x{:x}", rnti); logger->warning("Failed to create UE object for rnti=0x{:x}", rnti);
} }
}); });
} }
@ -333,12 +370,14 @@ void sched_nr::ue_rem(uint16_t rnti)
{ {
pending_events->enqueue_event("ue_rem", [this, rnti](event_manager::logger& ev_logger) { pending_events->enqueue_event("ue_rem", [this, rnti](event_manager::logger& ev_logger) {
ue_db.erase(rnti); ue_db.erase(rnti);
logger->info("SCHED: Removed user rnti=0x%x", rnti);
ev_logger.push("ue_rem(0x{:x})", rnti); ev_logger.push("ue_rem(0x{:x})", rnti);
}); });
} }
int sched_nr::add_ue_impl(uint16_t rnti, std::unique_ptr<sched_nr_impl::ue> u) int sched_nr::add_ue_impl(uint16_t rnti, std::unique_ptr<sched_nr_impl::ue> u)
{ {
logger->info("SCHED: New user rnti=0x%x, cc=%d", rnti, cfg.cells[0].cc);
return ue_db.insert(rnti, std::move(u)).has_value() ? SRSRAN_SUCCESS : SRSRAN_ERROR; return ue_db.insert(rnti, std::move(u)).has_value() ? SRSRAN_SUCCESS : SRSRAN_ERROR;
} }
@ -385,7 +424,7 @@ int sched_nr::get_dl_sched(slot_point pdsch_tti, uint32_t cc, dl_res_t& result)
ul_res_t& ul_res = pending_results->add_ul_result(pdsch_tti, cc); ul_res_t& ul_res = pending_results->add_ul_result(pdsch_tti, cc);
// process non-cc specific feedback if pending (e.g. SRs, buffer state updates, UE config) for non-CA UEs // process non-cc specific feedback if pending (e.g. SRs, buffer state updates, UE config) for non-CA UEs
pending_events->process_single_cc_ue_events(ue_db, cc); pending_events->process_cc_events(ue_db, cc);
// prepare non-CA UEs internal state for new slot // prepare non-CA UEs internal state for new slot
for (auto& u : ue_db) { for (auto& u : ue_db) {
@ -439,12 +478,11 @@ int sched_nr::dl_rach_info(const rar_info_t& rar_info, const ue_cfg_t& uecfg)
uint16_t rnti = rar_info.temp_crnti; uint16_t rnti = rar_info.temp_crnti;
if (add_ue_impl(rnti, std::move(u)) == SRSRAN_SUCCESS) { if (add_ue_impl(rnti, std::move(u)) == SRSRAN_SUCCESS) {
ev_logger.push("dl_rach_info(temp c-rnti=0x{:x})", rar_info.temp_crnti); ev_logger.push("dl_rach_info(temp c-rnti=0x{:x})", rar_info.temp_crnti);
// RACH is handled in cc worker, once the UE object is created and inserted in the ue_db // RACH is handled only once the UE object is created and inserted in the ue_db
uint32_t cc = uecfg.carriers[0].cc; uint32_t cc = uecfg.carriers[0].cc;
cc_workers[cc]->pending_feedback.enqueue_common_event( cc_workers[cc]->dl_rach_info(rar_info);
[this, cc, rar_info]() { cc_workers[cc]->dl_rach_info(rar_info); });
} else { } else {
ev_logger.push_warning("Failed to create UE object with rnti=0x%x", rar_info.temp_crnti); logger->warning("Failed to create UE object with rnti=0x%x", rar_info.temp_crnti);
} }
}; };
pending_events->enqueue_event("dl_rach_info", add_ue); pending_events->enqueue_event("dl_rach_info", add_ue);
@ -453,28 +491,22 @@ int sched_nr::dl_rach_info(const rar_info_t& rar_info, const ue_cfg_t& uecfg)
void sched_nr::dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) void sched_nr::dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack)
{ {
cc_workers[cc]->pending_feedback.enqueue_ue_feedback(rnti, [this, pid, tb_idx, ack](ue_carrier& ue_cc) { auto callback = [pid, tb_idx, ack](ue_carrier& ue_cc, event_manager::logger& ev_logger) {
int tbs = ue_cc.harq_ent.dl_ack_info(pid, tb_idx, ack); if (ue_cc.dl_ack_info(pid, tb_idx, ack) >= 0) {
if (tbs >= 0) { ev_logger.push("0x{:x}: dl_ack_info(pid={}, ack={})", ue_cc.rnti, pid, ack ? "OK" : "KO");
if (ack) {
ue_cc.metrics.tx_brate += tbs;
} else {
ue_cc.metrics.tx_errors++;
}
ue_cc.metrics.tx_pkts++;
} else {
logger->warning("SCHED: rnti=0x%x, received DL HARQ-ACK for empty pid=%d", ue_cc.rnti, pid);
} }
}); };
pending_events->enqueue_ue_cc_feedback("dl_ack_info", rnti, cc, callback);
} }
void sched_nr::ul_crc_info(uint16_t rnti, uint32_t cc, uint32_t pid, bool crc) void sched_nr::ul_crc_info(uint16_t rnti, uint32_t cc, uint32_t pid, bool crc)
{ {
cc_workers[cc]->pending_feedback.enqueue_ue_feedback(rnti, [this, pid, crc](ue_carrier& ue_cc) { auto callback = [pid, crc](ue_carrier& ue_cc, event_manager::logger& ev_logger) {
if (ue_cc.harq_ent.ul_crc_info(pid, crc) < 0) { if (ue_cc.ul_crc_info(pid, crc) >= 0) {
logger->warning("SCHED: rnti=0x%x, received CRC for empty pid=%d", ue_cc.rnti, pid); ev_logger.push("0x{:x}: ul_crc_info(pid={}, crc={})", ue_cc.rnti, pid, crc ? "OK" : "KO");
} }
}); };
pending_events->enqueue_ue_cc_feedback("ul_crc_info", rnti, cc, callback);
} }
void sched_nr::ul_sr_info(uint16_t rnti) void sched_nr::ul_sr_info(uint16_t rnti)
@ -498,7 +530,7 @@ void sched_nr::dl_buffer_state(uint16_t rnti, uint32_t lcid, uint32_t newtx, uin
pending_events->enqueue_ue_event( pending_events->enqueue_ue_event(
"dl_buffer_state", rnti, [lcid, newtx, retx](ue& u, event_manager::logger& event_logger) { "dl_buffer_state", rnti, [lcid, newtx, retx](ue& u, event_manager::logger& event_logger) {
u.rlc_buffer_state(lcid, newtx, retx); u.rlc_buffer_state(lcid, newtx, retx);
event_logger.push("0x{:x}: dl_buffer_state(lcid={}, newtx={}, retx={})", u.rnti, lcid, newtx, retx); event_logger.push("0x{:x}: dl_buffer_state(lcid={}, bsr={},{})", u.rnti, lcid, newtx, retx);
}); });
} }

@ -24,6 +24,7 @@ slot_ue::slot_ue(uint16_t rnti_, slot_point slot_rx_, uint32_t cc_) : rnti(rnti_
ue_carrier::ue_carrier(uint16_t rnti_, const ue_cfg_t& uecfg_, const cell_params_t& cell_params_) : ue_carrier::ue_carrier(uint16_t rnti_, const ue_cfg_t& uecfg_, const cell_params_t& cell_params_) :
rnti(rnti_), rnti(rnti_),
cc(cell_params_.cc), cc(cell_params_.cc),
logger(srslog::fetch_basic_logger(cell_params_.sched_args.logger_name)),
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(rnti_, cell_params_.nof_prb(), SCHED_NR_MAX_HARQ, cell_params_.bwps[0].logger) harq_ent(rnti_, cell_params_.nof_prb(), SCHED_NR_MAX_HARQ, cell_params_.bwps[0].logger)
@ -34,9 +35,29 @@ 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) int ue_carrier::dl_ack_info(uint32_t pid, uint32_t tb_idx, bool ack)
{ {
harq_ent.new_slot(slot_tx - TX_ENB_DELAY); int tbs = harq_ent.dl_ack_info(pid, tb_idx, ack);
if (tbs < 0) {
logger.warning("SCHED: rnti=0x%x received DL HARQ-ACK for empty pid=%d", rnti, pid);
return tbs;
}
if (ack) {
metrics.tx_brate += tbs;
} else {
metrics.tx_errors++;
}
metrics.tx_pkts++;
return tbs;
}
int ue_carrier::ul_crc_info(uint32_t pid, bool crc)
{
int ret = harq_ent.ul_crc_info(pid, crc);
if (ret < 0) {
logger.warning("SCHED: rnti=0x%x,cc=%d received CRC for empty pid=%d", rnti, cc, pid);
}
return ret;
} }
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)
@ -108,6 +129,12 @@ void ue::new_slot(slot_point pdcch_slot)
{ {
last_pdcch_slot = pdcch_slot; last_pdcch_slot = pdcch_slot;
for (std::unique_ptr<ue_carrier>& cc : carriers) {
if (cc != nullptr) {
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;

@ -18,51 +18,8 @@
namespace srsenb { namespace srsenb {
namespace sched_nr_impl { namespace sched_nr_impl {
carrier_feedback_manager::carrier_feedback_manager(const cell_params_t& cell_cfg) :
cfg(cell_cfg), logger(srslog::fetch_basic_logger(cell_cfg.sched_args.logger_name))
{}
void carrier_feedback_manager::enqueue_common_event(srsran::move_callback<void()> ev)
{
std::lock_guard<std::mutex> lock(feedback_mutex);
pending_events.emplace_back(std::move(ev));
}
void carrier_feedback_manager::enqueue_ue_feedback(uint16_t rnti, feedback_callback_t fdbk)
{
std::lock_guard<std::mutex> lock(feedback_mutex);
pending_feedback.emplace_back();
pending_feedback.back().rnti = rnti;
pending_feedback.back().fdbk = std::move(fdbk);
}
void carrier_feedback_manager::run(ue_map_t& ue_db)
{
{
std::lock_guard<std::mutex> lock(feedback_mutex);
tmp_feedback_to_run.swap(pending_feedback);
tmp_events_to_run.swap(pending_events);
}
for (srsran::move_callback<void()>& ev : tmp_events_to_run) {
ev();
}
tmp_events_to_run.clear();
for (feedback_t& f : tmp_feedback_to_run) {
if (ue_db.contains(f.rnti) and ue_db[f.rnti]->carriers[cfg.cc] != nullptr) {
f.fdbk(*ue_db[f.rnti]->carriers[cfg.cc]);
} else {
logger.info("SCHED: feedback received for rnti=0x%x, cc=%d that has been removed.", f.rnti, cfg.cc);
}
}
tmp_feedback_to_run.clear();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
cc_worker::cc_worker(const cell_params_t& params) : cc_worker::cc_worker(const cell_params_t& params) :
cfg(params), logger(srslog::fetch_basic_logger(params.sched_args.logger_name)), pending_feedback(params) cfg(params), logger(srslog::fetch_basic_logger(params.sched_args.logger_name))
{ {
for (uint32_t bwp_id = 0; bwp_id < cfg.cfg.bwps.size(); ++bwp_id) { for (uint32_t bwp_id = 0; bwp_id < cfg.cfg.bwps.size(); ++bwp_id) {
bwps.emplace_back(cfg.bwps[bwp_id]); bwps.emplace_back(cfg.bwps[bwp_id]);
@ -102,9 +59,6 @@ void cc_worker::run_slot(slot_point pdcch_slot, ue_map_t& ue_db, dl_sched_res_t&
// Create an BWP allocator object that will passed along to RA, SI, Data schedulers // Create an BWP allocator object that will passed along to RA, SI, Data schedulers
bwp_slot_allocator bwp_alloc{bwps[0].grid, pdcch_slot, slot_ues}; bwp_slot_allocator bwp_alloc{bwps[0].grid, pdcch_slot, slot_ues};
// Run pending cell feedback (process feedback)
pending_feedback.run(ue_db);
// Reserve UEs for this worker slot (select candidate UEs) // Reserve UEs for this worker slot (select candidate UEs)
for (auto& ue_pair : ue_db) { for (auto& ue_pair : ue_db) {
uint16_t rnti = ue_pair.first; uint16_t rnti = ue_pair.first;
@ -113,9 +67,6 @@ void cc_worker::run_slot(slot_point pdcch_slot, ue_map_t& ue_db, dl_sched_res_t&
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()) {

@ -73,6 +73,25 @@ void lch_ue_manager::new_tti()
} }
} }
void lch_ue_manager::dl_buffer_state(uint8_t lcid, uint32_t tx_queue, uint32_t prio_tx_queue)
{
if (base_type::dl_buffer_state(lcid, tx_queue, prio_tx_queue) == SRSRAN_SUCCESS) {
logger.debug("SCHED: rnti=0x%x DL lcid=%d buffer_state=%d,%d", rnti, lcid, tx_queue, prio_tx_queue);
}
}
void lch_ue_manager::ul_bsr(uint32_t lcg_id, uint32_t val)
{
if (base_type::ul_bsr(lcg_id, val) == SRSRAN_SUCCESS) {
if (logger.debug.enabled()) {
fmt::memory_buffer str_buffer;
fmt::format_to(str_buffer, "{}", lcg_bsr);
logger.debug(
"SCHED: rnti=0x%x, lcg_id=%d, bsr=%d. Current state=%s", rnti, lcg_id, val, srsran::to_c_str(str_buffer));
}
}
}
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) {

@ -56,7 +56,6 @@ void test_single_prach()
auto run_slot = [&res_grid, &rasched, &pdcch_slot, &slot_ues, &u]() -> const bwp_slot_grid* { auto run_slot = [&res_grid, &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()) {

Loading…
Cancel
Save