nr,gnb,sched: extend PDCCH allocator test to cover most allocation fail paths

master
Francisco 3 years ago committed by Francisco Paisana
parent 2e70256548
commit 20b327c320

@ -13,6 +13,7 @@
#ifndef SRSRAN_SCHED_NR_PDCCH_H
#define SRSRAN_SCHED_NR_PDCCH_H
#include "srsenb/hdr/stack/mac/sched_common.h"
#include "srsgnb/hdr/stack/mac/sched_nr_cfg.h"
#include "srsran/adt/bounded_bitset.h"
#include "srsran/adt/bounded_vector.h"
@ -83,6 +84,9 @@ private:
bool get_next_dfs();
};
using pdcch_dl_alloc_result = srsran::expected<pdcch_dl_t*, alloc_result>;
using pdcch_ul_alloc_result = srsran::expected<pdcch_ul_t*, alloc_result>;
/**
* Class to handle the allocation of REs for a BWP PDCCH in a specific slot
*/
@ -106,7 +110,7 @@ public:
* @param aggr_idx Aggregation level index (0..4)
* @return PDCCH object with dci context filled if the allocation was successful. nullptr otherwise
*/
pdcch_dl_t* alloc_rar_pdcch(uint16_t ra_rnti, uint32_t aggr_idx);
pdcch_dl_alloc_result alloc_rar_pdcch(uint16_t ra_rnti, uint32_t aggr_idx);
/**
* Allocates RE space for SI DCI in PDCCH, avoiding in the process collisions with other PDCCH allocations
@ -115,7 +119,7 @@ public:
* @param aggr_idx Aggregation level index (0..4)
* @return PDCCH object with dci context filled if the allocation was successful. nullptr otherwise
*/
pdcch_dl_t* alloc_si_pdcch(uint32_t ss_id, uint32_t aggr_idx);
pdcch_dl_alloc_result alloc_si_pdcch(uint32_t ss_id, uint32_t aggr_idx);
/**
* Allocates RE space for UE DL DCI in PDCCH, avoiding in the process collisions with other PDCCH allocations
@ -126,18 +130,18 @@ public:
* @param user UE object parameters
* @return PDCCH object with dci context filled if the allocation was successful. nullptr otherwise
*/
pdcch_dl_t*
pdcch_dl_alloc_result
alloc_dl_pdcch(srsran_rnti_type_t rnti_type, uint32_t ss_id, uint32_t aggr_idx, const ue_carrier_params_t& user);
/**
* Allocates RE space for UL DCI in PDCCH, avoiding in the process collisions with other PDCCH allocations
* @brief Allocates RE space for UL DCI in PDCCH, avoiding in the process collisions with other PDCCH allocations
* Fills DCI context with PDCCH allocation information
* @param ss_id Search space ID
* @param aggr_idx Aggregation level index (0..4)
* @param user UE object parameters
* @return PDCCH object with dci context filled if the allocation was successful. nullptr otherwise
*/
pdcch_ul_t* alloc_ul_pdcch(uint32_t ss_id, uint32_t aggr_idx, const ue_carrier_params_t& user);
pdcch_ul_alloc_result alloc_ul_pdcch(uint32_t ss_id, uint32_t aggr_idx, const ue_carrier_params_t& user);
/**
* Cancel and remove last PDCCH allocation. It should only be called once after each alloc_dl_pdcch/alloc_ul_pdcch
@ -156,21 +160,21 @@ public:
private:
using slot_coreset_list = srsran::optional_array<coreset_region, SRSRAN_UE_DL_NR_MAX_NOF_CORESET>;
pdcch_dl_t* alloc_dl_pdcch_common(srsran_rnti_type_t rnti_type,
uint16_t rnti,
uint32_t ss_id,
uint32_t aggr_idx,
srsran_dci_format_nr_t dci_fmt,
const ue_carrier_params_t* user = nullptr);
pdcch_dl_alloc_result alloc_dl_pdcch_common(srsran_rnti_type_t rnti_type,
uint16_t rnti,
uint32_t ss_id,
uint32_t aggr_idx,
srsran_dci_format_nr_t dci_fmt,
const ue_carrier_params_t* user = nullptr);
/// Helper function to verify valid inputs
bool check_args_valid(srsran_rnti_type_t rnti_type,
uint16_t rnti,
uint32_t ss_id,
uint32_t aggr_idx,
srsran_dci_format_nr_t dci_fmt,
const ue_carrier_params_t* user,
bool is_dl) const;
alloc_result check_args_valid(srsran_rnti_type_t rnti_type,
uint16_t rnti,
uint32_t ss_id,
uint32_t aggr_idx,
srsran_dci_format_nr_t dci_fmt,
const ue_carrier_params_t* user,
bool is_dl) const;
/// Fill DCI context of allocated PDCCH
void fill_dci_ctx_common(srsran_dci_ctx_t& dci,

@ -130,12 +130,13 @@ alloc_result bwp_slot_allocator::alloc_si(uint32_t aggr_idx,
return alloc_result::sch_collision;
}
const uint32_t ss_id = 0;
pdcch_dl_t* pdcch = bwp_pdcch_slot.pdcchs.alloc_si_pdcch(ss_id, aggr_idx);
if (pdcch == nullptr) {
const uint32_t ss_id = 0;
auto pdcch_result = bwp_pdcch_slot.pdcchs.alloc_si_pdcch(ss_id, aggr_idx);
if (pdcch_result.is_error()) {
logger.warning("SCHED: Cannot allocate SIB1 due to lack of PDCCH space.");
return alloc_result::no_cch_space;
return pdcch_result.error();
}
pdcch_dl_t* pdcch = pdcch_result.value();
// RAR allocation successful.
bwp_pdcch_slot.dl_prbs |= prbs;
@ -220,12 +221,13 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t
}
// Find PDCCH position
pdcch_dl_t* pdcch = bwp_pdcch_slot.pdcchs.alloc_rar_pdcch(ra_rnti, aggr_idx);
if (pdcch == nullptr) {
auto pdcch_result = bwp_pdcch_slot.pdcchs.alloc_rar_pdcch(ra_rnti, aggr_idx);
if (pdcch_result.is_error()) {
// Could not find space in PDCCH
logger.debug("SCHED: No space in PDCCH for DL tx.");
return alloc_result::no_cch_space;
return pdcch_result.error();
}
pdcch_dl_t* pdcch = pdcch_result.value();
// RAR allocation successful.
bwp_pdcch_slot.dl_prbs |= interv;
@ -322,12 +324,12 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, prb_grant dl_grant)
const srsran_search_space_t& ss = *ss_candidates[0];
// Find space and allocate PDCCH
pdcch_dl_t* pdcch = bwp_pdcch_slot.pdcchs.alloc_dl_pdcch(rnti_type, ss.id, aggr_idx, ue.cfg());
if (pdcch == nullptr) {
auto pdcch_result = bwp_pdcch_slot.pdcchs.alloc_dl_pdcch(rnti_type, ss.id, aggr_idx, ue.cfg());
if (pdcch_result.is_error()) {
// Could not find space in PDCCH
logger.debug("Could not find PDCCH space for rnti=0x%x PDSCH allocation", ue->rnti);
return alloc_result::no_cch_space;
return pdcch_result.error();
}
pdcch_dl_t* pdcch = pdcch_result.value();
// Update PRB grant based on the start and end of CORESET RBs
reduce_to_dl_coreset_bw(cfg, ss.id, srsran_dci_format_nr_1_0, dl_grant);
@ -428,12 +430,13 @@ alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, prb_grant ul_grant)
}
const srsran_search_space_t& ss = *ss_candidates[0];
pdcch_ul_t* pdcch = bwp_pdcch_slot.pdcchs.alloc_ul_pdcch(ss.id, aggr_idx, ue.cfg());
if (pdcch == nullptr) {
auto pdcch_result = bwp_pdcch_slot.pdcchs.alloc_ul_pdcch(ss.id, aggr_idx, ue.cfg());
if (pdcch_result.is_error()) {
// Could not find space in PDCCH
logger.debug("Could not find PDCCH space for rnti=0x%x PUSCH allocation", ue->rnti);
return alloc_result::no_cch_space;
return pdcch_result.error();
}
pdcch_ul_t* pdcch = pdcch_result.value();
// Allocation Successful

@ -191,7 +191,7 @@ srsran::span<const uint32_t> coreset_region::get_cce_loc_table(const alloc_recor
void coreset_region::print_allocations(fmt::memory_buffer& fmtbuf) const
{
if (not dci_list.empty()) {
fmt::format_to(fmtbuf, "CORESET#{}:\n", coreset_id);
fmt::format_to(fmtbuf, "CORESET#{} (#CCEs={}):\n", coreset_id, nof_cces());
}
for (const alloc_record& dci : dci_list) {
fmt::format_to(fmtbuf,
@ -236,22 +236,22 @@ void bwp_pdcch_allocator::fill_dci_ctx_common(srsran_dci_ctx_t& dci,
dci.format = dci_fmt;
}
pdcch_dl_t* bwp_pdcch_allocator::alloc_rar_pdcch(uint16_t ra_rnti, uint32_t aggr_idx)
pdcch_dl_alloc_result bwp_pdcch_allocator::alloc_rar_pdcch(uint16_t ra_rnti, uint32_t aggr_idx)
{
srsran_assert(bwp_cfg.cfg.pdcch.ra_search_space_present, "Allocating RAR PDCCH in BWP without RA SearchSpace");
return alloc_dl_pdcch_common(
srsran_rnti_type_ra, ra_rnti, bwp_cfg.cfg.pdcch.ra_search_space.id, aggr_idx, srsran_dci_format_nr_1_0, nullptr);
}
pdcch_dl_t* bwp_pdcch_allocator::alloc_si_pdcch(uint32_t ss_id, uint32_t aggr_idx)
pdcch_dl_alloc_result bwp_pdcch_allocator::alloc_si_pdcch(uint32_t ss_id, uint32_t aggr_idx)
{
return alloc_dl_pdcch_common(srsran_rnti_type_si, SRSRAN_SIRNTI, ss_id, aggr_idx, srsran_dci_format_nr_1_0, nullptr);
}
pdcch_dl_t* bwp_pdcch_allocator::alloc_dl_pdcch(srsran_rnti_type_t rnti_type,
uint32_t ss_id,
uint32_t aggr_idx,
const ue_carrier_params_t& user)
pdcch_dl_alloc_result bwp_pdcch_allocator::alloc_dl_pdcch(srsran_rnti_type_t rnti_type,
uint32_t ss_id,
uint32_t aggr_idx,
const ue_carrier_params_t& user)
{
static const srsran_dci_format_nr_t dci_fmt = srsran_dci_format_nr_1_0; // TODO: make it configurable
srsran_assert(rnti_type == srsran_rnti_type_c or rnti_type == srsran_rnti_type_tc,
@ -260,15 +260,16 @@ pdcch_dl_t* bwp_pdcch_allocator::alloc_dl_pdcch(srsran_rnti_type_t rnti_
return alloc_dl_pdcch_common(rnti_type, user.rnti, ss_id, aggr_idx, dci_fmt, &user);
}
pdcch_dl_t* bwp_pdcch_allocator::alloc_dl_pdcch_common(srsran_rnti_type_t rnti_type,
uint16_t rnti,
uint32_t ss_id,
uint32_t aggr_idx,
srsran_dci_format_nr_t dci_fmt,
const ue_carrier_params_t* user)
pdcch_dl_alloc_result bwp_pdcch_allocator::alloc_dl_pdcch_common(srsran_rnti_type_t rnti_type,
uint16_t rnti,
uint32_t ss_id,
uint32_t aggr_idx,
srsran_dci_format_nr_t dci_fmt,
const ue_carrier_params_t* user)
{
if (not check_args_valid(rnti_type, rnti, ss_id, aggr_idx, dci_fmt, user, true)) {
return nullptr;
alloc_result r = check_args_valid(rnti_type, rnti, ss_id, aggr_idx, dci_fmt, user, true);
if (r != alloc_result::success) {
return {r};
}
const srsran_search_space_t& ss = (user == nullptr) ? *bwp_cfg.get_ss(ss_id) : *user->get_ss(ss_id);
@ -286,7 +287,7 @@ pdcch_dl_t* bwp_pdcch_allocator::alloc_dl_pdcch_common(srsran_rnti_type_t
srslog::log_channel& ch = user == nullptr ? logger.warning : logger.debug;
log_pdcch_alloc_failure(ch, rnti_type, ss_id, rnti, "No available PDCCH position");
return nullptr;
return {alloc_result::no_cch_space};
}
// Fill DCI context information
@ -295,14 +296,16 @@ pdcch_dl_t* bwp_pdcch_allocator::alloc_dl_pdcch_common(srsran_rnti_type_t
// register last PDCCH coreset, in case it needs to be aborted
pending_dci = &pdcch_dl_list.back().dci.ctx;
return &pdcch_dl_list.back();
return {&pdcch_dl_list.back()};
}
pdcch_ul_t* bwp_pdcch_allocator::alloc_ul_pdcch(uint32_t ss_id, uint32_t aggr_idx, const ue_carrier_params_t& user)
pdcch_ul_alloc_result
bwp_pdcch_allocator::alloc_ul_pdcch(uint32_t ss_id, uint32_t aggr_idx, const ue_carrier_params_t& user)
{
static const srsran_dci_format_nr_t dci_fmt = srsran_dci_format_nr_0_0; // TODO: make it configurable
if (not check_args_valid(srsran_rnti_type_c, user.rnti, ss_id, aggr_idx, dci_fmt, &user, false)) {
return nullptr;
alloc_result r = check_args_valid(srsran_rnti_type_c, user.rnti, ss_id, aggr_idx, dci_fmt, &user, false);
if (r != alloc_result::success) {
return {r};
}
const srsran_search_space_t& ss = *user.get_ss(ss_id);
@ -319,7 +322,7 @@ pdcch_ul_t* bwp_pdcch_allocator::alloc_ul_pdcch(uint32_t ss_id, uint32_t aggr_id
// Log PDCCH allocation failure
log_pdcch_alloc_failure(logger.debug, srsran_rnti_type_c, ss_id, user.rnti, "No available PDCCH position");
return nullptr;
return {alloc_result::no_cch_space};
}
// Fill DCI context information
@ -328,7 +331,7 @@ pdcch_ul_t* bwp_pdcch_allocator::alloc_ul_pdcch(uint32_t ss_id, uint32_t aggr_id
// register last PDCCH coreset, in case it needs to be aborted
pending_dci = &pdcch_ul_list.back().dci.ctx;
return &pdcch_ul_list.back();
return {&pdcch_ul_list.back()};
}
void bwp_pdcch_allocator::cancel_last_pdcch()
@ -372,13 +375,13 @@ uint32_t bwp_pdcch_allocator::nof_cces(uint32_t coreset_id) const
return coresets[coreset_id].nof_cces();
}
bool bwp_pdcch_allocator::check_args_valid(srsran_rnti_type_t rnti_type,
uint16_t rnti,
uint32_t ss_id,
uint32_t aggr_idx,
srsran_dci_format_nr_t dci_fmt,
const ue_carrier_params_t* user,
bool is_dl) const
alloc_result bwp_pdcch_allocator::check_args_valid(srsran_rnti_type_t rnti_type,
uint16_t rnti,
uint32_t ss_id,
uint32_t aggr_idx,
srsran_dci_format_nr_t dci_fmt,
const ue_carrier_params_t* user,
bool is_dl) const
{
srsran_assert(ss_id < SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE, "Invalid SearchSpace#%d", ss_id);
srsran_assert(
@ -387,7 +390,7 @@ bool bwp_pdcch_allocator::check_args_valid(srsran_rnti_type_t rnti_type,
// DL must be active in given slot
if (not bwp_cfg.slots[slot_idx].is_dl) {
log_pdcch_alloc_failure(logger.error, rnti_type, ss_id, rnti, "DL is disabled for slot={}", slot_idx);
return false;
return alloc_result::no_cch_space;
}
// Verify SearchSpace validity
@ -395,19 +398,23 @@ bool bwp_pdcch_allocator::check_args_valid(srsran_rnti_type_t rnti_type,
if (ss == nullptr) {
// Couldn't find SearchSpace
log_pdcch_alloc_failure(logger.error, rnti_type, ss_id, rnti, "SearchSpace has not been configured");
return false;
return alloc_result::invalid_grant_params;
}
if (ss->nof_candidates[aggr_idx] == 0) {
// No valid DCI position candidates given aggregation level
log_pdcch_alloc_failure(
logger.warning, rnti_type, ss_id, rnti, "Chosen SearchSpace doesn't have CCE candidates for L={}", aggr_idx);
return false;
return alloc_result::invalid_grant_params;
}
if (not is_rnti_type_valid_in_search_space(rnti_type, ss->type)) {
// RNTI type doesnt match SearchSpace type
log_pdcch_alloc_failure(
logger.warning, rnti_type, ss_id, rnti, "Chosen SearchSpace type={} does not match rnti_type.", ss->type);
return false;
log_pdcch_alloc_failure(logger.warning,
rnti_type,
ss_id,
rnti,
"Chosen SearchSpace type \"{}\" does not match rnti_type.",
srsran_ss_type_str(ss->type));
return alloc_result::invalid_grant_params;
}
auto dci_fmt_equal = [dci_fmt](srsran_dci_format_nr_t f) { return f == dci_fmt; };
if (std::none_of(&ss->formats[0], &ss->formats[ss->nof_formats], dci_fmt_equal)) {
@ -417,29 +424,29 @@ bool bwp_pdcch_allocator::check_args_valid(srsran_rnti_type_t rnti_type,
rnti,
"Chosen SearchSpace does not support chosen dci format={}",
srsran_dci_format_nr_string(dci_fmt));
return false;
return alloc_result::invalid_grant_params;
}
if (is_dl) {
if (pdcch_dl_list.full()) {
log_pdcch_alloc_failure(
logger.warning, rnti_type, ss_id, rnti, "Maximum number of allocations={} reached", pdcch_dl_list.size());
return false;
return alloc_result::no_cch_space;
}
} else if (pdcch_ul_list.full()) {
log_pdcch_alloc_failure(
logger.warning, rnti_type, ss_id, rnti, "Maximum number of UL allocations={} reached", pdcch_ul_list.size());
return false;
return alloc_result::no_cch_space;
}
srsran_sanity_check(pdcch_dl_list.size() + pdcch_ul_list.size() == nof_allocations(), "Invalid PDCCH state");
return true;
return alloc_result::success;
}
void bwp_pdcch_allocator::print_allocations(fmt::memory_buffer& fmtbuf) const
{
fmt::format_to(
fmtbuf, "PDCCH allocations ({} active coresets):{}\n", coresets.size(), nof_allocations() == 0 ? " None" : "");
fmtbuf, "PDCCH allocations: ({} active coresets):{}\n", coresets.size(), nof_allocations() == 0 ? " None" : "");
for (const coreset_region& cs : coresets) {
cs.print_allocations(fmtbuf);
}

@ -41,10 +41,12 @@ void test_coreset0_cfg()
uecfg.phy_cfg.pdcch = cell_cfg.bwps[0].pdcch; // Starts without UE-specific PDCCH
ue_carrier_params_t ue_cc{0x46, bwp_params, uecfg};
pdcch_dl_list_t dl_pdcchs;
pdcch_ul_list_t ul_pdcchs;
pdcch_dl_t* dl_pdcch = nullptr;
pdcch_ul_t* ul_pdcch = nullptr;
pdcch_dl_list_t dl_pdcchs;
pdcch_ul_list_t ul_pdcchs;
pdcch_dl_alloc_result dl_pdcch_result;
pdcch_ul_alloc_result ul_pdcch_result;
pdcch_dl_t* dl_pdcch = nullptr;
pdcch_ul_t* ul_pdcch = nullptr;
bwp_pdcch_allocator pdcch_sched(bwp_params, 0, dl_pdcchs, ul_pdcchs);
for (const srsran_coreset_t& cs : view_active_coresets(cell_cfg.bwps[0].pdcch)) {
@ -56,17 +58,18 @@ void test_coreset0_cfg()
TESTASSERT_EQ(0, pdcch_sched.nof_allocations());
// SIB1 allocation should be successful
dl_pdcch = pdcch_sched.alloc_si_pdcch(0, aggr_idx);
TESTASSERT(dl_pdcch != nullptr);
dl_pdcch_result = pdcch_sched.alloc_si_pdcch(0, aggr_idx);
TESTASSERT(dl_pdcch_result.has_value());
dl_pdcch = dl_pdcch_result.value();
TESTASSERT_EQ(1, pdcch_sched.nof_allocations());
TESTASSERT_EQ(srsran_rnti_type_si, dl_pdcch->dci.ctx.rnti_type);
TESTASSERT_EQ(0, dl_pdcch->dci.ctx.coreset_id);
test_dci_ctx_consistency(bwp_params.cfg.pdcch, dl_pdcch->dci.ctx);
// No space for RAR, UE PDSCH/PUSCH
TESTASSERT(pdcch_sched.alloc_rar_pdcch(0x2, aggr_idx) == nullptr);
TESTASSERT(pdcch_sched.alloc_dl_pdcch(srsran_rnti_type_c, 1, aggr_idx, ue_cc) == nullptr);
TESTASSERT(pdcch_sched.alloc_ul_pdcch(1, aggr_idx, ue_cc) == nullptr);
TESTASSERT(pdcch_sched.alloc_rar_pdcch(0x2, aggr_idx).error() == alloc_result::no_cch_space);
TESTASSERT(pdcch_sched.alloc_dl_pdcch(srsran_rnti_type_c, 1, aggr_idx, ue_cc).error() == alloc_result::no_cch_space);
TESTASSERT(pdcch_sched.alloc_ul_pdcch(1, aggr_idx, ue_cc).error() == alloc_result::no_cch_space);
srslog::fetch_basic_logger("TEST").info("%s", pdcch_sched.print_allocations());
@ -74,8 +77,9 @@ void test_coreset0_cfg()
pdcch_sched.reset();
// RAR allocation should be successful
dl_pdcch = pdcch_sched.alloc_rar_pdcch(0x2, aggr_idx);
TESTASSERT(dl_pdcch != nullptr);
dl_pdcch_result = pdcch_sched.alloc_rar_pdcch(0x2, aggr_idx);
TESTASSERT(dl_pdcch_result.has_value());
dl_pdcch = dl_pdcch_result.value();
TESTASSERT_EQ(1, pdcch_sched.nof_allocations());
TESTASSERT_EQ(srsran_rnti_type_ra, dl_pdcch->dci.ctx.rnti_type);
TESTASSERT_EQ(0, dl_pdcch->dci.ctx.coreset_id);
@ -83,8 +87,8 @@ void test_coreset0_cfg()
test_dci_ctx_consistency(bwp_params.cfg.pdcch, dl_pdcch->dci.ctx);
// No space for RAR, UE PDSCH/PUSCH
TESTASSERT(pdcch_sched.alloc_dl_pdcch(srsran_rnti_type_c, 1, aggr_idx, ue_cc) == nullptr);
TESTASSERT(pdcch_sched.alloc_ul_pdcch(1, aggr_idx, ue_cc) == nullptr);
TESTASSERT(pdcch_sched.alloc_dl_pdcch(srsran_rnti_type_c, 1, aggr_idx, ue_cc).error() == alloc_result::no_cch_space);
TESTASSERT(pdcch_sched.alloc_ul_pdcch(1, aggr_idx, ue_cc).error() == alloc_result::no_cch_space);
srslog::fetch_basic_logger("TEST").info("%s", pdcch_sched.print_allocations());
@ -92,8 +96,9 @@ void test_coreset0_cfg()
pdcch_sched.reset();
// 1st PDCCH allocation for DL should be successful
dl_pdcch = pdcch_sched.alloc_dl_pdcch(srsran_rnti_type_c, 1, aggr_idx, ue_cc);
TESTASSERT(dl_pdcch != nullptr);
dl_pdcch_result = pdcch_sched.alloc_dl_pdcch(srsran_rnti_type_c, 1, aggr_idx, ue_cc);
TESTASSERT(dl_pdcch_result.has_value());
dl_pdcch = dl_pdcch_result.value();
TESTASSERT_EQ(1, pdcch_sched.nof_allocations());
TESTASSERT_EQ(srsran_rnti_type_c, dl_pdcch->dci.ctx.rnti_type);
TESTASSERT_EQ(0u, dl_pdcch->dci.ctx.coreset_id);
@ -101,7 +106,7 @@ void test_coreset0_cfg()
test_dci_ctx_consistency(bwp_params.cfg.pdcch, dl_pdcch->dci.ctx);
// No space for 2nd PDCCH allocation
TESTASSERT(pdcch_sched.alloc_ul_pdcch(1, aggr_idx, ue_cc) == nullptr);
TESTASSERT(pdcch_sched.alloc_ul_pdcch(1, aggr_idx, ue_cc).error() == alloc_result::no_cch_space);
srslog::fetch_basic_logger("TEST").info("%s", pdcch_sched.print_allocations());
@ -109,8 +114,9 @@ void test_coreset0_cfg()
pdcch_sched.reset();
// 1st PDCCH allocation for UL should be successful
ul_pdcch = pdcch_sched.alloc_ul_pdcch(1, aggr_idx, ue_cc);
TESTASSERT(ul_pdcch != nullptr);
ul_pdcch_result = pdcch_sched.alloc_ul_pdcch(1, aggr_idx, ue_cc);
TESTASSERT(ul_pdcch_result.has_value());
ul_pdcch = ul_pdcch_result.value();
TESTASSERT_EQ(1, pdcch_sched.nof_allocations());
TESTASSERT_EQ(srsran_rnti_type_c, ul_pdcch->dci.ctx.rnti_type);
TESTASSERT_EQ(0u, ul_pdcch->dci.ctx.coreset_id);
@ -118,7 +124,7 @@ void test_coreset0_cfg()
test_dci_ctx_consistency(bwp_params.cfg.pdcch, ul_pdcch->dci.ctx);
// No space for 2nd PDCCH allocation
TESTASSERT(pdcch_sched.alloc_dl_pdcch(srsran_rnti_type_c, 1, aggr_idx, ue_cc) == nullptr);
TESTASSERT(pdcch_sched.alloc_dl_pdcch(srsran_rnti_type_c, 1, aggr_idx, ue_cc).error() == alloc_result::no_cch_space);
srslog::fetch_basic_logger("TEST").info("%s", pdcch_sched.print_allocations());
}
@ -164,7 +170,7 @@ void test_coreset2_cfg()
TESTASSERT_EQ(0, pdcch_sched.nof_allocations());
// SIB1 allocation should be successful
dl_pdcch = pdcch_sched.alloc_si_pdcch(0, aggr_idx);
dl_pdcch = pdcch_sched.alloc_si_pdcch(0, aggr_idx).value();
TESTASSERT(dl_pdcch != nullptr);
TESTASSERT_EQ(1, pdcch_sched.nof_allocations());
TESTASSERT_EQ(srsran_rnti_type_si, dl_pdcch->dci.ctx.rnti_type);
@ -174,12 +180,12 @@ void test_coreset2_cfg()
test_dci_ctx_consistency(bwp_params.cfg.pdcch, dl_pdcch->dci.ctx);
// No space for RAR or PDSCH in SS#1
TESTASSERT(pdcch_sched.alloc_rar_pdcch(0x2, aggr_idx) == nullptr);
TESTASSERT(pdcch_sched.alloc_dl_pdcch(srsran_rnti_type_c, 1, aggr_idx, ue_cc) == nullptr);
TESTASSERT(pdcch_sched.alloc_ul_pdcch(1, aggr_idx, ue_cc) == nullptr);
TESTASSERT(pdcch_sched.alloc_rar_pdcch(0x2, aggr_idx).error() == alloc_result::no_cch_space);
TESTASSERT(pdcch_sched.alloc_dl_pdcch(srsran_rnti_type_c, 1, aggr_idx, ue_cc).error() == alloc_result::no_cch_space);
TESTASSERT(pdcch_sched.alloc_ul_pdcch(1, aggr_idx, ue_cc).error() == alloc_result::no_cch_space);
// there is space for UE DL PDCCH in SS#2
dl_pdcch = pdcch_sched.alloc_dl_pdcch(srsran_rnti_type_c, 2, aggr_idx, ue_cc);
dl_pdcch = pdcch_sched.alloc_dl_pdcch(srsran_rnti_type_c, 2, aggr_idx, ue_cc).value();
TESTASSERT(dl_pdcch != nullptr);
TESTASSERT_EQ(2, pdcch_sched.nof_allocations());
TESTASSERT_EQ(srsran_rnti_type_c, dl_pdcch->dci.ctx.rnti_type);
@ -190,7 +196,7 @@ void test_coreset2_cfg()
test_dci_ctx_consistency(bwp_params.cfg.pdcch, dl_pdcch->dci.ctx);
// there is space for UE UL PDCCH in SS#2
ul_pdcch = pdcch_sched.alloc_ul_pdcch(2, aggr_idx, ue_cc);
ul_pdcch = pdcch_sched.alloc_ul_pdcch(2, aggr_idx, ue_cc).value();
TESTASSERT(ul_pdcch != nullptr);
TESTASSERT_EQ(3, pdcch_sched.nof_allocations());
TESTASSERT_EQ(srsran_rnti_type_c, ul_pdcch->dci.ctx.rnti_type);
@ -202,7 +208,7 @@ void test_coreset2_cfg()
test_dci_ctx_consistency(bwp_params.cfg.pdcch, ul_pdcch->dci.ctx);
// No space for 3rd PDCCH allocation in SS#2
TESTASSERT(pdcch_sched.alloc_dl_pdcch(srsran_rnti_type_c, 2, aggr_idx, ue_cc) == nullptr);
TESTASSERT(pdcch_sched.alloc_dl_pdcch(srsran_rnti_type_c, 2, aggr_idx, ue_cc).error() == alloc_result::no_cch_space);
// Verify there are no PDCCH collisions
TESTASSERT_EQ(3, pdcch_sched.nof_allocations());
@ -219,6 +225,71 @@ void test_coreset2_cfg()
TESTASSERT_EQ(0, ul_pdcchs.size());
}
void test_invalid_params()
{
const uint32_t aggr_idx = 2;
srsran::test_delimit_logger delimiter{"Test PDCCH Allocation with Invalid Arguments"};
sched_nr_impl::cell_cfg_t cell_cfg = get_default_sa_cell_cfg_common();
cell_cfg.bwps[0].pdcch.search_space_present[2] = true;
cell_cfg.bwps[0].pdcch.search_space[2] = get_default_ue_specific_search_space(2, 2);
cell_cfg.bwps[0].pdcch.coreset_present[2] = true;
cell_cfg.bwps[0].pdcch.coreset[2] = get_default_ue_specific_coreset(2, cell_cfg.carrier.pci);
cell_cfg.bwps[0].pdcch.search_space_present[3] = true;
cell_cfg.bwps[0].pdcch.search_space[3] = get_default_ue_specific_search_space(3, 2);
cell_cfg.bwps[0].pdcch.search_space[3].nof_formats = 1; // only DL
cell_cfg.bwps[0].pdcch.search_space[3].formats[0] = srsran_dci_format_nr_1_0;
sched_nr_interface::sched_args_t sched_args;
bwp_params_t bwp_params{cell_cfg, sched_args, 0, 0};
// UE config
ue_cfg_t uecfg = get_rach_ue_cfg(0);
uecfg.phy_cfg = get_common_ue_phy_cfg(cell_cfg);
uecfg.phy_cfg.pdcch = cell_cfg.bwps[0].pdcch; // Starts with UE-specific PDCCH
ue_carrier_params_t ue_cc{0x46, bwp_params, uecfg};
pdcch_dl_list_t dl_pdcchs;
pdcch_ul_list_t ul_pdcchs;
pdcch_dl_alloc_result dl_res;
pdcch_ul_alloc_result ul_res;
bwp_pdcch_allocator pdcch_sched(bwp_params, 0, dl_pdcchs, ul_pdcchs);
// Slot with SIB1 + DL PDCCH and UL PDCCH
TESTASSERT_EQ(0, pdcch_sched.nof_allocations());
// Pass UE search space for SI alloc
dl_res = pdcch_sched.alloc_si_pdcch(2, aggr_idx);
TESTASSERT(dl_res.is_error() and dl_res.error() == alloc_result::invalid_grant_params);
// Pass aggregation index for which there are no candidates
dl_res = pdcch_sched.alloc_si_pdcch(2, 4);
TESTASSERT(dl_res.is_error() and dl_res.error() == alloc_result::invalid_grant_params);
// SearchSpace must exist
dl_res = pdcch_sched.alloc_dl_pdcch(srsran_rnti_type_c, 4, aggr_idx, ue_cc);
TESTASSERT(dl_res.is_error() and dl_res.error() == alloc_result::invalid_grant_params);
// TC-RNTI cannot be allocated in Common SearchSpace Type1
dl_res = pdcch_sched.alloc_dl_pdcch(srsran_rnti_type_tc, 2, aggr_idx, ue_cc);
TESTASSERT(dl_res.is_error() and dl_res.error() == alloc_result::invalid_grant_params);
// C-RNTI cannot be allocated in Common SearchSpace Type0
dl_res = pdcch_sched.alloc_dl_pdcch(srsran_rnti_type_c, 0, aggr_idx, ue_cc);
TESTASSERT(dl_res.is_error() and dl_res.error() == alloc_result::invalid_grant_params);
// UL allocation cannot be made in SearchSpace without DCI format 0_0
ul_res = pdcch_sched.alloc_ul_pdcch(3, aggr_idx, ue_cc);
TESTASSERT(ul_res.is_error() and ul_res.error() == alloc_result::invalid_grant_params);
// Success case
TESTASSERT(pdcch_sched.nof_allocations() == 0);
ul_res = pdcch_sched.alloc_ul_pdcch(2, aggr_idx, ue_cc);
TESTASSERT(ul_res.has_value() and ul_res.value()->dci.ctx.format == srsran_dci_format_nr_0_0);
TESTASSERT(pdcch_sched.nof_allocations() == 1);
}
} // namespace srsenb
int main()
@ -235,4 +306,5 @@ int main()
srsenb::test_coreset0_cfg();
srsenb::test_coreset2_cfg();
srsenb::test_invalid_params();
}
Loading…
Cancel
Save