diff --git a/srsue/hdr/stack/rrc/rrc.h b/srsue/hdr/stack/rrc/rrc.h index cc8ac07f3..509aca629 100644 --- a/srsue/hdr/stack/rrc/rrc.h +++ b/srsue/hdr/stack/rrc/rrc.h @@ -185,6 +185,7 @@ class cell_t has_valid_sib13 = true; } + // TODO: replace with TTI count uint32_t timeout_secs(struct timeval now) { struct timeval t[3]; memcpy(&t[2], &now, sizeof(struct timeval)); @@ -443,22 +444,26 @@ private: // List of strongest neighbour cell const static int NEIGHBOUR_TIMEOUT = 5; const static int NOF_NEIGHBOUR_CELLS = 8; - std::vector neighbour_cells; - cell_t* serving_cell = nullptr; + + typedef std::unique_ptr unique_cell_t; + std::vector neighbour_cells; + unique_cell_t serving_cell = nullptr; void set_serving_cell(uint32_t cell_idx); - void set_serving_cell(phy_interface_rrc_lte::phy_cell_t phy_cell); + void set_serving_cell(phy_interface_rrc_lte::phy_cell_t phy_cell); + unique_cell_t remove_neighbour_cell(const uint32_t earfcn, const uint32_t pci); + cell_t* get_neighbour_cell_handle(const uint32_t earfcn, const uint32_t pci); + bool has_neighbour_cell(const uint32_t earfcn, const uint32_t pci); int find_neighbour_cell(uint32_t earfcn, uint32_t pci); bool add_neighbour_cell(uint32_t earfcn, uint32_t pci, float rsrp); bool add_neighbour_cell(phy_interface_rrc_lte::phy_cell_t phy_cell, float rsrp); - bool add_neighbour_cell(cell_t *cell); + bool add_neighbour_cell(unique_cell_t new_cell); void sort_neighbour_cells(); void clean_neighbours(); - std::vector::iterator delete_neighbour(std::vector::iterator it); - void delete_neighbour(uint32_t cell_idx); + void delete_last_neighbour(); bool initiated = false; - asn1::rrc::reest_cause_e m_reest_cause = {}; + asn1::rrc::reest_cause_e m_reest_cause = asn1::rrc::reest_cause_e::nulltype; uint16_t m_reest_rnti = 0; bool reestablishment_started = false; bool reestablishment_successful = false; diff --git a/srsue/src/stack/rrc/rrc.cc b/srsue/src/stack/rrc/rrc.cc index 59698aade..fa8009839 100644 --- a/srsue/src/stack/rrc/rrc.cc +++ b/srsue/src/stack/rrc/rrc.cc @@ -51,34 +51,13 @@ rrc::rrc(srslte::log* rrc_log_) : state(RRC_STATE_IDLE), last_state(RRC_STATE_CONNECTED), drb_up(false), - rrc_log(rrc_log_) + rrc_log(rrc_log_), + serving_cell(unique_cell_t(new cell_t({}, 0.0))) { - n310_cnt = 0; - n311_cnt = 0; - serving_cell = new cell_t(); - neighbour_cells.reserve(NOF_NEIGHBOUR_CELLS); - initiated = false; - running = false; - m_reest_cause = asn1::rrc::reest_cause_e::nulltype; - m_reest_rnti = 0; - reestablishment_successful = false; - - current_mac_cfg = {}; - previous_mac_cfg = {}; - current_phy_cfg = {}; - previous_phy_cfg = {}; } rrc::~rrc() { - if (serving_cell) { - delete(serving_cell); - } - - std::vector::iterator it; - for (it = neighbour_cells.begin(); it != neighbour_cells.end(); ++it) { - delete(*it); - } } static void srslte_rrc_handler(asn1::srsasn_logger_level_t level, void* ctx, const char* str) @@ -417,20 +396,17 @@ void rrc::process_new_phy_meas(phy_meas_t meas) uint32_t earfcn = meas.earfcn; uint32_t pci = meas.pci; - // Measurements in RRC_CONNECTED go through measurement class to log reports etc. - if (state != RRC_STATE_IDLE) { - measurements.new_phy_meas(earfcn, pci, rsrp, rsrq, tti); - - // Measurements in RRC_IDLE update serving cell - } else { - + if (state == RRC_STATE_IDLE) { // Update serving cell if (serving_cell->equals(earfcn, pci)) { serving_cell->set_rsrp(rsrp); - // Or update/add neighbour cell } else { + // Or update/add neighbour cell add_neighbour_cell(earfcn, pci, rsrp); } + } else { + // Measurements in RRC_CONNECTED go through measurement class to log reports etc. + measurements.new_phy_meas(earfcn, pci, rsrp, rsrq, tti); } } @@ -541,73 +517,42 @@ void rrc::cell_reselection(float rsrp, float rsrq) // Set new serving cell void rrc::set_serving_cell(phy_interface_rrc_lte::phy_cell_t phy_cell) { - int cell_idx = find_neighbour_cell(phy_cell.earfcn, phy_cell.cell.id); - if (cell_idx >= 0) { - set_serving_cell(cell_idx); - } else { - rrc_log->error("Setting serving cell: Unknown cell with earfcn=%d, PCI=%d\n", phy_cell.earfcn, phy_cell.cell.id); - } -} - -// Set new serving cell -void rrc::set_serving_cell(uint32_t cell_idx) { - - if (cell_idx < neighbour_cells.size()) { + if (has_neighbour_cell(phy_cell.earfcn, phy_cell.cell.id)) { // Remove future serving cell from neighbours to make space for current serving cell - cell_t *new_serving_cell = neighbour_cells[cell_idx]; - if (!new_serving_cell) { - rrc_log->error("Setting serving cell. Index %d is empty\n", cell_idx); - return; - } - neighbour_cells.erase(std::remove(neighbour_cells.begin(), neighbour_cells.end(), neighbour_cells[cell_idx]), - neighbour_cells.end()); + unique_cell_t new_serving_cell = remove_neighbour_cell(phy_cell.earfcn, phy_cell.cell.id); // Move serving cell to neighbours list if (serving_cell->is_valid()) { - // Make sure it does not exist already - int serving_idx = find_neighbour_cell(serving_cell->get_earfcn(), serving_cell->get_pci()); - if (serving_idx >= 0 && (uint32_t) serving_idx < neighbour_cells.size()) { - rrc_log->error("Error serving cell is already in the neighbour list. Removing it\n"); - neighbour_cells.erase(std::remove(neighbour_cells.begin(), neighbour_cells.end(), neighbour_cells[serving_idx]), neighbour_cells.end()); - } - // If not in the list, add it to the list of neighbours (sorted inside the function) - if (!add_neighbour_cell(serving_cell)) { - rrc_log->info("Serving cell not added to list of neighbours. Worse than current neighbours\n"); + if (has_neighbour_cell(serving_cell->get_earfcn(), serving_cell->get_pci())) { + rrc_log->error("Error serving cell is already in the neighbour list.\n"); + // note, removing it here is not an option + } else { + if (add_neighbour_cell(std::move(serving_cell)) == false) { + rrc_log->info("Serving cell not added to list of neighbours. Worse than current neighbours\n"); + } } - } else { - // Do not leak it if we are not adding to neighbour list - delete serving_cell; } // Set new serving cell - serving_cell = new_serving_cell; - - rrc_log->info("Setting serving cell idx=%d, earfcn=%d, PCI=%d, rsrp=%.2f, nof_neighbours=%zd\n", - cell_idx, + serving_cell = std::move(new_serving_cell); + rrc_log->info("Setting serving cell earfcn=%d, PCI=%d, rsrp=%.2f, nof_neighbours=%zd\n", serving_cell->get_earfcn(), serving_cell->get_pci(), serving_cell->get_rsrp(), neighbour_cells.size()); - } else { - rrc_log->error("Setting invalid serving cell idx %d\n", cell_idx); + rrc_log->error("Setting serving cell: Unknown cell with earfcn=%d, PCI=%d\n", phy_cell.earfcn, phy_cell.cell.id); } } -bool sort_rsrp(cell_t *u1, cell_t *u2) { - return u1->greater(u2); -} - -void rrc::delete_neighbour(uint32_t cell_idx) { - measurements.delete_report(neighbour_cells[cell_idx]->get_earfcn(), neighbour_cells[cell_idx]->get_pci()); - delete neighbour_cells[cell_idx]; - neighbour_cells.erase(std::remove(neighbour_cells.begin(), neighbour_cells.end(), neighbour_cells[cell_idx]), neighbour_cells.end()); -} - -std::vector::iterator rrc::delete_neighbour(std::vector::iterator it) { - measurements.delete_report((*it)->get_earfcn(), (*it)->get_pci()); - delete (*it); - return neighbour_cells.erase(it); +void rrc::delete_last_neighbour() +{ + if (not neighbour_cells.empty()) { + auto& it = neighbour_cells.back(); + rrc_log->debug("Delete cell earfcn=%d, pci=%d from neighbor list.\n", (*it).get_earfcn(), (*it).get_pci()); + measurements.delete_report((*it).get_earfcn(), (*it).get_pci()); + neighbour_cells.pop_back(); + } } /* Called by main RRC thread to remove neighbours from which measurements have not been received in a while @@ -617,36 +562,36 @@ void rrc::clean_neighbours() struct timeval now; gettimeofday(&now, NULL); - std::vector::iterator it = neighbour_cells.begin(); - while(it != neighbour_cells.end()) { + for (auto it = neighbour_cells.begin(); it != neighbour_cells.end();) { if ((*it)->timeout_secs(now) > NEIGHBOUR_TIMEOUT) { rrc_log->info("Neighbour PCI=%d timed out. Deleting\n", (*it)->get_pci()); - it = delete_neighbour(it); + it = neighbour_cells.erase(it); } else { ++it; } } } -// Sort neighbour cells by decreasing order of RSRP +// Sort neighbour cells by decreasing order of RSRP and remove old cells from neighbor list void rrc::sort_neighbour_cells() { // Remove out-of-sync cells - std::vector::iterator it = neighbour_cells.begin(); - while(it != neighbour_cells.end()) { + for (auto it = neighbour_cells.begin(); it != neighbour_cells.end();) { if ((*it)->in_sync == false) { rrc_log->info("Neighbour PCI=%d is out-of-sync. Deleting\n", (*it)->get_pci()); - it = delete_neighbour(it); + it = neighbour_cells.erase(it); } else { ++it; } } - std::sort(neighbour_cells.begin(), neighbour_cells.end(), sort_rsrp); + std::sort(std::begin(neighbour_cells), std::end(neighbour_cells), [](const unique_cell_t& a, const unique_cell_t& b) { + return a->greater(b.get()); + }); if (neighbour_cells.size() > 0) { - char ordered[512]; - int n=0; + char ordered[512] = {}; + int n = 0; n += snprintf(ordered, 512, "[earfcn=%d, pci=%d, rsrp=%.2f", @@ -667,20 +612,24 @@ void rrc::sort_neighbour_cells() } } -bool rrc::add_neighbour_cell(cell_t *new_cell) { +bool rrc::add_neighbour_cell(unique_cell_t new_cell) +{ bool ret = false; if (neighbour_cells.size() < NOF_NEIGHBOUR_CELLS) { ret = true; - } else if (new_cell->greater(neighbour_cells[neighbour_cells.size()-1])) { - // Replace old one by new one - delete_neighbour(neighbour_cells.size()-1); + } else if (new_cell->greater(neighbour_cells.back().get())) { + // delete last neighbour cell + delete_last_neighbour(); ret = true; } if (ret) { - neighbour_cells.push_back(new_cell); + rrc_log->info("Adding neighbour cell EARFCN=%d, PCI=%d, nof_neighbours=%zd\n", + new_cell->get_earfcn(), + new_cell->get_pci(), + neighbour_cells.size() + 1); + neighbour_cells.push_back(std::move(new_cell)); } - rrc_log->info("Added neighbour cell EARFCN=%d, PCI=%d, nof_neighbours=%zd\n", - new_cell->get_earfcn(), new_cell->get_pci(), neighbour_cells.size()); + sort_neighbour_cells(); return ret; } @@ -700,35 +649,45 @@ bool rrc::add_neighbour_cell(uint32_t earfcn, uint32_t pci, float rsrp) bool rrc::add_neighbour_cell(phy_interface_rrc_lte::phy_cell_t phy_cell, float rsrp) { - if (phy_cell.earfcn == 0) { - phy_cell.earfcn = serving_cell->get_earfcn(); - } - - // First check if already exists - int cell_idx = find_neighbour_cell(phy_cell.earfcn, phy_cell.cell.id); - - rrc_log->info("Adding PCI=%d, earfcn=%d, cell_idx=%d\n", phy_cell.cell.id, phy_cell.earfcn, cell_idx); - - // If exists, update RSRP if provided, sort again and return - if (cell_idx >= 0 && std::isnormal(rsrp)) { - neighbour_cells[cell_idx]->set_rsrp(rsrp); + // if cell exists, update RSRP, if provided, sort again and return + cell_t* cell = get_neighbour_cell_handle(phy_cell.earfcn, phy_cell.cell.id); + if (cell && std::isnormal(rsrp)) { + cell->set_rsrp(rsrp); sort_neighbour_cells(); return true; } - // If not, create a new one - cell_t *new_cell = new cell_t(phy_cell, rsrp); + // if cell doesn't exist, add it + return add_neighbour_cell(unique_cell_t(new cell_t(phy_cell, rsrp))); +} - return add_neighbour_cell(new_cell); +// This will remove the cell from the current neighbour list +rrc::unique_cell_t rrc::remove_neighbour_cell(const uint32_t earfcn, const uint32_t pci) +{ + auto it = find_if(neighbour_cells.begin(), neighbour_cells.end(), [&](const unique_cell_t& cell) { + return cell->equals(earfcn, pci); + }); + if (it != neighbour_cells.end()) { + auto retval = std::move(*it); + it = neighbour_cells.erase(it); + return retval; + } + return nullptr; } -int rrc::find_neighbour_cell(uint32_t earfcn, uint32_t pci) { - for (uint32_t i = 0; i < neighbour_cells.size(); i++) { - if (neighbour_cells[i]->equals(earfcn, pci)) { - return (int) i; +cell_t* rrc::get_neighbour_cell_handle(const uint32_t earfcn, const uint32_t pci) +{ + for (auto& cell : neighbour_cells) { + if (cell->equals(earfcn, pci)) { + return cell.get(); } } - return -1; + return nullptr; +} + +bool rrc::has_neighbour_cell(const uint32_t earfcn, const uint32_t pci) +{ + return get_neighbour_cell_handle(earfcn, pci) != nullptr; } /******************************************************************************* @@ -1067,8 +1026,8 @@ bool rrc::ho_prepare() uint32_t target_earfcn = (mob_ctrl_info->carrier_freq_present) ? mob_ctrl_info->carrier_freq.dl_carrier_freq : serving_cell->get_earfcn(); - int target_cell_idx = find_neighbour_cell(target_earfcn, mob_ctrl_info->target_pci); - if (target_cell_idx < 0) { + + if (not has_neighbour_cell(target_earfcn, mob_ctrl_info->target_pci)) { rrc_log->console("Received HO command to unknown PCI=%d\n", mob_ctrl_info->target_pci); rrc_log->error("Could not find target cell earfcn=%d, pci=%d\n", serving_cell->get_earfcn(), mob_ctrl_info->target_pci); @@ -1103,13 +1062,14 @@ bool rrc::ho_prepare() apply_rr_config_dedicated(&mob_reconf_r8->rr_cfg_ded); } - if (!phy->cell_select(&neighbour_cells[target_cell_idx]->phy_cell)) { + cell_t* target_cell = get_neighbour_cell_handle(target_earfcn, mob_ctrl_info->target_pci); + if (!phy->cell_select(&target_cell->phy_cell)) { rrc_log->error("Could not synchronize with target cell pci=%d. Trying to return to source PCI\n", - neighbour_cells[target_cell_idx]->get_pci()); + target_cell->get_pci()); return false; } - set_serving_cell(target_cell_idx); + set_serving_cell(target_cell->phy_cell); // Extract and apply scell config if any apply_scell_config(mob_reconf_r8); diff --git a/srsue/src/stack/rrc/rrc_procedures.cc b/srsue/src/stack/rrc/rrc_procedures.cc index ae9f84edc..facde57eb 100644 --- a/srsue/src/stack/rrc/rrc_procedures.cc +++ b/srsue/src/stack/rrc/rrc_procedures.cc @@ -340,27 +340,29 @@ proc_outcome_t rrc::cell_selection_proc::step_cell_selection() for (; neigh_index < rrc_ptr->neighbour_cells.size(); ++neigh_index) { /*TODO: CHECK that PLMN matches. Currently we don't receive SIB1 of neighbour cells * neighbour_cells[i]->plmn_equals(selected_plmn_id) && */ - if (rrc_ptr->neighbour_cells[neigh_index]->in_sync) { + if (rrc_ptr->neighbour_cells.at(neigh_index)->in_sync) { // Matches S criteria - float rsrp = rrc_ptr->neighbour_cells[neigh_index]->get_rsrp(); - cell_t* serv_cell = rrc_ptr->serving_cell; - if (not serv_cell->in_sync or + float rsrp = rrc_ptr->neighbour_cells.at(neigh_index)->get_rsrp(); + + if (not rrc_ptr->serving_cell->in_sync or (rrc_ptr->cell_selection_criteria(rsrp) and rsrp > rrc_ptr->serving_cell->get_rsrp() + 5)) { // currently connected and verifies cell selection criteria // Try to select Cell - rrc_ptr->set_serving_cell(neigh_index); - Info("Selected cell idx=%d, PCI=%d, EARFCN=%d\n", neigh_index, serv_cell->get_pci(), serv_cell->get_earfcn()); - log_h->console("Selected cell PCI=%d, EARFCN=%d\n", serv_cell->get_pci(), serv_cell->get_earfcn()); + rrc_ptr->set_serving_cell(rrc_ptr->neighbour_cells.at(neigh_index)->phy_cell); + Info( + "Selected cell PCI=%d, EARFCN=%d\n", rrc_ptr->serving_cell->get_pci(), rrc_ptr->serving_cell->get_earfcn()); + log_h->console( + "Selected cell PCI=%d, EARFCN=%d\n", rrc_ptr->serving_cell->get_pci(), rrc_ptr->serving_cell->get_earfcn()); /* BLOCKING CALL */ - if (rrc_ptr->phy->cell_select(&serv_cell->phy_cell)) { + if (rrc_ptr->phy->cell_select(&rrc_ptr->serving_cell->phy_cell)) { if (not rrc_ptr->serv_cell_cfg.launch(rrc_ptr, rrc_ptr->ue_required_sibs)) { return proc_outcome_t::error; } state = search_state_t::cell_config; return proc_outcome_t::repeat; } else { - serv_cell->in_sync = false; + rrc_ptr->serving_cell->in_sync = false; Error("Could not camp on serving cell.\n"); // Continue to next neighbour cell }