From 045f647914243dfd4dc3fdec94ecc3f8b7ae039b Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Mon, 28 Sep 2020 20:42:21 +0100 Subject: [PATCH] fix edge case where serving cell is good enough for reestablishment but the sibs are not yet acquired --- srsue/hdr/stack/rrc/rrc.h | 2 +- srsue/hdr/stack/rrc/rrc_cell.h | 1 + srsue/hdr/stack/rrc/rrc_procedures.h | 9 +++---- srsue/src/stack/rrc/rrc.cc | 20 ++++---------- srsue/src/stack/rrc/rrc_cell.cc | 10 +++++++ srsue/src/stack/rrc/rrc_procedures.cc | 39 +++++++++++++++++++-------- 6 files changed, 49 insertions(+), 32 deletions(-) diff --git a/srsue/hdr/stack/rrc/rrc.h b/srsue/hdr/stack/rrc/rrc.h index 14a77ec59..cdd813503 100644 --- a/srsue/hdr/stack/rrc/rrc.h +++ b/srsue/hdr/stack/rrc/rrc.h @@ -329,7 +329,7 @@ private: // Senders void send_con_request(srslte::establishment_cause_t cause); - void send_con_restablish_request(asn1::rrc::reest_cause_e cause, uint16_t rnti, uint16_t pci); + void send_con_restablish_request(asn1::rrc::reest_cause_e cause, uint16_t rnti, uint16_t pci, uint32_t cellid); void send_con_restablish_complete(); void send_con_setup_complete(srslte::unique_byte_buffer_t nas_msg); void send_ul_info_transfer(srslte::unique_byte_buffer_t nas_msg); diff --git a/srsue/hdr/stack/rrc/rrc_cell.h b/srsue/hdr/stack/rrc/rrc_cell.h index b497610a6..a104efd84 100644 --- a/srsue/hdr/stack/rrc/rrc_cell.h +++ b/srsue/hdr/stack/rrc/rrc_cell.h @@ -89,6 +89,7 @@ public: uint32_t get_cell_id() const { return (uint32_t)sib1.cell_access_related_info.cell_id.to_number(); } + bool has_sibs(srslte::span indexes) const; bool has_sib(uint32_t index) const; bool has_sib1() const { return has_valid_sib1; } bool has_sib2() const { return has_valid_sib2; } diff --git a/srsue/hdr/stack/rrc/rrc_procedures.h b/srsue/hdr/stack/rrc/rrc_procedures.h index 1c25be23e..683204a30 100644 --- a/srsue/hdr/stack/rrc/rrc_procedures.h +++ b/srsue/hdr/stack/rrc/rrc_procedures.h @@ -286,11 +286,10 @@ public: private: enum class state_t { wait_cell_selection, wait_reest_msg } state; - rrc* rrc_ptr = nullptr; - asn1::rrc::reest_cause_e reest_cause = asn1::rrc::reest_cause_e::nulltype; - uint16_t reest_rnti = 0; - uint16_t reest_source_pci = 0; - uint32_t reest_source_freq = 0; + rrc* rrc_ptr = nullptr; + asn1::rrc::reest_cause_e reest_cause = asn1::rrc::reest_cause_e::nulltype; + uint16_t reest_rnti = 0, reest_source_pci = 0; + uint32_t reest_source_freq = 0, reest_cellid = 0; bool passes_cell_criteria() const; srslte::proc_outcome_t cell_criteria(); diff --git a/srsue/src/stack/rrc/rrc.cc b/srsue/src/stack/rrc/rrc.cc index ca666cc24..c529169ed 100644 --- a/srsue/src/stack/rrc/rrc.cc +++ b/srsue/src/stack/rrc/rrc.cc @@ -723,25 +723,11 @@ void rrc::send_con_request(srslte::establishment_cause_t cause) } /* RRC connection re-establishment procedure (5.3.7.4) */ -void rrc::send_con_restablish_request(reest_cause_e cause, uint16_t crnti, uint16_t pci) +void rrc::send_con_restablish_request(reest_cause_e cause, uint16_t crnti, uint16_t pci, uint32_t cellid) { - uint32_t cellid; - // Clean reestablishment type reestablishment_successful = false; - if (cause == reest_cause_e::ho_fail) { - crnti = ho_handler.get()->ho_src_rnti; - pci = ho_handler.get()->ho_src_cell.get_pci(); - cellid = ho_handler.get()->ho_src_cell.get_cell_id(); - } else if (cause == reest_cause_e::other_fail) { - // use source PCI after RLF - cellid = meas_cells.serving_cell().get_cell_id(); - } else { - pci = meas_cells.serving_cell().get_pci(); - cellid = meas_cells.serving_cell().get_cell_id(); - } - // Compute shortMAC-I uint8_t varShortMAC_packed[16] = {}; asn1::bit_ref bref(varShortMAC_packed, sizeof(varShortMAC_packed)); @@ -806,6 +792,10 @@ void rrc::send_con_restablish_request(reest_cause_e cause, uint16_t crnti, uint1 meas_cells.serving_cell().phy_cell.pci, meas_cells.serving_cell().phy_cell.earfcn, cause.to_string().c_str()); + rrc_log->info("RRC Connection Reestablishment to PCI=%d, EARFCN=%d (Cause: \"%s\")\n", + meas_cells.serving_cell().phy_cell.pci, + meas_cells.serving_cell().phy_cell.earfcn, + cause.to_string().c_str()); send_ul_ccch_msg(ul_ccch_msg); } diff --git a/srsue/src/stack/rrc/rrc_cell.cc b/srsue/src/stack/rrc/rrc_cell.cc index 40334be20..17add2995 100644 --- a/srsue/src/stack/rrc/rrc_cell.cc +++ b/srsue/src/stack/rrc/rrc_cell.cc @@ -75,6 +75,16 @@ uint32_t cell_t::timeout_secs(struct timeval now) const return t[0].tv_sec; } +bool cell_t::has_sibs(srslte::span indexes) const +{ + for (uint32_t idx : indexes) { + if (not has_sib(idx)) { + return false; + } + } + return true; +} + bool cell_t::has_sib(uint32_t index) const { switch (index) { diff --git a/srsue/src/stack/rrc/rrc_procedures.cc b/srsue/src/stack/rrc/rrc_procedures.cc index 2064db70b..7cefd77c5 100644 --- a/srsue/src/stack/rrc/rrc_procedures.cc +++ b/srsue/src/stack/rrc/rrc_procedures.cc @@ -456,8 +456,9 @@ rrc::cell_selection_proc::cell_selection_proc(rrc* parent_) : rrc_ptr(parent_) { */ proc_outcome_t rrc::cell_selection_proc::init(std::vector required_sibs_) { - if (rrc_ptr->meas_cells.nof_neighbours() == 0 and rrc_ptr->phy_ctrl->is_in_sync() and - rrc_ptr->phy->cell_is_camping()) { + bool serv_cell_is_ok = rrc_ptr->phy_ctrl->is_in_sync() and rrc_ptr->phy->cell_is_camping(); + if (rrc_ptr->meas_cells.nof_neighbours() == 0 and serv_cell_is_ok and + rrc_ptr->meas_cells.serving_cell().has_sibs(required_sibs_)) { // don't bother with cell selection if there are no neighbours and we are already camping Debug("Skipping Cell Selection Procedure as there are no neighbour and cell is camping.\n"); cs_result = cs_result_t::same_cell; @@ -480,8 +481,16 @@ proc_outcome_t rrc::cell_selection_proc::init(std::vector required_sib } else { required_sibs = std::move(required_sibs_); } - neigh_index = 0; - cs_result = cs_result_t::no_cell; + neigh_index = 0; + cs_result = cs_result_t::no_cell; + if (serv_cell_is_ok) { + state = search_state_t::cell_config; + if (not rrc_ptr->serv_cell_cfg.launch(&serv_cell_cfg_fut, required_sibs)) { + Warning("Failed to launch %s procedure\n", rrc_ptr->serv_cell_cfg.get()->name()); + return proc_outcome_t::error; + } + return proc_outcome_t::yield; + } state = search_state_t::cell_selection; discard_serving = false; serv_cell_select_attempted = false; @@ -1159,18 +1168,26 @@ proc_outcome_t rrc::connection_reest_proc::init(asn1::rrc::reest_cause_e cause) } // Save reestablishment Cause and current C-RNTI context - reest_rnti = uernti.crnti; - reest_cause = cause; - reest_source_pci = rrc_ptr->meas_cells.serving_cell().get_pci(); // needed for reestablishment with another cell - reest_source_freq = rrc_ptr->meas_cells.serving_cell().get_earfcn(); + reest_cause = cause; + if (reest_cause.value == reest_cause_opts::ho_fail) { + reest_rnti = rrc_ptr->ho_handler.get()->ho_src_rnti; + reest_source_pci = rrc_ptr->ho_handler.get()->ho_src_cell.get_pci(); + reest_cellid = rrc_ptr->ho_handler.get()->ho_src_cell.get_cell_id(); + reest_source_freq = rrc_ptr->ho_handler.get()->ho_src_cell.get_earfcn(); + } else { + reest_rnti = uernti.crnti; + reest_source_pci = rrc_ptr->meas_cells.serving_cell().get_pci(); // needed for reestablishment with another cell + reest_cellid = rrc_ptr->meas_cells.serving_cell().get_cell_id(); + reest_source_freq = rrc_ptr->meas_cells.serving_cell().get_earfcn(); + } - Info("Starting... cause: \"%s\", UE context: {C-RNTI=0x%x, PCI=%d, DL-EARFCN=%d}\n", + Info("Starting... cause: \"%s\", UE context: {C-RNTI=0x%x, PCI=%d, CELL ID=%d}\n", reest_cause == asn1::rrc::reest_cause_opts::recfg_fail ? "Reconfiguration failure" : cause == asn1::rrc::reest_cause_opts::ho_fail ? "Handover failure" : "Other failure", reest_rnti, reest_source_pci, - reest_source_freq); + reest_cellid); // 5.3.7.2 - Initiation @@ -1240,7 +1257,7 @@ srslte::proc_outcome_t rrc::connection_reest_proc::cell_criteria() // Not implemented yet. // 1> initiate transmission of the RRCConnectionReestablishmentRequest message in accordance with 5.3.7.4; - rrc_ptr->send_con_restablish_request(reest_cause, reest_rnti, reest_source_pci); + rrc_ptr->send_con_restablish_request(reest_cause, reest_rnti, reest_source_pci, reest_cellid); state = state_t::wait_reest_msg; return proc_outcome_t::yield;