From 08e1f01c729dfaac499fc58166a10507e74f3a68 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 1 May 2020 14:30:56 +0100 Subject: [PATCH] allocation of the sr/cqi/pucch_cs resources takes place at a frequency basis now --- srsenb/hdr/stack/rrc/rrc.h | 28 +--- srsenb/hdr/stack/rrc/rrc_cell_cfg.h | 57 ++++++-- srsenb/src/stack/rrc/rrc.cc | 201 +++------------------------ srsenb/src/stack/rrc/rrc_cell_cfg.cc | 200 +++++++++++++++++++++++--- 4 files changed, 252 insertions(+), 234 deletions(-) diff --git a/srsenb/hdr/stack/rrc/rrc.h b/srsenb/hdr/stack/rrc/rrc.h index d86b89d69..c9342a7cd 100644 --- a/srsenb/hdr/stack/rrc/rrc.h +++ b/srsenb/hdr/stack/rrc/rrc.h @@ -38,9 +38,9 @@ namespace srsenb { class cell_info_common; -class cell_ctxt_common_list; +class cell_info_common_list; class cell_ctxt_dedicated_list; -class pucch_res_common; +class freq_res_common_list; static const char rrc_state_text[RRC_STATE_N_ITEMS][100] = {"IDLE", "WAIT FOR CON SETUP COMPLETE", @@ -174,11 +174,8 @@ private: void notify_s1ap_ue_erab_setup_response(const asn1::s1ap::erab_to_be_setup_list_bearer_su_req_l& e); // Getters for PUCCH resources - int allocate_scell_pucch(uint32_t cc_idx); - int get_sr(uint8_t* I_sr, uint16_t* N_pucch_sr); int get_cqi(uint16_t* pmi_idx, uint16_t* n_pucch, uint32_t ue_cc_idx); int get_ri(uint32_t m_ri, uint16_t* ri_idx); - int get_n_pucch_cs(uint16_t* N_pucch_cs); bool is_allocated() const; bool select_security_algorithms(); @@ -228,21 +225,14 @@ private: asn1::rrc::ue_eutra_cap_s eutra_capabilities; srslte::rrc_ue_capabilities_t ue_capabilities; - typedef struct { + struct erab_t { uint8_t id; asn1::s1ap::erab_level_qos_params_s qos_params; asn1::bounded_bitstring<1, 160, true, true> address; uint32_t teid_out; uint32_t teid_in; - } erab_t; + }; std::map erabs; - int sr_sched_sf_idx = 0; - int sr_sched_prb_idx = 0; - bool sr_allocated = false; - uint32_t sr_N_pucch = 0; - uint32_t sr_I = 0; - uint16_t n_pucch_cs_idx = 0; - bool n_pucch_cs_alloc = false; std::map erab_info_list; @@ -258,11 +248,6 @@ private: ///< Helper to fill SCell struct for RRR Connection Reconfig int fill_scell_to_addmod_list(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn_reconf); - int sr_allocate(uint32_t period); - void sr_free(); - int n_pucch_cs_allocate(); - void n_pucch_cs_free(); - ///< UE's Physical layer dedicated configuration phy_interface_rrc_lte::phy_rrc_dedicated_list_t phy_rrc_dedicated_list = {}; @@ -304,9 +289,10 @@ private: srslte::log_ref rrc_log; // derived params - std::unique_ptr cell_common_list; + std::unique_ptr cell_common_list; // state + std::unique_ptr pucch_res_list; std::map > users; // NOTE: has to have fixed addr std::map pending_paging; @@ -341,8 +327,6 @@ private: static const int RRC_THREAD_PRIO = 65; srslte::block_queue rx_pdu_queue; - std::unique_ptr pucch_res; - asn1::rrc::mcch_msg_s mcch; bool enable_mbms = false; rrc_cfg_t cfg = {}; diff --git a/srsenb/hdr/stack/rrc/rrc_cell_cfg.h b/srsenb/hdr/stack/rrc/rrc_cell_cfg.h index cf2fdd27d..b8ebfd369 100644 --- a/srsenb/hdr/stack/rrc/rrc_cell_cfg.h +++ b/srsenb/hdr/stack/rrc/rrc_cell_cfg.h @@ -41,6 +41,18 @@ public: std::array n_pucch_cs_used = {}; }; +class freq_res_common_list +{ +public: + explicit freq_res_common_list(const rrc_cfg_t& cfg_); + + pucch_res_common* get_earfcn(uint32_t earfcn); + +private: + const rrc_cfg_t& cfg; + std::map pucch_res_list; +}; + /** Storage of cell-specific eNB config and derived params */ struct cell_info_common { uint32_t enb_cc_idx = 0; @@ -53,10 +65,10 @@ struct cell_info_common { cell_info_common(uint32_t idx_, const cell_cfg_t& cfg) : enb_cc_idx(idx_), cell_cfg(cfg) {} }; -class cell_ctxt_common_list +class cell_info_common_list { public: - explicit cell_ctxt_common_list(const rrc_cfg_t& cfg_); + explicit cell_info_common_list(const rrc_cfg_t& cfg_); cell_info_common* get_cc_idx(uint32_t enb_cc_idx) { return &cell_list[enb_cc_idx]; } const cell_info_common* get_cc_idx(uint32_t enb_cc_idx) const { return &cell_list[enb_cc_idx]; } @@ -74,6 +86,7 @@ struct cell_ctxt_dedicated { uint32_t ue_cc_idx; const cell_info_common& cell_common; bool cqi_res_present = false; + bool sr_res_present = false; struct cqi_res_t { uint32_t pmi_idx = 0; uint32_t pucch_res = 0; @@ -93,13 +106,11 @@ class cell_ctxt_dedicated_list { public: explicit cell_ctxt_dedicated_list(const rrc_cfg_t& cfg_, - pucch_res_common& pucch_res_, - const cell_ctxt_common_list& enb_common_list); + freq_res_common_list& pucch_res_list_, + const cell_info_common_list& enb_common_list); ~cell_ctxt_dedicated_list(); cell_ctxt_dedicated* add_cell(uint32_t enb_cc_idx); - bool alloc_cqi_resources(uint32_t ue_cc_idx, uint32_t period); - bool dealloc_cqi_resources(uint32_t ue_cc_idx); cell_ctxt_dedicated* get_ue_cc_idx(uint32_t ue_cc_idx) { @@ -107,18 +118,42 @@ public: } cell_ctxt_dedicated* get_enb_cc_idx(uint32_t enb_cc_idx); size_t nof_cells() const { return cell_ded_list.size(); } - size_t nof_cell_with_cqi_res() const; + bool is_allocated() const { return nof_cells() > 0; } using iterator = std::vector::iterator; iterator begin() { return cell_ded_list.begin(); } iterator end() { return cell_ded_list.end(); } + struct sr_res_t { + int sr_sched_sf_idx = 0; + int sr_sched_prb_idx = 0; + uint32_t sr_N_pucch = 0; + uint32_t sr_I = 0; + }; + + const sr_res_t* get_sr_res() const { return sr_res_present ? &sr_res : nullptr; } + const uint16_t* get_n_pucch_cs() const { return n_pucch_cs_present ? &n_pucch_cs_idx : nullptr; } + bool is_pucch_cs_allocated() const { return n_pucch_cs_present; } + private: - srslte::log_ref log_h{"RRC"}; - const rrc_cfg_t& cfg; - const cell_ctxt_common_list& common_list; - pucch_res_common& pucch_res; + bool alloc_cqi_resources(uint32_t ue_cc_idx, uint32_t period); + bool dealloc_cqi_resources(uint32_t ue_cc_idx); + bool alloc_sr_resources(uint32_t period); + bool dealloc_sr_resources(); + bool alloc_pucch_cs_resources(); + bool dealloc_pucch_cs_resources(); + + srslte::log_ref log_h{"RRC"}; + const rrc_cfg_t& cfg; + const cell_info_common_list& common_list; + freq_res_common_list& pucch_res_list; + + pucch_res_common* pucch_res = nullptr; std::vector cell_ded_list; + bool sr_res_present = false; + bool n_pucch_cs_present = false; + sr_res_t sr_res = {}; + uint16_t n_pucch_cs_idx = 0; }; } // namespace srsenb diff --git a/srsenb/src/stack/rrc/rrc.cc b/srsenb/src/stack/rrc/rrc.cc index 1820c5899..6844d27cb 100644 --- a/srsenb/src/stack/rrc/rrc.cc +++ b/srsenb/src/stack/rrc/rrc.cc @@ -70,7 +70,7 @@ void rrc::init(const rrc_cfg_t& cfg_, configure_mbsfn_sibs(&cfg.sibs[1].sib2(), &cfg.sibs[12].sib13_v920()); } - pucch_res.reset(new pucch_res_common{}); + pucch_res_list.reset(new freq_res_common_list{cfg}); // Loads the PRACH root sequence cfg.sibs[1].sib2().rr_cfg_common.prach_cfg.root_seq_idx = cfg.cell_list[0].root_seq_idx; @@ -781,7 +781,7 @@ void rrc::config_mac() scellcfg.enb_cc_idx = it - cfg.cell_list.begin(); scellcfg.ul_allowed = scellitem.ul_allowed; scellcfg.cross_carrier_scheduling = scellitem.cross_carrier_sched; - sched_cfg[ccidx].scell_list.push_back(std::move(scellcfg)); + sched_cfg[ccidx].scell_list.push_back(scellcfg); } } @@ -804,7 +804,7 @@ uint32_t rrc::generate_sibs() sched_info_list_l& sched_info = cfg.sib1.sched_info_list; // Store configs,SIBs in common cell ctxt list - cell_common_list.reset(new cell_ctxt_common_list{cfg}); + cell_common_list.reset(new cell_info_common_list{cfg}); // generate and pack into SIB buffers for (uint32_t cc_idx = 0; cc_idx < cfg.cell_list.size(); cc_idx++) { @@ -985,7 +985,7 @@ rrc::ue::ue(rrc* outer_rrc, uint16_t rnti_, const sched_interface::ue_cfg_t& sch pool(srslte::byte_buffer_pool::get_instance()), current_sched_ue_cfg(sched_ue_cfg), phy_rrc_dedicated_list(sched_ue_cfg.supported_cc_list.size()), - cell_ded_list(new cell_ctxt_dedicated_list{parent->cfg, *parent->pucch_res, *outer_rrc->cell_common_list}) + cell_ded_list(new cell_ctxt_dedicated_list{parent->cfg, *outer_rrc->pucch_res_list, *outer_rrc->cell_common_list}) { if (current_sched_ue_cfg.supported_cc_list.empty() or not current_sched_ue_cfg.supported_cc_list[0].active) { parent->rrc_log->warning("No PCell set. Picking eNBccIdx=0 as PCell\n"); @@ -1005,23 +1005,9 @@ rrc::ue::ue(rrc* outer_rrc, uint16_t rnti_, const sched_interface::ue_cfg_t& sch if (cell_ded_list->add_cell(sched_ue_cfg.supported_cc_list[0].enb_cc_idx) == nullptr) { return; } - if (cell_ded_list->alloc_cqi_resources(UE_PCELL_CC_IDX, parent->cfg.cqi_cfg.period) != SRSLTE_SUCCESS) { - return; - } - if (sr_allocate(parent->cfg.cqi_cfg.period) != SRSLTE_SUCCESS) { - return; - } - if (parent->cfg.cell_list.size() > 1) { - n_pucch_cs_allocate(); - } } -rrc::ue::~ue() -{ - // And deallocate resources from RRC - sr_free(); - n_pucch_cs_free(); -} +rrc::ue::~ue() {} rrc_state_t rrc::ue::get_state() { @@ -1556,15 +1542,9 @@ void rrc::ue::send_connection_setup(bool is_setup) } phy_cfg->ant_info.explicit_value().ue_tx_ant_sel.set(setup_e::release); - if (is_setup) { - if (get_sr(&phy_cfg->sched_request_cfg.setup().sr_cfg_idx, &phy_cfg->sched_request_cfg.setup().sr_pucch_res_idx)) { - parent->rrc_log->error("Allocating SR resources for rnti=0x%x\n", rnti); - return; - } - } else { - phy_cfg->sched_request_cfg.setup().sr_cfg_idx = (uint8_t)sr_I; - phy_cfg->sched_request_cfg.setup().sr_pucch_res_idx = (uint16_t)sr_N_pucch; - } + phy_cfg->sched_request_cfg.setup().sr_cfg_idx = (uint8_t)cell_ded_list->get_sr_res()->sr_I; + phy_cfg->sched_request_cfg.setup().sr_pucch_res_idx = (uint16_t)cell_ded_list->get_sr_res()->sr_N_pucch; + // Power control phy_cfg->ul_pwr_ctrl_ded_present = true; phy_cfg->ul_pwr_ctrl_ded.p0_ue_pusch = 0; @@ -1618,8 +1598,8 @@ void rrc::ue::send_connection_setup(bool is_setup) current_sched_ue_cfg.dl_cfg.cqi_report.periodic_configured = true; } current_sched_ue_cfg.dl_cfg.tm = SRSLTE_TM1; - current_sched_ue_cfg.pucch_cfg.I_sr = sr_I; - current_sched_ue_cfg.pucch_cfg.n_pucch_sr = sr_N_pucch; + current_sched_ue_cfg.pucch_cfg.I_sr = cell_ded_list->get_sr_res()->sr_I; + current_sched_ue_cfg.pucch_cfg.n_pucch_sr = cell_ded_list->get_sr_res()->sr_N_pucch; current_sched_ue_cfg.pucch_cfg.sr_configured = true; const sib_type2_s& sib2 = get_ue_cc_cfg(UE_PCELL_CC_IDX)->sib2; current_sched_ue_cfg.pucch_cfg.delta_pucch_shift = sib2.rr_cfg_common.pucch_cfg_common.delta_pucch_shift.to_number(); @@ -1732,7 +1712,7 @@ void rrc::ue::send_connection_reconf_upd(srslte::unique_byte_buffer_t pdu) phy_cfg->sched_request_cfg.setup().dsr_trans_max = parent->cfg.sr_cfg.dsr_max; phy_cfg->cqi_report_cfg_present = true; - if (cell_ded_list->nof_cell_with_cqi_res() > 0) { + if (cell_ded_list->nof_cells() > 0) { phy_cfg->cqi_report_cfg.cqi_report_periodic_present = true; phy_cfg->cqi_report_cfg.cqi_report_periodic.set_setup().cqi_format_ind_periodic.set( cqi_report_periodic_c::setup_s_::cqi_format_ind_periodic_c_::types::wideband_cqi); @@ -1757,7 +1737,8 @@ void rrc::ue::send_connection_reconf_upd(srslte::unique_byte_buffer_t pdu) } apply_reconf_phy_config(reconfig_r8); - get_sr(&phy_cfg->sched_request_cfg.setup().sr_cfg_idx, &phy_cfg->sched_request_cfg.setup().sr_pucch_res_idx); + phy_cfg->sched_request_cfg.setup().sr_cfg_idx = cell_ded_list->get_sr_res()->sr_I; + phy_cfg->sched_request_cfg.setup().sr_cfg_idx = cell_ded_list->get_sr_res()->sr_N_pucch; pdu->clear(); @@ -1940,14 +1921,11 @@ int rrc::ue::fill_scell_to_addmod_list(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn_ } // Allocate CQI + PUCCH for SCells. - uint32_t nof_allocs = 0; - for (size_t scell_idx = 0; scell_idx < pcell_cfg->cell_cfg.scell_list.size(); ++scell_idx) { - uint32_t cell_id = pcell_cfg->cell_cfg.scell_list[scell_idx].cell_id; - if (cell_ded_list->add_cell(parent->cell_common_list->get_cell_id(cell_id)->enb_cc_idx) != nullptr) { - nof_allocs += allocate_scell_pucch(scell_idx + 1) == SRSLTE_SUCCESS ? 1 : 0; - } + for (auto scell_idx : pcell_cfg->cell_cfg.scell_list) { + uint32_t cell_id = scell_idx.cell_id; + cell_ded_list->add_cell(parent->cell_common_list->get_cell_id(cell_id)->enb_cc_idx); } - if (nof_allocs == 1) { + if (cell_ded_list->nof_cells() == 1) { // No SCell could be allocated. Fallback to single cell mode. return SRSLTE_SUCCESS; } @@ -2080,7 +2058,7 @@ int rrc::ue::fill_scell_to_addmod_list(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn_ n1_pucch_an_cs_r10_l item0(4); // TODO: should we use a different n1PUCCH-AN-CS-List configuration? for (auto& it : item0) { - get_n_pucch_cs(&it); + it = cell_ded_list->is_pucch_cs_allocated() ? *cell_ded_list->get_n_pucch_cs() : 0; } ch_sel_r10.n1_pucch_an_cs_r10.setup().n1_pucch_an_cs_list_r10.push_back(item0); @@ -2448,100 +2426,6 @@ void rrc::ue::apply_reconf_phy_config(const asn1::rrc::rrc_conn_recfg_r8_ies_s& } } -void rrc::ue::sr_free() -{ - if (sr_allocated) { - if (parent->pucch_res->sr_sched.nof_users[sr_sched_prb_idx][sr_sched_sf_idx] > 0) { - parent->pucch_res->sr_sched.nof_users[sr_sched_prb_idx][sr_sched_sf_idx]--; - } else { - parent->rrc_log->warning( - "Removing SR resources: no users in time-frequency slot (%d, %d)\n", sr_sched_prb_idx, sr_sched_sf_idx); - } - parent->rrc_log->info( - "Deallocated SR resources for time-frequency slot (%d, %d)\n", sr_sched_prb_idx, sr_sched_sf_idx); - sr_allocated = false; - } -} - -int rrc::ue::get_sr(uint8_t* I_sr, uint16_t* N_pucch_sr) -{ - if (sr_allocated) { - *I_sr = sr_I; - *N_pucch_sr = sr_N_pucch; - return SRSLTE_SUCCESS; - } else { - return SRSLTE_ERROR; - } -} - -int rrc::ue::sr_allocate(uint32_t period) -{ - uint32_t c = SRSLTE_CP_ISNORM(parent->cfg.cell.cp) ? 3 : 2; - uint32_t delta_pucch_shift = - get_ue_cc_cfg(UE_PCELL_CC_IDX)->sib2.rr_cfg_common.pucch_cfg_common.delta_pucch_shift.to_number(); - - uint32_t max_users = 12 * c / delta_pucch_shift; - - // Find freq-time resources with least number of users - int i_min = 0, j_min = 0; - uint32_t min_users = std::numeric_limits::max(); - for (uint32_t i = 0; i < parent->cfg.sr_cfg.nof_prb; i++) { - for (uint32_t j = 0; j < parent->cfg.sr_cfg.nof_subframes; j++) { - if (parent->pucch_res->sr_sched.nof_users[i][j] < min_users) { - i_min = i; - j_min = j; - min_users = parent->pucch_res->sr_sched.nof_users[i][j]; - } - } - } - - if (parent->pucch_res->sr_sched.nof_users[i_min][j_min] > max_users) { - parent->rrc_log->error("Not enough PUCCH resources to allocate Scheduling Request\n"); - return SRSLTE_ERROR; - } - - // Compute I_sr - if (period != 5 && period != 10 && period != 20 && period != 40 && period != 80) { - parent->rrc_log->error("Invalid SchedulingRequest period %d ms\n", period); - return SRSLTE_ERROR; - } - if (parent->cfg.sr_cfg.sf_mapping[j_min] < period) { - sr_I = period - 5 + parent->cfg.sr_cfg.sf_mapping[j_min]; - } else { - parent->rrc_log->error( - "Allocating SR: invalid sf_idx=%d for period=%d\n", parent->cfg.sr_cfg.sf_mapping[j_min], period); - return SRSLTE_ERROR; - } - - // Compute N_pucch_sr - sr_N_pucch = i_min * max_users + parent->pucch_res->sr_sched.nof_users[i_min][j_min]; - if (get_ue_cc_cfg(UE_PCELL_CC_IDX)->sib2.rr_cfg_common.pucch_cfg_common.ncs_an) { - sr_N_pucch += get_ue_cc_cfg(UE_PCELL_CC_IDX)->sib2.rr_cfg_common.pucch_cfg_common.ncs_an; - } - - // Allocate user - parent->pucch_res->sr_sched.nof_users[i_min][j_min]++; - sr_sched_prb_idx = i_min; - sr_sched_sf_idx = j_min; - sr_allocated = true; - - parent->rrc_log->info("Allocated SR resources for time-frequency slot (%d, %d), N_pucch_sr=%d, I_sr=%d\n", - sr_sched_prb_idx, - sr_sched_sf_idx, - sr_N_pucch, - sr_I); - return SRSLTE_SUCCESS; -} - -void rrc::ue::n_pucch_cs_free() -{ - if (n_pucch_cs_alloc) { - parent->pucch_res->n_pucch_cs_used[n_pucch_cs_idx] = false; - n_pucch_cs_alloc = false; - parent->rrc_log->info("Deallocated N_pucch_cs=%d\n", n_pucch_cs_idx); - } -} - int rrc::ue::get_cqi(uint16_t* pmi_idx, uint16_t* n_pucch, uint32_t ue_cc_idx) { cell_ctxt_dedicated* c = cell_ded_list->get_ue_cc_idx(ue_cc_idx); @@ -2555,56 +2439,9 @@ int rrc::ue::get_cqi(uint16_t* pmi_idx, uint16_t* n_pucch, uint32_t ue_cc_idx) } } -int rrc::ue::allocate_scell_pucch(uint32_t ue_cc_idx) -{ - if (cell_ded_list->alloc_cqi_resources(ue_cc_idx, parent->cfg.cqi_cfg.period) != SRSLTE_SUCCESS) { - parent->rrc_log->error("Error allocating CQI resource for ue_cc_idx=%d\n", ue_cc_idx); - return SRSLTE_ERROR; - } - // Allocate resources for Format1b CS (will be optional PUCCH3/CS) - if (parent->cfg.cell_list.size() == 2 && ue_cc_idx == 1) { - if (n_pucch_cs_allocate()) { - parent->rrc_log->error("Error allocating PUCCH Format1b CS resource for ue_cc_idx=%d\n", ue_cc_idx); - return SRSLTE_ERROR; - } - } - return SRSLTE_SUCCESS; -} - -int rrc::ue::n_pucch_cs_allocate() -{ - const sib_type2_s& sib2 = get_ue_cc_cfg(UE_PCELL_CC_IDX)->sib2; - const uint16_t N_pucch_1 = sib2.rr_cfg_common.pucch_cfg_common.n1_pucch_an; - const uint32_t max_cce = srslte_max_cce(parent->cfg.cell.nof_prb); - // Loop through all available resources - for (uint32_t i = 0; i < pucch_res_common::N_PUCCH_MAX_RES; i++) { - if (!parent->pucch_res->n_pucch_cs_used[i] && !(i >= N_pucch_1 && i < N_pucch_1 + max_cce)) { - // Allocate resource - parent->pucch_res->n_pucch_cs_used[i] = true; - n_pucch_cs_idx = i; - n_pucch_cs_alloc = true; - parent->rrc_log->info("Allocated N_pucch_cs=%d\n", n_pucch_cs_idx); - return SRSLTE_SUCCESS; - } - } - parent->rrc_log->warning("Could not allocated N_pucch_cs\n"); - return SRSLTE_ERROR; -} - -int rrc::ue::get_n_pucch_cs(uint16_t* N_pucch_cs) -{ - if (n_pucch_cs_alloc) { - *N_pucch_cs = n_pucch_cs_idx; - return SRSLTE_SUCCESS; - } else { - return SRSLTE_ERROR; - } -} - bool rrc::ue::is_allocated() const { - return cell_ded_list->nof_cell_with_cqi_res() > 0 and sr_allocated and - (parent->cfg.cell_list.size() <= 1 or n_pucch_cs_alloc); + return cell_ded_list->is_allocated(); } int rrc::ue::get_ri(uint32_t m_ri, uint16_t* ri_idx) diff --git a/srsenb/src/stack/rrc/rrc_cell_cfg.cc b/srsenb/src/stack/rrc/rrc_cell_cfg.cc index 0b5dceb97..8451a665f 100644 --- a/srsenb/src/stack/rrc/rrc_cell_cfg.cc +++ b/srsenb/src/stack/rrc/rrc_cell_cfg.cc @@ -25,11 +25,27 @@ using namespace asn1::rrc; namespace srsenb { +freq_res_common_list::freq_res_common_list(const rrc_cfg_t& cfg_) : cfg(cfg_) +{ + for (auto& c : cfg.cell_list) { + auto it = pucch_res_list.find(c.dl_earfcn); + if (it == pucch_res_list.end()) { + pucch_res_list[c.dl_earfcn] = {}; + } + } +} + +pucch_res_common* freq_res_common_list::get_earfcn(uint32_t earfcn) +{ + auto it = pucch_res_list.find(earfcn); + return (it == pucch_res_list.end()) ? nullptr : &(it->second); +} + /************************* * cell ctxt common ************************/ -cell_ctxt_common_list::cell_ctxt_common_list(const rrc_cfg_t& cfg_) : cfg(cfg_) +cell_info_common_list::cell_info_common_list(const rrc_cfg_t& cfg_) : cfg(cfg_) { cell_list.reserve(cfg.cell_list.size()); @@ -63,7 +79,7 @@ cell_ctxt_common_list::cell_ctxt_common_list(const rrc_cfg_t& cfg_) : cfg(cfg_) } } -const cell_info_common* cell_ctxt_common_list::get_cell_id(uint32_t cell_id) const +const cell_info_common* cell_info_common_list::get_cell_id(uint32_t cell_id) const { auto it = std::find_if(cell_list.begin(), cell_list.end(), [cell_id](const cell_info_common& c) { return c.cell_cfg.cell_id == cell_id; @@ -71,7 +87,7 @@ const cell_info_common* cell_ctxt_common_list::get_cell_id(uint32_t cell_id) con return it == cell_list.end() ? nullptr : &(*it); } -const cell_info_common* cell_ctxt_common_list::get_pci(uint32_t pci) const +const cell_info_common* cell_info_common_list::get_pci(uint32_t pci) const { auto it = std::find_if( cell_list.begin(), cell_list.end(), [pci](const cell_info_common& c) { return c.cell_cfg.pci == pci; }); @@ -83,10 +99,10 @@ const cell_info_common* cell_ctxt_common_list::get_pci(uint32_t pci) const ************************/ cell_ctxt_dedicated_list::cell_ctxt_dedicated_list(const rrc_cfg_t& cfg_, - pucch_res_common& pucch_res_, - const cell_ctxt_common_list& enb_common_list) : + freq_res_common_list& pucch_res_list_, + const cell_info_common_list& enb_common_list) : cfg(cfg_), - pucch_res(pucch_res_), + pucch_res_list(pucch_res_list_), common_list(enb_common_list) { cell_ded_list.reserve(common_list.nof_cells()); @@ -97,6 +113,8 @@ cell_ctxt_dedicated_list::~cell_ctxt_dedicated_list() for (auto& c : cell_ded_list) { dealloc_cqi_resources(c.ue_cc_idx); } + dealloc_sr_resources(); + dealloc_pucch_cs_resources(); } cell_ctxt_dedicated* cell_ctxt_dedicated_list::get_enb_cc_idx(uint32_t enb_cc_idx) @@ -107,12 +125,6 @@ cell_ctxt_dedicated* cell_ctxt_dedicated_list::get_enb_cc_idx(uint32_t enb_cc_id return it == cell_ded_list.end() ? nullptr : &(*it); } -size_t cell_ctxt_dedicated_list::nof_cell_with_cqi_res() const -{ - return std::count_if( - cell_ded_list.begin(), cell_ded_list.end(), [](const cell_ctxt_dedicated& c) { return c.cqi_res_present; }); -} - cell_ctxt_dedicated* cell_ctxt_dedicated_list::add_cell(uint32_t enb_cc_idx) { const cell_info_common* cell_common = common_list.get_cc_idx(enb_cc_idx); @@ -126,7 +138,37 @@ cell_ctxt_dedicated* cell_ctxt_dedicated_list::add_cell(uint32_t enb_cc_idx) return nullptr; } + uint32_t ue_cc_idx = cell_ded_list.size(); + + if (ue_cc_idx == UE_PCELL_CC_IDX) { + // Fetch PUCCH resources if it's pcell + pucch_res = pucch_res_list.get_earfcn(cell_common->cell_cfg.dl_earfcn); + } + 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 (ue_cc_idx == UE_PCELL_CC_IDX) { + if (not alloc_sr_resources(cfg.cqi_cfg.period)) { + log_h->error("Failed to allocate SR resources for PCell\n"); + cell_ded_list.pop_back(); + return nullptr; + } + if (cfg.cell_list.size() == 2) { + // Allocate resources for Format1b CS (will be optional PUCCH3/CS) + if (not alloc_pucch_cs_resources()) { + log_h->error("Error allocating PUCCH Format1b CS resource for SCell\n"); + cell_ded_list.pop_back(); + return nullptr; + } + } + } + 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); + cell_ded_list.pop_back(); + return nullptr; + } + return &cell_ded_list.back(); } @@ -153,14 +195,14 @@ bool cell_ctxt_dedicated_list::alloc_cqi_resources(uint32_t ue_cc_idx, uint32_t uint32_t min_users = std::numeric_limits::max(); for (uint32_t i = 0; i < cfg.cqi_cfg.nof_prb; i++) { for (uint32_t j = 0; j < cfg.cqi_cfg.nof_subframes; j++) { - if (pucch_res.cqi_sched.nof_users[i][j] < min_users) { + if (pucch_res->cqi_sched.nof_users[i][j] < min_users) { i_min = i; j_min = j; - min_users = pucch_res.cqi_sched.nof_users[i][j]; + min_users = pucch_res->cqi_sched.nof_users[i][j]; } } } - if (pucch_res.cqi_sched.nof_users[i_min][j_min] > max_users) { + if (pucch_res->cqi_sched.nof_users[i_min][j_min] > max_users) { log_h->error("Not enough PUCCH resources to allocate Scheduling Request\n"); return false; } @@ -195,7 +237,7 @@ bool cell_ctxt_dedicated_list::alloc_cqi_resources(uint32_t ue_cc_idx, uint32_t } // Compute n_pucch_2 - uint16_t n_pucch = i_min * max_users + pucch_res.cqi_sched.nof_users[i_min][j_min]; + uint16_t n_pucch = i_min * max_users + pucch_res->cqi_sched.nof_users[i_min][j_min]; if (pcell_pucch_cfg.ncs_an) { n_pucch += pcell_pucch_cfg.ncs_an; } @@ -206,7 +248,7 @@ bool cell_ctxt_dedicated_list::alloc_cqi_resources(uint32_t ue_cc_idx, uint32_t cell->cqi_res.prb_idx = i_min; cell->cqi_res.sf_idx = j_min; - pucch_res.cqi_sched.nof_users[i_min][j_min]++; + pucch_res->cqi_sched.nof_users[i_min][j_min]++; log_h->info("Allocated CQI resources for ue_cc_idx=%d, time-frequency slot (%d, %d), n_pucch_2=%d, pmi_cfg_idx=%d\n", ue_cc_idx, @@ -224,8 +266,8 @@ bool cell_ctxt_dedicated_list::dealloc_cqi_resources(uint32_t ue_cc_idx) return false; } - if (pucch_res.cqi_sched.nof_users[c->cqi_res.prb_idx][c->cqi_res.sf_idx] > 0) { - pucch_res.cqi_sched.nof_users[c->cqi_res.prb_idx][c->cqi_res.sf_idx]--; + if (pucch_res->cqi_sched.nof_users[c->cqi_res.prb_idx][c->cqi_res.sf_idx] > 0) { + pucch_res->cqi_sched.nof_users[c->cqi_res.prb_idx][c->cqi_res.sf_idx]--; log_h->info("Deallocated CQI resources for time-frequency slot (%d, %d)\n", c->cqi_res.prb_idx, c->cqi_res.sf_idx); } else { log_h->warning( @@ -235,4 +277,124 @@ bool cell_ctxt_dedicated_list::dealloc_cqi_resources(uint32_t ue_cc_idx) return true; } +bool cell_ctxt_dedicated_list::alloc_sr_resources(uint32_t period) +{ + cell_ctxt_dedicated* cell = get_ue_cc_idx(UE_PCELL_CC_IDX); + if (cell == nullptr) { + log_h->error("The user cell pcell has not been allocated\n"); + return false; + } + if (cell->sr_res_present) { + log_h->error("The user sr resources are already allocated\n"); + return false; + } + + 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 max_users = 12 * c / delta_pucch_shift; + + // Find freq-time resources with least number of users + int i_min = 0, j_min = 0; + uint32_t min_users = std::numeric_limits::max(); + for (uint32_t i = 0; i < cfg.sr_cfg.nof_prb; i++) { + for (uint32_t j = 0; j < cfg.sr_cfg.nof_subframes; j++) { + if (pucch_res->sr_sched.nof_users[i][j] < min_users) { + i_min = i; + j_min = j; + min_users = pucch_res->sr_sched.nof_users[i][j]; + } + } + } + + if (pucch_res->sr_sched.nof_users[i_min][j_min] > max_users) { + log_h->error("Not enough PUCCH resources to allocate Scheduling Request\n"); + return false; + } + + // Compute I_sr + if (period != 5 && period != 10 && period != 20 && period != 40 && period != 80) { + log_h->error("Invalid SchedulingRequest period %d ms\n", period); + return false; + } + if (cfg.sr_cfg.sf_mapping[j_min] < period) { + sr_res.sr_I = period - 5 + cfg.sr_cfg.sf_mapping[j_min]; + } else { + log_h->error("Allocating SR: invalid sf_idx=%d for period=%d\n", cfg.sr_cfg.sf_mapping[j_min], period); + return false; + } + + // Compute N_pucch_sr + 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) { + sr_res.sr_N_pucch += cell->cell_common.sib2.rr_cfg_common.pucch_cfg_common.ncs_an; + } + + // Allocate user + pucch_res->sr_sched.nof_users[i_min][j_min]++; + sr_res.sr_sched_prb_idx = i_min; + sr_res.sr_sched_sf_idx = j_min; + sr_res_present = true; + + return true; +} + +bool cell_ctxt_dedicated_list::dealloc_sr_resources() +{ + if (sr_res_present) { + if (pucch_res->sr_sched.nof_users[sr_res.sr_sched_prb_idx][sr_res.sr_sched_sf_idx] > 0) { + pucch_res->sr_sched.nof_users[sr_res.sr_sched_prb_idx][sr_res.sr_sched_sf_idx]--; + } else { + log_h->warning("Removing SR resources: no users in time-frequency slot (%d, %d)\n", + sr_res.sr_sched_prb_idx, + sr_res.sr_sched_sf_idx); + } + log_h->info( + "Deallocated SR resources for time-frequency slot (%d, %d)\n", sr_res.sr_sched_prb_idx, sr_res.sr_sched_sf_idx); + sr_res_present = false; + return true; + } + return false; +} + +bool cell_ctxt_dedicated_list::alloc_pucch_cs_resources() +{ + cell_ctxt_dedicated* cell = get_ue_cc_idx(UE_PCELL_CC_IDX); + if (cell == nullptr) { + log_h->error("The user cell pcell has not been allocated\n"); + return false; + } + if (cell->sr_res_present) { + log_h->error("The user sr resources are already allocated\n"); + return false; + } + + 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 uint32_t max_cce = srslte_max_cce(cfg.cell.nof_prb); + // Loop through all available resources + for (uint32_t i = 0; i < pucch_res_common::N_PUCCH_MAX_RES; i++) { + if (!pucch_res->n_pucch_cs_used[i] && !(i >= N_pucch_1 && i < N_pucch_1 + max_cce)) { + // Allocate resource + pucch_res->n_pucch_cs_used[i] = true; + n_pucch_cs_idx = i; + n_pucch_cs_present = true; + log_h->info("Allocated N_pucch_cs=%d\n", n_pucch_cs_idx); + return true; + } + } + log_h->warning("Could not allocated N_pucch_cs\n"); + return false; +} + +bool cell_ctxt_dedicated_list::dealloc_pucch_cs_resources() +{ + if (n_pucch_cs_present) { + pucch_res->n_pucch_cs_used[n_pucch_cs_idx] = false; + n_pucch_cs_present = false; + log_h->info("Deallocated N_pucch_cs=%d\n", n_pucch_cs_idx); + return true; + } + return false; +} + } // namespace srsenb