|
|
@ -120,7 +120,7 @@ cell_ctxt_dedicated_list::~cell_ctxt_dedicated_list()
|
|
|
|
cell_ctxt_dedicated* cell_ctxt_dedicated_list::get_enb_cc_idx(uint32_t enb_cc_idx)
|
|
|
|
cell_ctxt_dedicated* cell_ctxt_dedicated_list::get_enb_cc_idx(uint32_t enb_cc_idx)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto it = std::find_if(cell_ded_list.begin(), cell_ded_list.end(), [enb_cc_idx](const cell_ctxt_dedicated& c) {
|
|
|
|
auto it = std::find_if(cell_ded_list.begin(), cell_ded_list.end(), [enb_cc_idx](const cell_ctxt_dedicated& c) {
|
|
|
|
return c.cell_common.enb_cc_idx == enb_cc_idx;
|
|
|
|
return c.cell_common->enb_cc_idx == enb_cc_idx;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
return it == cell_ded_list.end() ? nullptr : &(*it);
|
|
|
|
return it == cell_ded_list.end() ? nullptr : &(*it);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -147,29 +147,121 @@ cell_ctxt_dedicated* cell_ctxt_dedicated_list::add_cell(uint32_t enb_cc_idx)
|
|
|
|
|
|
|
|
|
|
|
|
cell_ded_list.emplace_back(cell_ded_list.size(), *cell_common);
|
|
|
|
cell_ded_list.emplace_back(cell_ded_list.size(), *cell_common);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Allocate CQI, SR, and PUCCH CS resources. If failure, do not add new cell
|
|
|
|
|
|
|
|
if (not alloc_cell_resources(ue_cc_idx)) {
|
|
|
|
|
|
|
|
rem_last_cell();
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return &cell_ded_list.back();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool cell_ctxt_dedicated_list::rem_last_cell()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (cell_ded_list.empty()) {
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t ue_cc_idx = cell_ded_list.size() - 1;
|
|
|
|
|
|
|
|
if (ue_cc_idx == UE_PCELL_CC_IDX) {
|
|
|
|
|
|
|
|
dealloc_sr_resources();
|
|
|
|
|
|
|
|
dealloc_pucch_cs_resources();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
dealloc_cqi_resources(ue_cc_idx);
|
|
|
|
|
|
|
|
cell_ded_list.pop_back();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool cell_ctxt_dedicated_list::alloc_cell_resources(uint32_t ue_cc_idx)
|
|
|
|
|
|
|
|
{
|
|
|
|
// Allocate CQI, SR, and PUCCH CS resources. If failure, do not add new cell
|
|
|
|
// Allocate CQI, SR, and PUCCH CS resources. If failure, do not add new cell
|
|
|
|
if (ue_cc_idx == UE_PCELL_CC_IDX) {
|
|
|
|
if (ue_cc_idx == UE_PCELL_CC_IDX) {
|
|
|
|
if (not alloc_sr_resources(cfg.sr_cfg.period)) {
|
|
|
|
if (not alloc_sr_resources(cfg.sr_cfg.period)) {
|
|
|
|
log_h->error("Failed to allocate SR resources for PCell\n");
|
|
|
|
log_h->error("Failed to allocate SR resources for PCell\n");
|
|
|
|
cell_ded_list.pop_back();
|
|
|
|
return false;
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (cfg.cell_list.size() == 2) {
|
|
|
|
if (cfg.cell_list.size() == 2) {
|
|
|
|
// Allocate resources for Format1b CS (will be optional PUCCH3/CS)
|
|
|
|
// Allocate resources for Format1b CS (will be optional PUCCH3/CS)
|
|
|
|
if (not alloc_pucch_cs_resources()) {
|
|
|
|
if (not alloc_pucch_cs_resources()) {
|
|
|
|
log_h->error("Error allocating PUCCH Format1b CS resource for SCell\n");
|
|
|
|
log_h->error("Error allocating PUCCH Format1b CS resource for SCell\n");
|
|
|
|
cell_ded_list.pop_back();
|
|
|
|
return false;
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (not alloc_cqi_resources(ue_cc_idx, cfg.cqi_cfg.period)) {
|
|
|
|
if (not alloc_cqi_resources(ue_cc_idx, cfg.cqi_cfg.period)) {
|
|
|
|
log_h->error("Failed to allocate CQIresources for cell enb_cc_idx=%d\n", enb_cc_idx);
|
|
|
|
log_h->error("Failed to allocate CQIresources for cell ue_cc_idx=%d\n", ue_cc_idx);
|
|
|
|
cell_ded_list.pop_back();
|
|
|
|
return false;
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return &cell_ded_list.back();
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Set UE Cells. Contrarily to rem_cell/add_cell(), this method avoids unnecessary reallocation of PUCCH resources.
|
|
|
|
|
|
|
|
* @param enb_cc_idxs list of cells supported by the UE
|
|
|
|
|
|
|
|
* @return true if all cells were allocated
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool cell_ctxt_dedicated_list::set_cells(const std::vector<uint32_t>& enb_cc_idxs)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// Remove extra previously allocked cells
|
|
|
|
|
|
|
|
while (enb_cc_idxs.size() < cell_ded_list.size()) {
|
|
|
|
|
|
|
|
rem_last_cell();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cell_ded_list.empty()) {
|
|
|
|
|
|
|
|
// There were no previous cells allocated. Just add new ones
|
|
|
|
|
|
|
|
for (auto& cc_idx : enb_cc_idxs) {
|
|
|
|
|
|
|
|
if (not add_cell(cc_idx)) {
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const cell_info_common* prev_pcell = cell_ded_list[UE_PCELL_CC_IDX].cell_common;
|
|
|
|
|
|
|
|
const cell_info_common* new_pcell = common_list.get_cc_idx(enb_cc_idxs[0]);
|
|
|
|
|
|
|
|
bool pcell_freq_changed = prev_pcell->cell_cfg.dl_earfcn != new_pcell->cell_cfg.dl_earfcn;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (pcell_freq_changed) {
|
|
|
|
|
|
|
|
// Need to clean all allocated resources if PCell earfcn changes
|
|
|
|
|
|
|
|
while (not cell_ded_list.empty()) {
|
|
|
|
|
|
|
|
rem_last_cell();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
while (cell_ded_list.size() < enb_cc_idxs.size()) {
|
|
|
|
|
|
|
|
if (not add_cell(enb_cc_idxs[cell_ded_list.size()])) {
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t ue_cc_idx = 0;
|
|
|
|
|
|
|
|
for (; ue_cc_idx < enb_cc_idxs.size(); ++ue_cc_idx) {
|
|
|
|
|
|
|
|
uint32_t enb_cc_idx = enb_cc_idxs[ue_cc_idx];
|
|
|
|
|
|
|
|
const cell_info_common* cell_common = common_list.get_cc_idx(enb_cc_idx);
|
|
|
|
|
|
|
|
if (cell_common == nullptr) {
|
|
|
|
|
|
|
|
log_h->error("cell with enb_cc_idx=%d does not exist.\n", enb_cc_idx);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
auto* prev_cell_common = cell_ded_list[ue_cc_idx].cell_common;
|
|
|
|
|
|
|
|
if (enb_cc_idx == prev_cell_common->enb_cc_idx) {
|
|
|
|
|
|
|
|
// Same cell. Do not realloc resources
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dealloc_cqi_resources(ue_cc_idx);
|
|
|
|
|
|
|
|
cell_ded_list[ue_cc_idx] = cell_ctxt_dedicated{ue_cc_idx, *cell_common};
|
|
|
|
|
|
|
|
if (not alloc_cqi_resources(ue_cc_idx, cfg.cqi_cfg.period)) {
|
|
|
|
|
|
|
|
log_h->error("Failed to allocate CQI resources for cell ue_cc_idx=%d\n", ue_cc_idx);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
while (ue_cc_idx < cell_ded_list.size()) {
|
|
|
|
|
|
|
|
// Remove cells above the one that failed
|
|
|
|
|
|
|
|
rem_last_cell();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cell_ded_list.empty()) {
|
|
|
|
|
|
|
|
// We failed to allocate new PCell. Fallback to old PCell
|
|
|
|
|
|
|
|
add_cell(prev_pcell->enb_cc_idx);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return ue_cc_idx == enb_cc_idxs.size();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool cell_ctxt_dedicated_list::alloc_cqi_resources(uint32_t ue_cc_idx, uint32_t period)
|
|
|
|
bool cell_ctxt_dedicated_list::alloc_cqi_resources(uint32_t ue_cc_idx, uint32_t period)
|
|
|
@ -184,7 +276,7 @@ bool cell_ctxt_dedicated_list::alloc_cqi_resources(uint32_t ue_cc_idx, uint32_t
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const auto& pcell_pucch_cfg = get_ue_cc_idx(UE_PCELL_CC_IDX)->cell_common.sib2.rr_cfg_common.pucch_cfg_common;
|
|
|
|
const auto& pcell_pucch_cfg = get_ue_cc_idx(UE_PCELL_CC_IDX)->cell_common->sib2.rr_cfg_common.pucch_cfg_common;
|
|
|
|
uint32_t c = SRSLTE_CP_ISNORM(cfg.cell.cp) ? 3 : 2;
|
|
|
|
uint32_t c = SRSLTE_CP_ISNORM(cfg.cell.cp) ? 3 : 2;
|
|
|
|
uint32_t delta_pucch_shift = pcell_pucch_cfg.delta_pucch_shift.to_number();
|
|
|
|
uint32_t delta_pucch_shift = pcell_pucch_cfg.delta_pucch_shift.to_number();
|
|
|
|
delta_pucch_shift = SRSLTE_MAX(1, delta_pucch_shift);
|
|
|
|
delta_pucch_shift = SRSLTE_MAX(1, delta_pucch_shift);
|
|
|
@ -285,13 +377,13 @@ bool cell_ctxt_dedicated_list::alloc_sr_resources(uint32_t period)
|
|
|
|
log_h->error("The user cell pcell has not been allocated\n");
|
|
|
|
log_h->error("The user cell pcell has not been allocated\n");
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (cell->sr_res_present) {
|
|
|
|
if (sr_res_present) {
|
|
|
|
log_h->error("The user sr resources are already allocated\n");
|
|
|
|
log_h->error("The user sr resources are already allocated\n");
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t c = SRSLTE_CP_ISNORM(cfg.cell.cp) ? 3 : 2;
|
|
|
|
uint32_t c = SRSLTE_CP_ISNORM(cfg.cell.cp) ? 3 : 2;
|
|
|
|
uint32_t delta_pucch_shift = cell->cell_common.sib2.rr_cfg_common.pucch_cfg_common.delta_pucch_shift.to_number();
|
|
|
|
uint32_t delta_pucch_shift = cell->cell_common->sib2.rr_cfg_common.pucch_cfg_common.delta_pucch_shift.to_number();
|
|
|
|
delta_pucch_shift = SRSLTE_MAX(1, delta_pucch_shift); // prevent div by zero
|
|
|
|
delta_pucch_shift = SRSLTE_MAX(1, delta_pucch_shift); // prevent div by zero
|
|
|
|
uint32_t max_users = 12 * c / delta_pucch_shift;
|
|
|
|
uint32_t max_users = 12 * c / delta_pucch_shift;
|
|
|
|
|
|
|
|
|
|
|
@ -327,8 +419,8 @@ bool cell_ctxt_dedicated_list::alloc_sr_resources(uint32_t period)
|
|
|
|
|
|
|
|
|
|
|
|
// Compute N_pucch_sr
|
|
|
|
// Compute N_pucch_sr
|
|
|
|
sr_res.sr_N_pucch = i_min * max_users + pucch_res->sr_sched.nof_users[i_min][j_min];
|
|
|
|
sr_res.sr_N_pucch = i_min * max_users + pucch_res->sr_sched.nof_users[i_min][j_min];
|
|
|
|
if (cell->cell_common.sib2.rr_cfg_common.pucch_cfg_common.ncs_an) {
|
|
|
|
if (cell->cell_common->sib2.rr_cfg_common.pucch_cfg_common.ncs_an) {
|
|
|
|
sr_res.sr_N_pucch += cell->cell_common.sib2.rr_cfg_common.pucch_cfg_common.ncs_an;
|
|
|
|
sr_res.sr_N_pucch += cell->cell_common->sib2.rr_cfg_common.pucch_cfg_common.ncs_an;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Allocate user
|
|
|
|
// Allocate user
|
|
|
@ -365,12 +457,12 @@ bool cell_ctxt_dedicated_list::alloc_pucch_cs_resources()
|
|
|
|
log_h->error("The user cell pcell has not been allocated\n");
|
|
|
|
log_h->error("The user cell pcell has not been allocated\n");
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (cell->sr_res_present) {
|
|
|
|
if (n_pucch_cs_present) {
|
|
|
|
log_h->error("The user sr resources are already allocated\n");
|
|
|
|
log_h->error("The user sr resources are already allocated\n");
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const sib_type2_s& sib2 = cell->cell_common.sib2;
|
|
|
|
const sib_type2_s& sib2 = cell->cell_common->sib2;
|
|
|
|
const uint16_t N_pucch_1 = sib2.rr_cfg_common.pucch_cfg_common.n1_pucch_an;
|
|
|
|
const uint16_t N_pucch_1 = sib2.rr_cfg_common.pucch_cfg_common.n1_pucch_an;
|
|
|
|
const uint32_t max_cce = srslte_max_cce(cfg.cell.nof_prb);
|
|
|
|
const uint32_t max_cce = srslte_max_cce(cfg.cell.nof_prb);
|
|
|
|
// Loop through all available resources
|
|
|
|
// Loop through all available resources
|
|
|
|