mirror of https://github.com/PentHertz/srsLTE.git
nr,gnb,sched: centralized all feedback/event management (cc-specific and non-cc-specific) into a single class
This commit is contained in:
parent
7c146c5198
commit
1a56629a72
|
@ -44,8 +44,8 @@ public:
|
|||
void config_lcid(uint32_t lcid, const mac_lc_ch_cfg_t& bearer_cfg);
|
||||
|
||||
// Buffer Status update
|
||||
void 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 ul_bsr(uint32_t lcg_id, uint32_t val);
|
||||
int dl_buffer_state(uint8_t lcid, uint32_t tx_queue, uint32_t prio_tx_queue);
|
||||
|
||||
// Configuration getters
|
||||
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_);
|
||||
void set_cfg(const ue_cfg_t& ue_cfg);
|
||||
|
||||
/// Called after CC Feedback has been processed
|
||||
void new_slot(slot_point slot_tx);
|
||||
int dl_ack_info(uint32_t pid, uint32_t tb_idx, bool ack);
|
||||
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);
|
||||
|
||||
|
@ -83,8 +83,9 @@ public:
|
|||
mac_ue_metrics_t metrics = {};
|
||||
|
||||
private:
|
||||
bwp_ue_cfg bwp_cfg;
|
||||
const cell_params_t& cell_params;
|
||||
srslog::basic_logger& logger;
|
||||
bwp_ue_cfg bwp_cfg;
|
||||
const cell_params_t& cell_params;
|
||||
};
|
||||
|
||||
class ue
|
||||
|
|
|
@ -30,41 +30,9 @@ struct mac_metrics_t;
|
|||
|
||||
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
|
||||
{
|
||||
public:
|
||||
using feedback_callback_t = srsran::move_callback<void(ue_carrier&)>;
|
||||
|
||||
explicit cc_worker(const cell_params_t& params);
|
||||
|
||||
void dl_rach_info(const sched_nr_interface::rar_info_t& rar_info);
|
||||
|
@ -75,8 +43,6 @@ public:
|
|||
const cell_params_t& cfg;
|
||||
srslog::basic_logger& logger;
|
||||
|
||||
carrier_feedback_manager pending_feedback;
|
||||
|
||||
// cc-specific resources
|
||||
srsran::bounded_vector<bwp_manager, SCHED_NR_MAX_BWP_PER_CELL> bwps;
|
||||
|
||||
|
@ -92,15 +58,6 @@ private:
|
|||
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 srsenb
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@ public:
|
|||
|
||||
// Inherited methods from ue_buffer_manager base class
|
||||
using base_type::config_lcid;
|
||||
using base_type::dl_buffer_state;
|
||||
using base_type::get_bsr;
|
||||
using base_type::get_bsr_state;
|
||||
using base_type::get_dl_prio_tx;
|
||||
|
@ -42,8 +41,9 @@ public:
|
|||
using base_type::is_bearer_dl;
|
||||
using base_type::is_bearer_ul;
|
||||
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);
|
||||
|
||||
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/srslog/bundled/fmt/format.h"
|
||||
#include "srsran/srslog/bundled/fmt/ranges.h"
|
||||
extern "C" {
|
||||
#include "srsran/config.h"
|
||||
}
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
|
@ -144,37 +147,26 @@ int ue_buffer_manager<isNR>::get_bsr() const
|
|||
}
|
||||
|
||||
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)) {
|
||||
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;
|
||||
|
||||
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));
|
||||
}
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
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)) {
|
||||
logger.warning("The provided lcid=%d is not valid", lcid);
|
||||
return;
|
||||
}
|
||||
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);
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
channels[lcid].buf_prio_tx = prio_tx_queue;
|
||||
channels[lcid].buf_tx = tx_queue;
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
// Explicit instantiation
|
||||
|
|
|
@ -85,9 +85,9 @@ public:
|
|||
{
|
||||
if (log_enabled and event_fmtbuf.size() > 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 {
|
||||
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)...);
|
||||
}
|
||||
}
|
||||
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:
|
||||
bool log_enabled;
|
||||
|
@ -117,7 +110,9 @@ public:
|
|||
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)
|
||||
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));
|
||||
}
|
||||
|
||||
/// 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
|
||||
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
|
||||
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);
|
||||
|
||||
{
|
||||
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) {
|
||||
if (ev.rnti == SRSRAN_INVALID_RNTI) {
|
||||
// events already processed
|
||||
|
@ -186,6 +200,15 @@ public:
|
|||
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:
|
||||
|
@ -204,12 +227,29 @@ private:
|
|||
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;
|
||||
|
||||
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<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_events.reset(new event_manager{*logger});
|
||||
pending_events.reset(new event_manager{cfg});
|
||||
|
||||
// Initiate cell-specific schedulers
|
||||
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)
|
||||
{
|
||||
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) {
|
||||
if (ue_cfg_impl(rnti, uecfg) == SRSRAN_SUCCESS) {
|
||||
ev_logger.push("ue_cfg(0x{:x})", rnti);
|
||||
} 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) {
|
||||
ue_db.erase(rnti);
|
||||
logger->info("SCHED: Removed user rnti=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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
// 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
|
||||
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;
|
||||
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);
|
||||
// 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;
|
||||
cc_workers[cc]->pending_feedback.enqueue_common_event(
|
||||
[this, cc, rar_info]() { cc_workers[cc]->dl_rach_info(rar_info); });
|
||||
cc_workers[cc]->dl_rach_info(rar_info);
|
||||
} 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);
|
||||
|
@ -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)
|
||||
{
|
||||
cc_workers[cc]->pending_feedback.enqueue_ue_feedback(rnti, [this, pid, tb_idx, ack](ue_carrier& ue_cc) {
|
||||
int tbs = ue_cc.harq_ent.dl_ack_info(pid, tb_idx, ack);
|
||||
if (tbs >= 0) {
|
||||
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);
|
||||
auto callback = [pid, tb_idx, ack](ue_carrier& ue_cc, event_manager::logger& ev_logger) {
|
||||
if (ue_cc.dl_ack_info(pid, tb_idx, ack) >= 0) {
|
||||
ev_logger.push("0x{:x}: dl_ack_info(pid={}, ack={})", ue_cc.rnti, pid, ack ? "OK" : "KO");
|
||||
}
|
||||
});
|
||||
};
|
||||
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)
|
||||
{
|
||||
cc_workers[cc]->pending_feedback.enqueue_ue_feedback(rnti, [this, pid, crc](ue_carrier& ue_cc) {
|
||||
if (ue_cc.harq_ent.ul_crc_info(pid, crc) < 0) {
|
||||
logger->warning("SCHED: rnti=0x%x, received CRC for empty pid=%d", ue_cc.rnti, pid);
|
||||
auto callback = [pid, crc](ue_carrier& ue_cc, event_manager::logger& ev_logger) {
|
||||
if (ue_cc.ul_crc_info(pid, crc) >= 0) {
|
||||
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)
|
||||
|
@ -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(
|
||||
"dl_buffer_state", rnti, [lcid, newtx, retx](ue& u, event_manager::logger& event_logger) {
|
||||
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_) :
|
||||
rnti(rnti_),
|
||||
cc(cell_params_.cc),
|
||||
logger(srslog::fetch_basic_logger(cell_params_.sched_args.logger_name)),
|
||||
bwp_cfg(rnti_, cell_params_.bwps[0], uecfg_),
|
||||
cell_params(cell_params_),
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -108,6 +129,12 @@ void ue::new_slot(slot_point 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}
|
||||
if (sched_cfg.sched_cfg.auto_refill_buffer) {
|
||||
dl_pending_bytes = 1000000;
|
||||
|
|
|
@ -18,51 +18,8 @@
|
|||
namespace srsenb {
|
||||
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) :
|
||||
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) {
|
||||
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
|
||||
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)
|
||||
for (auto& ue_pair : ue_db) {
|
||||
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;
|
||||
}
|
||||
|
||||
// Update UE CC state
|
||||
u.carriers[cfg.cc]->new_slot(pdcch_slot);
|
||||
|
||||
// info for a given UE on a slot to be process
|
||||
slot_ues.insert(rnti, u.try_reserve(pdcch_slot, cfg.cc));
|
||||
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)
|
||||
{
|
||||
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* {
|
||||
mac_logger.set_context(pdcch_slot.to_uint());
|
||||
u.new_slot(pdcch_slot);
|
||||
u.carriers[0]->new_slot(pdcch_slot);
|
||||
slot_ues.clear();
|
||||
slot_ue sfu = u.try_reserve(pdcch_slot, 0);
|
||||
if (not sfu.empty()) {
|
||||
|
|
Loading…
Reference in New Issue