allocation of the sr/cqi/pucch_cs resources takes place at a frequency basis now

master
Francisco Paisana 5 years ago committed by Francisco Paisana
parent ee994468f7
commit 08e1f01c72

@ -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<uint8_t, erab_t> 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<uint8_t, srslte::unique_byte_buffer_t> 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_ctxt_common_list> cell_common_list;
std::unique_ptr<cell_info_common_list> cell_common_list;
// state
std::unique_ptr<freq_res_common_list> pucch_res_list;
std::map<uint16_t, std::unique_ptr<ue> > users; // NOTE: has to have fixed addr
std::map<uint32_t, asn1::rrc::paging_record_s> pending_paging;
@ -341,8 +327,6 @@ private:
static const int RRC_THREAD_PRIO = 65;
srslte::block_queue<rrc_pdu> rx_pdu_queue;
std::unique_ptr<pucch_res_common> pucch_res;
asn1::rrc::mcch_msg_s mcch;
bool enable_mbms = false;
rrc_cfg_t cfg = {};

@ -41,6 +41,18 @@ public:
std::array<bool, N_PUCCH_MAX_RES> 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<uint32_t, pucch_res_common> 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<cell_ctxt_dedicated>::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:
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_ctxt_common_list& common_list;
pucch_res_common& pucch_res;
const cell_info_common_list& common_list;
freq_res_common_list& pucch_res_list;
pucch_res_common* pucch_res = nullptr;
std::vector<cell_ctxt_dedicated> 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

@ -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<uint32_t>::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)

@ -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<uint32_t>::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<uint32_t>::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

Loading…
Cancel
Save