sched, feature enhancement, bugfix - allow RAR DL grants with variable PRB size

Some bug fixes had to be solved:
- the cfi cannot be dynamic once we set a SIB/paging/RAR allocation. This is too avoid effective coderate to exceed its maximum
- the previous bugfix required adding the feature to cancel the last PDCCH+PDSCH allocation
This commit is contained in:
Francisco 2021-03-15 17:13:30 +00:00 committed by Francisco Paisana
parent 47f1175502
commit 1f35c4dc8b
13 changed files with 254 additions and 213 deletions

View File

@ -115,6 +115,8 @@ public:
void reset();
private:
alloc_outcome_t allocate_pending_rar(sf_sched* tti_sched, const pending_rar_t& rar, uint32_t& nof_grants_alloc);
// args
srslog::basic_logger& logger;
const sched_cell_params_t* cc_cfg = nullptr;

View File

@ -106,6 +106,10 @@ struct prb_interval : public srslte::interval<uint32_t> {
/// Type of Allocation stored in PDSCH/PUSCH
enum class alloc_type_t { DL_BC, DL_PCCH, DL_RAR, DL_DATA, UL_DATA };
inline bool is_dl_ctrl_alloc(alloc_type_t a)
{
return a == alloc_type_t::DL_BC or a == alloc_type_t::DL_PCCH or a == alloc_type_t::DL_RAR;
}
} // namespace srsenb

View File

@ -37,7 +37,8 @@ struct alloc_outcome_t {
NO_DATA,
INVALID_PRBMASK,
INVALID_CARRIER,
INVALID_CODERATE
CODERATE_TOO_HIGH,
NOF_ALLOCS_LIMIT
};
result_enum result = ERROR;
alloc_outcome_t() = default;
@ -101,10 +102,11 @@ public:
void init(const sched_cell_params_t& cell_params_);
void new_tti(tti_point tti_rx);
dl_ctrl_alloc_t alloc_dl_ctrl(uint32_t aggr_lvl, alloc_type_t alloc_type);
alloc_outcome_t alloc_dl_ctrl(uint32_t aggr_lvl, rbg_interval rbg_range, alloc_type_t alloc_type);
alloc_outcome_t alloc_dl_data(sched_ue* user, const rbgmask_t& user_mask, bool has_pusch_grant);
bool reserve_dl_rbgs(uint32_t start_rbg, uint32_t end_rbg);
void rem_last_alloc_dl(rbg_interval rbgs);
alloc_outcome_t alloc_ul_data(sched_ue* user, prb_interval alloc, bool needs_pdcch, bool strict = true);
alloc_outcome_t reserve_ul_prbs(const prbmask_t& prbmask, bool strict);
alloc_outcome_t reserve_ul_prbs(prb_interval alloc, bool strict);
@ -127,8 +129,7 @@ private:
// consts
const sched_cell_params_t* cc_cfg = nullptr;
srslog::basic_logger& logger;
uint32_t nof_rbgs = 0;
uint32_t si_n_rbg = 0, rar_n_rbg = 0;
uint32_t nof_rbgs = 0;
uint32_t pucch_nrb = 0;
prbmask_t pucch_mask;
@ -137,9 +138,8 @@ private:
// internal state
tti_point tti_rx;
uint32_t avail_rbg = 0;
rbgmask_t dl_mask = {};
prbmask_t ul_mask = {};
rbgmask_t dl_mask = {};
prbmask_t ul_mask = {};
};
/** Description: Stores the RAR, broadcast, paging, DL data, UL data allocations for the given subframe
@ -157,8 +157,6 @@ public:
struct rar_alloc_t {
sf_sched::ctrl_alloc_t alloc_data;
sched_interface::dl_sched_rar_t rar_grant;
rar_alloc_t(const sf_sched::ctrl_alloc_t& c, const sched_interface::dl_sched_rar_t& r) : alloc_data(c), rar_grant(r)
{}
};
struct bc_alloc_t : public ctrl_alloc_t {
sched_interface::dl_sched_bc_t bc_grant;
@ -198,7 +196,7 @@ public:
// DL alloc methods
alloc_outcome_t alloc_sib(uint32_t aggr_lvl, uint32_t sib_idx, uint32_t sib_ntx, rbg_interval rbgs);
alloc_outcome_t alloc_paging(uint32_t aggr_lvl, uint32_t paging_payload, rbg_interval rbgs);
std::pair<alloc_outcome_t, uint32_t> alloc_rar(uint32_t aggr_lvl, const pending_rar_t& rar_grant);
alloc_outcome_t alloc_rar(uint32_t aggr_lvl, const pending_rar_t& rar_grant, rbg_interval rbgs, uint32_t nof_grants);
bool reserve_dl_rbgs(uint32_t rbg_start, uint32_t rbg_end) { return tti_alloc.reserve_dl_rbgs(rbg_start, rbg_end); }
const std::vector<rar_alloc_t>& get_allocated_rars() const { return rar_allocs; }
@ -228,17 +226,16 @@ public:
const sched_cell_params_t* get_cc_cfg() const { return cc_cfg; }
private:
ctrl_code_t alloc_dl_ctrl(uint32_t aggr_lvl, uint32_t tbs_bytes, uint16_t rnti);
void set_bc_sched_result(const sf_cch_allocator::alloc_result_t& dci_result,
sched_interface::dl_sched_res_t* dl_result);
void set_rar_sched_result(const sf_cch_allocator::alloc_result_t& dci_result,
sched_interface::dl_sched_res_t* dl_result);
void set_dl_data_sched_result(const sf_cch_allocator::alloc_result_t& dci_result,
sched_interface::dl_sched_res_t* dl_result,
sched_ue_list& ue_list);
void set_ul_sched_result(const sf_cch_allocator::alloc_result_t& dci_result,
sched_interface::ul_sched_res_t* ul_result,
sched_ue_list& ue_list);
void set_bc_sched_result(const sf_cch_allocator::alloc_result_t& dci_result,
sched_interface::dl_sched_res_t* dl_result);
void set_rar_sched_result(const sf_cch_allocator::alloc_result_t& dci_result,
sched_interface::dl_sched_res_t* dl_result);
void set_dl_data_sched_result(const sf_cch_allocator::alloc_result_t& dci_result,
sched_interface::dl_sched_res_t* dl_result,
sched_ue_list& ue_list);
void set_ul_sched_result(const sf_cch_allocator::alloc_result_t& dci_result,
sched_interface::ul_sched_res_t* ul_result,
sched_ue_list& ue_list);
// consts
const sched_cell_params_t* cc_cfg = nullptr;

View File

@ -48,6 +48,8 @@ public:
*/
bool alloc_dci(alloc_type_t alloc_type, uint32_t aggr_idx, sched_ue* user = nullptr, bool has_pusch_grant = false);
void rem_last_dci();
// getters
uint32_t get_cfi() const { return current_cfix + 1; }
void get_allocs(alloc_result_t* vec = nullptr, pdcch_mask_t* tot_mask = nullptr, size_t idx = 0) const;
@ -106,7 +108,8 @@ private:
// tti vars
tti_point tti_rx;
uint32_t current_cfix = 0;
uint32_t current_cfix = 0;
uint32_t current_max_cfix = 0;
std::vector<alloc_tree_t> alloc_trees; ///< List of PDCCH alloc trees, where index is the cfi index
std::vector<alloc_record_t> dci_record_list; ///< Keeps a record of all the PDCCH allocations done so far
};

View File

@ -88,67 +88,73 @@ void bc_sched::update_si_windows(sf_sched* tti_sched)
void bc_sched::alloc_sibs(sf_sched* tti_sched)
{
const uint32_t max_nof_prbs_sib = 4;
uint32_t current_sf_idx = tti_sched->get_tti_tx_dl().sf_idx();
uint32_t current_sfn = tti_sched->get_tti_tx_dl().sfn();
uint32_t current_sf_idx = tti_sched->get_tti_tx_dl().sf_idx();
uint32_t current_sfn = tti_sched->get_tti_tx_dl().sfn();
for (uint32_t sib_idx = 0; sib_idx < pending_sibs.size(); sib_idx++) {
sched_sib_t& pending_sib = pending_sibs[sib_idx];
if (cc_cfg->cfg.sibs[sib_idx].len > 0 and pending_sib.is_in_window and pending_sib.n_tx < 4) {
uint32_t nof_tx = (sib_idx > 0) ? SRSLTE_MIN(srslte::ceil_div(cc_cfg->cfg.si_window_ms, 10), 4) : 4;
uint32_t n_sf = (tti_sched->get_tti_tx_dl() - pending_sibs[sib_idx].window_start);
// Check if SIB is configured and within window
if (cc_cfg->cfg.sibs[sib_idx].len == 0 or not pending_sib.is_in_window or pending_sib.n_tx >= 4) {
continue;
}
// Check if there is any SIB to tx
bool sib1_flag = (sib_idx == 0) and (current_sfn % 2) == 0 and current_sf_idx == 5;
bool other_sibs_flag = (sib_idx > 0) and
(n_sf >= (cc_cfg->cfg.si_window_ms / nof_tx) * pending_sibs[sib_idx].n_tx) and
current_sf_idx == 9;
if (not sib1_flag and not other_sibs_flag) {
continue;
}
// Check if subframe index is the correct one for SIB transmission
uint32_t nof_tx = (sib_idx > 0) ? SRSLTE_MIN(srslte::ceil_div(cc_cfg->cfg.si_window_ms, 10), 4) : 4;
uint32_t n_sf = (tti_sched->get_tti_tx_dl() - pending_sibs[sib_idx].window_start);
bool sib1_flag = (sib_idx == 0) and (current_sfn % 2) == 0 and current_sf_idx == 5;
bool other_sibs_flag = (sib_idx > 0) and
(n_sf >= (cc_cfg->cfg.si_window_ms / nof_tx) * pending_sibs[sib_idx].n_tx) and
current_sf_idx == 9;
if (not sib1_flag and not other_sibs_flag) {
continue;
}
// Attempt different number of RBGs
bool success = false;
for (uint32_t nrbgs = 2; nrbgs < 5; ++nrbgs) {
rbg_interval rbg_interv = find_empty_rbg_interval(nrbgs, tti_sched->get_dl_mask());
if (rbg_interv.empty()) {
break;
}
alloc_outcome_t ret = tti_sched->alloc_sib(bc_aggr_level, sib_idx, pending_sibs[sib_idx].n_tx, rbg_interv);
if (ret != alloc_outcome_t::INVALID_CODERATE) {
if (ret == alloc_outcome_t::SUCCESS) {
// SIB scheduled successfully
success = true;
pending_sibs[sib_idx].n_tx++;
}
break;
}
// Attempt again, but with more RBGs
// Attempt PDSCH grants with increasing number of RBGs
alloc_outcome_t ret = alloc_outcome_t::CODERATE_TOO_HIGH;
for (uint32_t nrbgs = 1; nrbgs < cc_cfg->nof_rbgs and ret == alloc_outcome_t::CODERATE_TOO_HIGH; ++nrbgs) {
rbg_interval rbg_interv = find_empty_rbg_interval(nrbgs, tti_sched->get_dl_mask());
if (rbg_interv.length() != nrbgs) {
ret = alloc_outcome_t::RB_COLLISION;
break;
}
if (not success) {
logger.warning("SCHED: Could not allocate SIB=%d, len=%d", sib_idx + 1, cc_cfg->cfg.sibs[sib_idx].len);
ret = tti_sched->alloc_sib(bc_aggr_level, sib_idx, pending_sibs[sib_idx].n_tx, rbg_interv);
if (ret == alloc_outcome_t::SUCCESS) {
// SIB scheduled successfully
pending_sibs[sib_idx].n_tx++;
}
}
if (ret != alloc_outcome_t::SUCCESS) {
logger.warning("SCHED: Could not allocate SIB=%d, len=%d. Cause: %s",
sib_idx + 1,
cc_cfg->cfg.sibs[sib_idx].len,
ret.to_string());
}
}
}
void bc_sched::alloc_paging(sf_sched* tti_sched)
{
uint32_t paging_payload = 0;
if (rrc->is_paging_opportunity(current_tti.to_uint(), &paging_payload) and paging_payload > 0) {
alloc_outcome_t ret = alloc_outcome_t::ERROR;
for (uint32_t nrbgs = 2; nrbgs < 5; ++nrbgs) {
rbg_interval rbg_interv = find_empty_rbg_interval(nrbgs, tti_sched->get_dl_mask());
ret = tti_sched->alloc_paging(bc_aggr_level, paging_payload, rbg_interv);
if (ret == alloc_outcome_t::SUCCESS or ret == alloc_outcome_t::RB_COLLISION) {
break;
}
}
if (ret != alloc_outcome_t::SUCCESS) {
logger.warning(
"SCHED: Could not allocate Paging with payload length=%d, cause=%s", paging_payload, ret.to_string());
// Check if pending Paging message
if (not rrc->is_paging_opportunity(tti_sched->get_tti_tx_dl().to_uint(), &paging_payload) or paging_payload == 0) {
return;
}
alloc_outcome_t ret = alloc_outcome_t::CODERATE_TOO_HIGH;
for (uint32_t nrbgs = 1; nrbgs < cc_cfg->nof_rbgs and ret == alloc_outcome_t::CODERATE_TOO_HIGH; ++nrbgs) {
rbg_interval rbg_interv = find_empty_rbg_interval(nrbgs, tti_sched->get_dl_mask());
if (rbg_interv.length() != nrbgs) {
ret = alloc_outcome_t::RB_COLLISION;
break;
}
ret = tti_sched->alloc_paging(bc_aggr_level, paging_payload, rbg_interv);
}
if (ret != alloc_outcome_t::SUCCESS) {
logger.warning(
"SCHED: Could not allocate Paging with payload length=%d, cause=%s", paging_payload, ret.to_string());
}
}
@ -167,6 +173,32 @@ ra_sched::ra_sched(const sched_cell_params_t& cfg_, sched_ue_list& ue_db_) :
cc_cfg(&cfg_), logger(srslog::fetch_basic_logger("MAC")), ue_db(&ue_db_)
{}
alloc_outcome_t
ra_sched::allocate_pending_rar(sf_sched* tti_sched, const pending_rar_t& rar, uint32_t& nof_grants_alloc)
{
alloc_outcome_t ret = alloc_outcome_t::ERROR;
for (nof_grants_alloc = rar.msg3_grant.size(); nof_grants_alloc > 0; nof_grants_alloc--) {
ret = alloc_outcome_t::CODERATE_TOO_HIGH;
for (uint32_t nrbg = 1; nrbg < cc_cfg->nof_rbgs and ret == alloc_outcome_t::CODERATE_TOO_HIGH; ++nrbg) {
rbg_interval rbg_interv = find_empty_rbg_interval(nrbg, tti_sched->get_dl_mask());
if (rbg_interv.length() == nrbg) {
ret = tti_sched->alloc_rar(rar_aggr_level, rar, rbg_interv, nof_grants_alloc);
} else {
ret = alloc_outcome_t::RB_COLLISION;
}
}
// If allocation was not successful because there were not enough RBGs, try allocating fewer Msg3 grants
if (ret != alloc_outcome_t::CODERATE_TOO_HIGH and ret != alloc_outcome_t::RB_COLLISION) {
break;
}
}
if (ret != alloc_outcome_t::SUCCESS) {
logger.info("SCHED: RAR allocation for L=%d was postponed. Cause=%s", rar_aggr_level, ret.to_string());
}
return ret;
}
// Schedules RAR
// On every call to this function, we schedule the oldest RAR which is still within the window. If outside the window we
// discard it.
@ -192,7 +224,7 @@ void ra_sched::dl_sched(sf_sched* tti_sched)
rar_window,
tti_tx_dl);
srslte::console("%s\n", srslte::to_c_str(str_buffer));
logger.error("%s", srslte::to_c_str(str_buffer));
logger.warning("%s", srslte::to_c_str(str_buffer));
it = pending_rars.erase(it);
continue;
}
@ -200,33 +232,30 @@ void ra_sched::dl_sched(sf_sched* tti_sched)
}
// Try to schedule DCI + RBGs for RAR Grant
std::pair<alloc_outcome_t, uint32_t> ret = tti_sched->alloc_rar(rar_aggr_level, rar);
uint32_t nof_rar_allocs = 0;
alloc_outcome_t ret = allocate_pending_rar(tti_sched, rar, nof_rar_allocs);
if (ret == alloc_outcome_t::SUCCESS) {
// If RAR allocation was successful:
// - in case all Msg3 grants were allocated, remove pending RAR, and continue with following RAR
// - otherwise, erase only Msg3 grants that were allocated, and stop iteration
// If RAR allocation was successful:
// - in case all Msg3 grants were allocated, remove pending RAR
// - otherwise, erase only Msg3 grants that were allocated.
if (ret.first == alloc_outcome_t::SUCCESS) {
uint32_t nof_rar_allocs = ret.second;
if (nof_rar_allocs == rar.msg3_grant.size()) {
pending_rars.erase(it);
it = pending_rars.erase(it);
} else {
std::copy(rar.msg3_grant.begin() + nof_rar_allocs, rar.msg3_grant.end(), rar.msg3_grant.begin());
rar.msg3_grant.resize(rar.msg3_grant.size() - nof_rar_allocs);
break;
}
break;
} else {
// If RAR allocation was not successful:
// - in case of unavailable PDCCH space, try next pending RAR allocation
// - otherwise, stop iteration
if (ret != alloc_outcome_t::DCI_COLLISION) {
break;
}
++it;
}
// If RAR allocation was not successful:
// - in case of unavailable RBGs, stop loop
// - otherwise, attempt to schedule next pending RAR
logger.info("SCHED: Could not allocate RAR for L=%d, cause=%s", rar_aggr_level, ret.first.to_string());
if (ret.first == alloc_outcome_t::RB_COLLISION) {
// there are not enough RBs for RAR or Msg3 allocation. We can skip this TTI
return;
}
// For any other type of error, continue with next pending RAR
++it;
}
}

View File

@ -22,7 +22,7 @@ const char* alloc_outcome_t::to_string() const
case SUCCESS:
return "success";
case DCI_COLLISION:
return "dci_collision";
return "PDCCH position not available";
case RB_COLLISION:
return "rb_collision";
case ERROR:
@ -41,6 +41,10 @@ const char* alloc_outcome_t::to_string() const
return "invalid rbg mask";
case INVALID_CARRIER:
return "invalid eNB carrier";
case CODERATE_TOO_HIGH:
return "Effective coderate is too high";
case NOF_ALLOCS_LIMIT:
return "Max number of allocations reached";
default:
break;
}
@ -116,10 +120,8 @@ cc_sched_result* sched_result_list::get_cc(srslte::tti_point tti_rx, uint32_t en
void sf_grid_t::init(const sched_cell_params_t& cell_params_)
{
cc_cfg = &cell_params_;
nof_rbgs = cc_cfg->nof_rbgs;
si_n_rbg = srslte::ceil_div(4, cc_cfg->P);
rar_n_rbg = srslte::ceil_div(3, cc_cfg->P);
cc_cfg = &cell_params_;
nof_rbgs = cc_cfg->nof_rbgs;
dl_mask.resize(nof_rbgs);
ul_mask.resize(cc_cfg->nof_prb());
@ -144,7 +146,6 @@ void sf_grid_t::new_tti(tti_point tti_rx_)
dl_mask.reset();
ul_mask.reset();
avail_rbg = nof_rbgs;
// Reserve PRBs for PUCCH
ul_mask |= pucch_mask;
@ -181,7 +182,7 @@ alloc_outcome_t sf_grid_t::alloc_dl(uint32_t aggr_idx,
if (not pdcch_alloc.alloc_dci(alloc_type, aggr_idx, user, has_pusch_grant)) {
if (user != nullptr) {
if (logger.debug.enabled()) {
logger.debug("No space in PDCCH for rnti=0x%x DL tx. Current PDCCH allocation: %s",
logger.debug("No space in PDCCH for rnti=0x%x DL tx. Current PDCCH allocation:\n%s",
user->get_rnti(),
pdcch_alloc.result_to_string(true).c_str());
}
@ -191,20 +192,11 @@ alloc_outcome_t sf_grid_t::alloc_dl(uint32_t aggr_idx,
// Allocate RBGs
dl_mask |= alloc_mask;
avail_rbg -= alloc_mask.count();
return alloc_outcome_t::SUCCESS;
}
//! Allocates CCEs and RBs for control allocs. It allocates RBs in a contiguous manner.
sf_grid_t::dl_ctrl_alloc_t sf_grid_t::alloc_dl_ctrl(uint32_t aggr_idx, alloc_type_t alloc_type)
{
rbg_interval range{nof_rbgs - avail_rbg,
nof_rbgs - avail_rbg + ((alloc_type == alloc_type_t::DL_RAR) ? rar_n_rbg : si_n_rbg)};
return {alloc_dl_ctrl(aggr_idx, range, alloc_type), range};
}
/// Allocates CCEs and RBs for control allocs. It allocates RBs in a contiguous manner.
alloc_outcome_t sf_grid_t::alloc_dl_ctrl(uint32_t aggr_idx, rbg_interval rbg_range, alloc_type_t alloc_type)
{
if (alloc_type != alloc_type_t::DL_RAR and alloc_type != alloc_type_t::DL_BC and
@ -252,7 +244,7 @@ alloc_outcome_t sf_grid_t::alloc_ul_data(sched_ue* user, prb_interval alloc, boo
uint32_t aggr_idx = user->get_aggr_level(cc_cfg->enb_cc_idx, nof_bits);
if (not pdcch_alloc.alloc_dci(alloc_type_t::UL_DATA, aggr_idx, user)) {
if (logger.debug.enabled()) {
logger.debug("No space in PDCCH for rnti=0x%x UL tx. Current PDCCH allocation: %s",
logger.debug("No space in PDCCH for rnti=0x%x UL tx. Current PDCCH allocation:\n%s",
user->get_rnti(),
pdcch_alloc.result_to_string(true).c_str());
}
@ -271,6 +263,19 @@ bool sf_grid_t::reserve_dl_rbgs(uint32_t start_rbg, uint32_t end_rbg)
return true;
}
void sf_grid_t::rem_last_alloc_dl(rbg_interval rbgs)
{
if (pdcch_alloc.nof_allocs() == 0) {
logger.error("Remove DL alloc called for empty Subframe RB grid");
return;
}
pdcch_alloc.rem_last_dci();
rbgmask_t rbgmask(dl_mask.size());
rbgmask.fill(rbgs.start(), rbgs.stop());
dl_mask &= ~rbgmask;
}
alloc_outcome_t sf_grid_t::reserve_ul_prbs(prb_interval alloc, bool strict)
{
if (alloc.stop() > ul_mask.size()) {
@ -365,69 +370,36 @@ void sf_sched::new_tti(tti_point tti_rx_, sf_sched_result* cc_results_)
bool sf_sched::is_dl_alloc(uint16_t rnti) const
{
for (const auto& a : data_allocs) {
if (a.rnti == rnti) {
return true;
}
}
return false;
return std::any_of(data_allocs.begin(), data_allocs.end(), [rnti](const dl_alloc_t& u) { return u.rnti == rnti; });
}
bool sf_sched::is_ul_alloc(uint16_t rnti) const
{
for (const auto& a : ul_data_allocs) {
if (a.rnti == rnti) {
return true;
}
}
return false;
}
sf_sched::ctrl_code_t sf_sched::alloc_dl_ctrl(uint32_t aggr_lvl, uint32_t tbs_bytes, uint16_t rnti)
{
ctrl_alloc_t ctrl_alloc{};
// based on rnti, check which type of alloc
alloc_type_t alloc_type = alloc_type_t::DL_RAR;
if (rnti == SRSLTE_SIRNTI) {
alloc_type = alloc_type_t::DL_BC;
} else if (rnti == SRSLTE_PRNTI) {
alloc_type = alloc_type_t::DL_PCCH;
}
/* Allocate space in the DL RBG and PDCCH grids */
sf_grid_t::dl_ctrl_alloc_t ret = tti_alloc.alloc_dl_ctrl(aggr_lvl, alloc_type);
if (not ret.outcome) {
return {ret.outcome, ctrl_alloc};
}
// Allocation Successful
ctrl_alloc.dci_idx = tti_alloc.get_pdcch_grid().nof_allocs() - 1;
ctrl_alloc.rbg_range = ret.rbg_range;
ctrl_alloc.req_bytes = tbs_bytes;
return {ret.outcome, ctrl_alloc};
return std::any_of(
ul_data_allocs.begin(), ul_data_allocs.end(), [rnti](const ul_alloc_t& u) { return u.rnti == rnti; });
}
alloc_outcome_t sf_sched::alloc_sib(uint32_t aggr_lvl, uint32_t sib_idx, uint32_t sib_ntx, rbg_interval rbgs)
{
if (bc_allocs.size() >= sched_interface::MAX_BC_LIST) {
logger.warning("SCHED: Maximum number of Broadcast allocations reached");
return alloc_outcome_t::ERROR;
return alloc_outcome_t::NOF_ALLOCS_LIMIT;
}
bc_alloc_t bc_alloc;
// Generate DCI for SIB
if (not generate_sib_dci(bc_alloc.bc_grant, get_tti_tx_dl(), sib_idx, sib_ntx, rbgs, *cc_cfg, tti_alloc.get_cfi())) {
return alloc_outcome_t::INVALID_CODERATE;
}
// Allocate SIB RBGs and PDCCH
alloc_outcome_t ret = tti_alloc.alloc_dl_ctrl(aggr_lvl, rbgs, alloc_type_t::DL_BC);
if (ret != alloc_outcome_t::SUCCESS) {
return ret;
}
// Generate DCI for SIB
if (not generate_sib_dci(bc_alloc.bc_grant, get_tti_tx_dl(), sib_idx, sib_ntx, rbgs, *cc_cfg, tti_alloc.get_cfi())) {
// Cancel on-going allocation
tti_alloc.rem_last_alloc_dl(rbgs);
return alloc_outcome_t::CODERATE_TOO_HIGH;
}
// Allocation Successful
bc_alloc.dci_idx = tti_alloc.get_pdcch_grid().nof_allocs() - 1;
bc_alloc.rbg_range = rbgs;
@ -441,21 +413,23 @@ alloc_outcome_t sf_sched::alloc_paging(uint32_t aggr_lvl, uint32_t paging_payloa
{
if (bc_allocs.size() >= sched_interface::MAX_BC_LIST) {
logger.warning("SCHED: Maximum number of Broadcast allocations reached");
return alloc_outcome_t::ERROR;
return alloc_outcome_t::NOF_ALLOCS_LIMIT;
}
bc_alloc_t bc_alloc;
// Generate DCI for Paging message
if (not generate_paging_dci(bc_alloc.bc_grant, get_tti_tx_dl(), paging_payload, rbgs, *cc_cfg, tti_alloc.get_cfi())) {
return alloc_outcome_t::INVALID_CODERATE;
}
// Allocate Paging RBGs and PDCCH
alloc_outcome_t ret = tti_alloc.alloc_dl_ctrl(aggr_lvl, rbgs, alloc_type_t::DL_PCCH);
if (ret != alloc_outcome_t::SUCCESS) {
return ret;
}
// Generate DCI for Paging message
if (not generate_paging_dci(bc_alloc.bc_grant, get_tti_tx_dl(), paging_payload, rbgs, *cc_cfg, tti_alloc.get_cfi())) {
// Cancel on-going allocation
tti_alloc.rem_last_alloc_dl(rbgs);
return alloc_outcome_t::CODERATE_TOO_HIGH;
}
// Allocation Successful
bc_alloc.dci_idx = tti_alloc.get_pdcch_grid().nof_allocs() - 1;
bc_alloc.rbg_range = rbgs;
@ -465,53 +439,44 @@ alloc_outcome_t sf_sched::alloc_paging(uint32_t aggr_lvl, uint32_t paging_payloa
return alloc_outcome_t::SUCCESS;
}
std::pair<alloc_outcome_t, uint32_t> sf_sched::alloc_rar(uint32_t aggr_lvl, const pending_rar_t& rar)
alloc_outcome_t sf_sched::alloc_rar(uint32_t aggr_lvl, const pending_rar_t& rar, rbg_interval rbgs, uint32_t nof_grants)
{
const uint32_t msg3_grant_size = 3;
std::pair<alloc_outcome_t, uint32_t> ret = {alloc_outcome_t::ERROR, 0};
static const uint32_t msg3_nof_prbs = 3;
if (rar_allocs.size() >= sched_interface::MAX_RAR_LIST) {
logger.warning("SCHED: Maximum number of RAR allocations per TTI reached.");
logger.info("SCHED: Maximum number of RAR allocations per TTI reached.");
return alloc_outcome_t::NOF_ALLOCS_LIMIT;
}
uint32_t buf_rar = 7 * nof_grants + 1; // 1+6 bytes per RAR subheader+body and 1 byte for Backoff
uint32_t total_ul_nof_prbs = msg3_nof_prbs * nof_grants;
// check if there is enough space for Msg3
if (last_msg3_prb + total_ul_nof_prbs > max_msg3_prb) {
return alloc_outcome_t::RB_COLLISION;
}
// allocate RBGs and PDCCH
alloc_outcome_t ret = tti_alloc.alloc_dl_ctrl(aggr_lvl, rbgs, alloc_type_t::DL_RAR);
if (ret != alloc_outcome_t::SUCCESS) {
return ret;
}
for (uint32_t nof_grants = rar.msg3_grant.size(); nof_grants > 0; nof_grants--) {
uint32_t buf_rar = 7 * nof_grants + 1; // 1+6 bytes per RAR subheader+body and 1 byte for Backoff
uint32_t total_msg3_size = msg3_grant_size * nof_grants;
// check if there is enough space for Msg3, try again with a lower number of grants
if (last_msg3_prb + total_msg3_size > max_msg3_prb) {
ret.first = alloc_outcome_t::RB_COLLISION;
continue;
}
// allocate RBs and PDCCH
sf_sched::ctrl_code_t ret2 = alloc_dl_ctrl(aggr_lvl, buf_rar, rar.ra_rnti);
ret.first = ret2.first.result;
ret.second = nof_grants;
if (ret.first == alloc_outcome_t::SUCCESS) {
sched_interface::dl_sched_rar_t rar_grant;
if (generate_rar_dci(rar_grant,
get_tti_tx_dl(),
rar,
ret2.second.rbg_range,
nof_grants,
last_msg3_prb,
*cc_cfg,
tti_alloc.get_cfi())) {
// RAR allocation successful
rar_allocs.emplace_back(ret2.second, rar_grant);
last_msg3_prb += msg3_grant_size * nof_grants;
return ret;
}
} else if (ret.first != alloc_outcome_t::RB_COLLISION) {
return ret;
}
// if there was no space for the RAR, try again with a lower number of grants
// Generate DCI for RAR
rar_alloc_t rar_alloc;
if (not generate_rar_dci(
rar_alloc.rar_grant, get_tti_tx_dl(), rar, rbgs, nof_grants, last_msg3_prb, *cc_cfg, tti_alloc.get_cfi())) {
// Cancel on-going allocation
tti_alloc.rem_last_alloc_dl(rbgs);
return alloc_outcome_t::CODERATE_TOO_HIGH;
}
logger.info("SCHED: RAR allocation postponed due to lack of RBs");
// RAR allocation successful
rar_alloc.alloc_data.dci_idx = tti_alloc.get_pdcch_grid().nof_allocs() - 1;
rar_alloc.alloc_data.rbg_range = rbgs;
rar_alloc.alloc_data.req_bytes = buf_rar;
rar_allocs.push_back(rar_alloc);
last_msg3_prb += total_ul_nof_prbs * nof_grants;
return ret;
}
@ -531,7 +496,7 @@ alloc_outcome_t sf_sched::alloc_dl_user(sched_ue* user, const rbgmask_t& user_ma
{
if (data_allocs.size() >= sched_interface::MAX_DATA_LIST) {
logger.warning("SCHED: Maximum number of DL allocations reached");
return alloc_outcome_t::ERROR;
return alloc_outcome_t::NOF_ALLOCS_LIMIT;
}
if (is_dl_alloc(user->get_rnti())) {

View File

@ -319,8 +319,9 @@ void log_broadcast_allocation(const sched_interface::dl_sched_bc_t& bc,
fmt::format_to(str_buffer, "{}", rbg_range);
if (bc.type == sched_interface::dl_sched_bc_t::bc_type::BCCH) {
logger.debug("SCHED: SIB%d, rbgs=(%d,%d), dci=(%d,%d), rv=%d, len=%d, period=%d, mcs=%d",
logger.debug("SCHED: SIB%d, cc=%d, rbgs=(%d,%d), dci=(%d,%d), rv=%d, len=%d, period=%d, mcs=%d",
bc.index + 1,
cell_params.enb_cc_idx,
rbg_range.start(),
rbg_range.stop(),
bc.dci.location.L,
@ -330,8 +331,9 @@ void log_broadcast_allocation(const sched_interface::dl_sched_bc_t& bc,
cell_params.cfg.sibs[bc.index].period_rf,
bc.dci.tb[0].mcs_idx);
} else {
logger.info("SCHED: PCH, rbgs=%s, dci=(%d,%d), tbs=%d, mcs=%d",
logger.info("SCHED: PCH, cc=%d, rbgs=%s, dci=(%d,%d), tbs=%d, mcs=%d",
srslte::to_c_str(str_buffer),
cell_params.enb_cc_idx,
bc.dci.location.L,
bc.dci.location.ncce,
bc.tbs,

View File

@ -37,7 +37,8 @@ void sf_cch_allocator::new_tti(tti_point tti_rx_)
t.reset();
}
dci_record_list.clear();
current_cfix = cc_cfg->sched_cfg->min_nof_ctrl_symbols - 1;
current_cfix = cc_cfg->sched_cfg->min_nof_ctrl_symbols - 1;
current_max_cfix = cc_cfg->sched_cfg->max_nof_ctrl_symbols - 1;
}
const cce_cfi_position_table*
@ -70,7 +71,7 @@ bool sf_cch_allocator::alloc_dci(alloc_type_t alloc_type, uint32_t aggr_idx, sch
bool success;
do {
success = alloc_dci_record(record, get_cfi() - 1);
} while (not success and get_cfi() < cc_cfg->sched_cfg->max_nof_ctrl_symbols and set_cfi(get_cfi() + 1));
} while (not success and current_cfix < current_max_cfix and set_cfi(get_cfi() + 1));
if (not success) {
// DCI allocation failed. go back to original CFI
@ -82,9 +83,45 @@ bool sf_cch_allocator::alloc_dci(alloc_type_t alloc_type, uint32_t aggr_idx, sch
// DCI record allocation successful
dci_record_list.push_back(record);
if (is_dl_ctrl_alloc(alloc_type)) {
// Dynamic CFI not yet supported for DL control allocations, as coderate can be exceeded
current_max_cfix = current_cfix;
}
return true;
}
void sf_cch_allocator::rem_last_dci()
{
assert(not dci_record_list.empty());
// Remove DCI record
dci_record_list.pop_back();
// Remove leaves of PDCCH position decisions
auto& tree = alloc_trees[current_cfix];
tree.prev_end = tree.prev_start;
if (dci_record_list.empty()) {
tree.prev_start = 0;
} else {
tree.prev_start = tree.dci_alloc_tree[tree.prev_start].parent_idx;
// Discover other tree nodes with same level
while (tree.prev_start > 0) {
uint32_t count = 0;
while (tree.dci_alloc_tree[tree.prev_start - 1].parent_idx >= 0) {
count++;
}
if (count == dci_record_list.size()) {
tree.prev_start--;
} else {
break;
}
}
}
tree.dci_alloc_tree.erase(tree.dci_alloc_tree.begin() + tree.prev_end, tree.dci_alloc_tree.end());
}
bool sf_cch_allocator::alloc_dci_record(const alloc_record_t& record, uint32_t cfix)
{
bool ret = false;

View File

@ -145,7 +145,7 @@ uint32_t sched_time_pf::try_ul_alloc(ue_ctxt& ue_ctxt, sched_ue& ue, sf_sched* t
: 0;
}
if (code == alloc_outcome_t::DCI_COLLISION) {
logger.info("SCHED: Couldn't find space in PDCCH for UL retx of rnti=0x%x", ue.get_rnti());
logger.info("SCHED: rnti=0x%x, cc=%d, Couldn't find space in PDCCH for UL tx", ue.get_rnti(), cc_cfg->enb_cc_idx);
}
return estim_tbs_bytes;
}

View File

@ -142,7 +142,8 @@ void sched_time_rr::sched_ul_newtxs(sched_ue_list& ue_db, sf_sched* tti_sched, s
}
alloc_outcome_t ret = tti_sched->alloc_ul_user(&user, alloc);
if (ret == alloc_outcome_t::DCI_COLLISION) {
logger.info("SCHED: Couldn't find space in PDCCH for UL tx of rnti=0x%x", user.get_rnti());
logger.info(
"SCHED: rnti=0x%x, cc=%d, Couldn't find space in PDCCH for UL tx", user.get_rnti(), cc_cfg->enb_cc_idx);
}
}
}

View File

@ -17,7 +17,7 @@
using namespace srsenb;
uint32_t const seed = std::chrono::system_clock::now().time_since_epoch().count();
uint32_t seed = std::chrono::system_clock::now().time_since_epoch().count();
/*******************
* Logging *
@ -157,7 +157,7 @@ int test_scell_activation(uint32_t sim_number, test_scell_activation_params para
}
};
generate_data(20, 1.0, P_ul_sr, randf());
tester.test_next_ttis(generator.tti_events);
TESTASSERT(tester.test_next_ttis(generator.tti_events) == SRSLTE_SUCCESS);
// Event: Reconf Complete. Activate SCells. Check if CE correctly transmitted
generator.step_tti();
@ -169,7 +169,7 @@ int test_scell_activation(uint32_t sim_number, test_scell_activation_params para
user->ue_sim_cfg->ue_cfg.supported_cc_list[i].active = true;
user->ue_sim_cfg->ue_cfg.supported_cc_list[i].enb_cc_idx = cc_idxs[i];
}
tester.test_next_ttis(generator.tti_events);
TESTASSERT(tester.test_next_ttis(generator.tti_events) == SRSLTE_SUCCESS);
auto activ_list = tester.get_enb_ue_cc_map(rnti1);
for (uint32_t i = 0; i < cc_idxs.size(); ++i) {
TESTASSERT(activ_list[i] >= 0);
@ -187,7 +187,7 @@ int test_scell_activation(uint32_t sim_number, test_scell_activation_params para
}
}
generator.step_tti();
tester.test_next_ttis(generator.tti_events);
TESTASSERT(tester.test_next_ttis(generator.tti_events) == SRSLTE_SUCCESS);
}
// Event: Wait for UE to receive and ack CE. Send cqi==0, which should not activate the SCell
@ -198,12 +198,12 @@ int test_scell_activation(uint32_t sim_number, test_scell_activation_params para
generator.step_tti();
}
}
tester.test_next_ttis(generator.tti_events);
TESTASSERT(tester.test_next_ttis(generator.tti_events) == SRSLTE_SUCCESS);
// The UE should now have received the CE
// Event: Generate a bit more data, it should *not* go through SCells until we send a CQI
generate_data(5, P_dl, P_ul_sr, randf());
tester.test_next_ttis(generator.tti_events);
TESTASSERT(tester.test_next_ttis(generator.tti_events) == SRSLTE_SUCCESS);
TESTASSERT(tester.sched_stats->users[rnti1].tot_dl_sched_data[params.pcell_idx] > 0);
TESTASSERT(tester.sched_stats->users[rnti1].tot_ul_sched_data[params.pcell_idx] > 0);
for (uint32_t i = 1; i < cc_idxs.size(); ++i) {
@ -217,7 +217,7 @@ int test_scell_activation(uint32_t sim_number, test_scell_activation_params para
tester.dl_cqi_info(tester.tti_rx.to_uint(), rnti1, cc_idxs[i], cqi);
}
generate_data(10, 1.0, 1.0, 1.0);
tester.test_next_ttis(generator.tti_events);
TESTASSERT(tester.test_next_ttis(generator.tti_events) == SRSLTE_SUCCESS);
uint64_t tot_dl_sched_data = 0;
uint64_t tot_ul_sched_data = 0;
for (const auto& c : cc_idxs) {

View File

@ -316,7 +316,8 @@ int test_dci_content_common(const sf_output_res_t& sf_out, uint32_t enb_cc_idx)
uint32_t nof_re = srslte_ra_dl_grant_nof_re(&cell_params.cfg.cell, &dl_sf, &grant);
float coderate = srslte_coderate(tbs * 8, nof_re);
const uint32_t Qm = 2;
CONDERROR(coderate > 0.930f * Qm, "Max coderate was exceeded from broadcast DCI");
CONDERROR(
coderate > 0.930f * Qm, "Max coderate was exceeded from %s DCI", dci.rnti == SRSLTE_SIRNTI ? "SIB" : "RAR");
return SRSLTE_SUCCESS;
};

View File

@ -78,7 +78,7 @@ int test_pdsch_grant(const sim_enb_ctxt_t& enb_ctxt,
uint32_t nof_retx = get_nof_retx(pdsch.dci.tb[0].rv); // 0..3
if (h.nof_txs == 0 or h.ndi != pdsch.dci.tb[0].ndi) {
// It is newtx
CONDERROR(nof_retx != 0, "Invalid rv index for new tx");
CONDERROR(nof_retx != 0, "Invalid rv index for new DL tx");
CONDERROR(h.active, "DL newtx for already active DL harq pid=%d", h.pid);
} else {
// it is retx
@ -196,7 +196,7 @@ int test_ul_sched_result(const sim_enb_ctxt_t& enb_ctxt, const sf_output_res_t&
if (h.nof_txs == 0 or h.ndi != pusch_ptr->dci.tb.ndi) {
// newtx
CONDERROR(nof_retx != 0, "Invalid rv index for new tx");
CONDERROR(nof_retx != 0, "Invalid rv index for new UL tx");
CONDERROR(pusch_ptr->current_tx_nb != 0, "UL HARQ retxs need to have been previously transmitted");
CONDERROR(not h_inactive, "New tx for already active UL HARQ");
CONDERROR(not pusch_ptr->needs_pdcch and ue.msg3_tti_rx.is_valid() and sf_out.tti_rx > ue.msg3_tti_rx,