diff --git a/srsue/hdr/stack/rrc/rrc.h b/srsue/hdr/stack/rrc/rrc.h index 2b13b4596..899c94892 100644 --- a/srsue/hdr/stack/rrc/rrc.h +++ b/srsue/hdr/stack/rrc/rrc.h @@ -22,6 +22,7 @@ #ifndef SRSUE_RRC_H #define SRSUE_RRC_H +#include "rrc_cell.h" #include "rrc_common.h" #include "rrc_metrics.h" #include "srslte/asn1/rrc_asn1.h" @@ -65,215 +66,6 @@ using srslte::byte_buffer_t; namespace srsue { -class cell_t -{ -public: - bool is_valid() { return phy_cell.earfcn != 0 && srslte_cellid_isvalid(phy_cell.pci); } - bool equals(cell_t* x) { return equals(x->phy_cell.earfcn, x->phy_cell.pci); } - bool equals(uint32_t earfcn, uint32_t pci) { return earfcn == phy_cell.earfcn && pci == phy_cell.pci; } - // NaN means an RSRP value has not yet been obtained. Keep then in the list and clean them if never updated - bool greater(cell_t* x) { return rsrp > x->rsrp || std::isnan(rsrp); } - bool plmn_equals(asn1::rrc::plmn_id_s plmn_id) - { - if (has_valid_sib1) { - for (uint32_t i = 0; i < sib1.cell_access_related_info.plmn_id_list.size(); i++) { - if (plmn_id.mcc == sib1.cell_access_related_info.plmn_id_list[i].plmn_id.mcc && - plmn_id.mnc == sib1.cell_access_related_info.plmn_id_list[i].plmn_id.mnc) { - return true; - } - } - } - return false; - } - - uint32_t nof_plmns() - { - if (has_valid_sib1) { - return sib1.cell_access_related_info.plmn_id_list.size(); - } else { - return 0; - } - } - - srslte::plmn_id_t get_plmn(uint32_t idx) - { - if (idx < sib1.cell_access_related_info.plmn_id_list.size() && has_valid_sib1) { - return srslte::make_plmn_id_t(sib1.cell_access_related_info.plmn_id_list[idx].plmn_id); - } else { - return {}; - } - } - - uint16_t get_tac() - { - if (has_valid_sib1) { - return (uint16_t)sib1.cell_access_related_info.tac.to_number(); - } else { - return 0; - } - } - - cell_t() - { - gettimeofday(&last_update, nullptr); - has_valid_sib1 = false; - has_valid_sib2 = false; - has_valid_sib3 = false; - has_valid_sib13 = false; - phy_cell = {0, 0, 0}; - rsrp = NAN; - rsrq = NAN; - sib1 = {}; - sib2 = {}; - sib3 = {}; - sib13 = {}; - } - - cell_t(phy_interface_rrc_lte::phy_cell_t phy_cell_) : cell_t() { phy_cell = phy_cell_; } - - uint32_t get_earfcn() const { return phy_cell.earfcn; } - - uint32_t get_pci() const { return phy_cell.pci; } - - void set_rsrp(float rsrp_) - { - if (!std::isnan(rsrp_)) { - rsrp = rsrp_; - } - gettimeofday(&last_update, nullptr); - } - void set_rsrq(float rsrq_) - { - if (!std::isnan(rsrq_)) { - rsrq = rsrq_; - } - } - void set_cfo(float cfo_Hz_) - { - if (not std::isnan(cfo_Hz_) && not std::isinf(cfo_Hz_)) { - phy_cell.cfo_hz = cfo_Hz_; - } - } - - float get_rsrp() const { return rsrp; } - float get_rsrq() const { return rsrq; } - float get_cfo_hz() const { return phy_cell.cfo_hz; } - - void set_sib1(asn1::rrc::sib_type1_s* sib1_); - void set_sib2(asn1::rrc::sib_type2_s* sib2_); - void set_sib3(asn1::rrc::sib_type3_s* sib3_); - void set_sib13(asn1::rrc::sib_type13_r9_s* sib13_); - - // TODO: replace with TTI count - uint32_t timeout_secs(struct timeval now) - { - struct timeval t[3]; - memcpy(&t[2], &now, sizeof(struct timeval)); - memcpy(&t[1], &last_update, sizeof(struct timeval)); - get_time_interval(t); - return t[0].tv_sec; - } - - asn1::rrc::sib_type1_s* sib1ptr() { return &sib1; } - asn1::rrc::sib_type2_s* sib2ptr() { return &sib2; } - asn1::rrc::sib_type3_s* sib3ptr() { return &sib3; } - asn1::rrc::sib_type13_r9_s* sib13ptr() { return &sib13; } - - uint32_t get_cell_id() const { return (uint32_t)sib1.cell_access_related_info.cell_id.to_number(); } - - bool has_sib1() { return has_valid_sib1; } - bool has_sib2() { return has_valid_sib2; } - bool has_sib3() { return has_valid_sib3; } - bool has_sib13() { return has_valid_sib13; } - - bool has_sib(uint32_t index) - { - switch (index) { - case 0: - return has_sib1(); - case 1: - return has_sib2(); - case 2: - return has_sib3(); - case 12: - return has_sib13(); - } - return false; - } - - void reset_sibs() - { - has_valid_sib1 = false; - has_valid_sib2 = false; - has_valid_sib3 = false; - has_valid_sib13 = false; - } - - uint16_t get_mcc() - { - uint16_t mcc; - if (has_valid_sib1) { - if (sib1.cell_access_related_info.plmn_id_list.size() > 0) { - if (srslte::bytes_to_mcc(&sib1.cell_access_related_info.plmn_id_list[0].plmn_id.mcc[0], &mcc)) { - return mcc; - } - } - } - return 0; - } - - uint16_t get_mnc() - { - uint16_t mnc; - if (has_valid_sib1) { - if (sib1.cell_access_related_info.plmn_id_list.size() > 0) { - if (srslte::bytes_to_mnc(&sib1.cell_access_related_info.plmn_id_list[0].plmn_id.mnc[0], - &mnc, - sib1.cell_access_related_info.plmn_id_list[0].plmn_id.mnc.size())) { - return mnc; - } - } - } - return 0; - } - - std::string to_string() const - { - char buf[256]; - snprintf(buf, - 256, - "{cell_id: 0x%x, pci: %d, dl_earfcn: %d, rsrp=%+.1f, cfo=%+.1f}", - get_cell_id(), - get_pci(), - get_earfcn(), - get_rsrp(), - get_cfo_hz()); - return std::string{buf}; - } - - bool is_sib_scheduled(uint32_t sib_index) const; - - phy_interface_rrc_lte::phy_cell_t phy_cell = {}; - bool has_mcch = false; - asn1::rrc::sib_type1_s sib1; - asn1::rrc::sib_type2_s sib2; - asn1::rrc::sib_type3_s sib3; - asn1::rrc::sib_type13_r9_s sib13; - asn1::rrc::mcch_msg_s mcch; - -private: - float rsrp = NAN; - float rsrq = NAN; - - struct timeval last_update = {}; - - bool has_valid_sib1 = false; - bool has_valid_sib2 = false; - bool has_valid_sib3 = false; - bool has_valid_sib13 = false; - std::map sib_info_map; ///< map of sib_index to index of schedInfoList in SIB1 -}; - class rrc : public rrc_interface_nas, public rrc_interface_phy_lte, public rrc_interface_mac, @@ -299,7 +91,7 @@ public: void get_metrics(rrc_metrics_t& m); // Timeout callback interface - void timer_expired(uint32_t timeout_id); + void timer_expired(uint32_t timeout_id) final; void srslte_rrc_log(const char* str); typedef enum { Rx = 0, Tx } direction_t; diff --git a/srsue/hdr/stack/rrc/rrc_cell.h b/srsue/hdr/stack/rrc/rrc_cell.h new file mode 100644 index 000000000..c0d4d3fef --- /dev/null +++ b/srsue/hdr/stack/rrc/rrc_cell.h @@ -0,0 +1,136 @@ +/* + * Copyright 2013-2020 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#ifndef SRSLTE_RRC_CELL_H +#define SRSLTE_RRC_CELL_H + +#include "srslte/asn1/rrc_asn1.h" +#include "srslte/asn1/rrc_asn1_utils.h" +#include "srslte/interfaces/ue_interfaces.h" + +namespace srsue { + +class cell_t +{ +public: + cell_t() { gettimeofday(&last_update, nullptr); } + explicit cell_t(phy_interface_rrc_lte::phy_cell_t phy_cell_) : cell_t() { phy_cell = phy_cell_; } + + // comparison based on pci and earfcn + bool is_valid() { return phy_cell.earfcn != 0 && srslte_cellid_isvalid(phy_cell.pci); } + bool equals(const cell_t& x) { return equals(x.phy_cell.earfcn, x.phy_cell.pci); } + bool equals(uint32_t earfcn, uint32_t pci) { return earfcn == phy_cell.earfcn && pci == phy_cell.pci; } + + // NaN means an RSRP value has not yet been obtained. Keep then in the list and clean them if never updated + bool greater(cell_t* x) { return rsrp > x->rsrp || std::isnan(rsrp); } + + bool has_plmn_id(asn1::rrc::plmn_id_s plmn_id) const; + uint32_t nof_plmns() const { return has_sib1() ? sib1.cell_access_related_info.plmn_id_list.size() : 0; } + srslte::plmn_id_t get_plmn(uint32_t idx) const; + + uint16_t get_tac() const { return has_sib1() ? (uint16_t)sib1.cell_access_related_info.tac.to_number() : 0; } + uint32_t get_earfcn() const { return phy_cell.earfcn; } + uint32_t get_pci() const { return phy_cell.pci; } + + void set_rsrp(float rsrp_) + { + if (!std::isnan(rsrp_)) { + rsrp = rsrp_; + } + gettimeofday(&last_update, nullptr); + } + void set_rsrq(float rsrq_) + { + if (!std::isnan(rsrq_)) { + rsrq = rsrq_; + } + } + void set_cfo(float cfo_Hz_) + { + if (not std::isnan(cfo_Hz_) && not std::isinf(cfo_Hz_)) { + phy_cell.cfo_hz = cfo_Hz_; + } + } + + float get_rsrp() const { return rsrp; } + float get_rsrq() const { return rsrq; } + float get_cfo_hz() const { return phy_cell.cfo_hz; } + + // TODO: replace with TTI count + uint32_t timeout_secs(struct timeval now) const; + + void set_sib1(const asn1::rrc::sib_type1_s& sib1_); + void set_sib2(const asn1::rrc::sib_type2_s& sib2_); + void set_sib3(const asn1::rrc::sib_type3_s& sib3_); + void set_sib13(const asn1::rrc::sib_type13_r9_s& sib13_); + + const asn1::rrc::sib_type1_s* sib1ptr() const { return has_sib1() ? &sib1 : nullptr; } + const asn1::rrc::sib_type2_s* sib2ptr() const { return has_sib2() ? &sib2 : nullptr; } + const asn1::rrc::sib_type3_s* sib3ptr() const { return has_sib3() ? &sib3 : nullptr; } + const asn1::rrc::sib_type13_r9_s* sib13ptr() const { return has_sib13() ? &sib13 : nullptr; } + + uint32_t get_cell_id() const { return (uint32_t)sib1.cell_access_related_info.cell_id.to_number(); } + + bool has_sib(uint32_t index) const; + bool has_sib1() const { return has_valid_sib1; } + bool has_sib2() const { return has_valid_sib2; } + bool has_sib3() const { return has_valid_sib3; } + bool has_sib13() const { return has_valid_sib13; } + + void reset_sibs() + { + has_valid_sib1 = false; + has_valid_sib2 = false; + has_valid_sib3 = false; + has_valid_sib13 = false; + } + + uint16_t get_mcc() const; + uint16_t get_mnc() const; + + std::string to_string() const; + + bool is_sib_scheduled(uint32_t sib_index) const; + + phy_interface_rrc_lte::phy_cell_t phy_cell = {0, 0, 0}; + bool has_mcch = false; + asn1::rrc::sib_type1_s sib1 = {}; + asn1::rrc::sib_type2_s sib2 = {}; + asn1::rrc::sib_type3_s sib3 = {}; + asn1::rrc::sib_type13_r9_s sib13 = {}; + asn1::rrc::mcch_msg_s mcch = {}; + +private: + float rsrp = NAN; + float rsrq = NAN; + + struct timeval last_update = {}; + + bool has_valid_sib1 = false; + bool has_valid_sib2 = false; + bool has_valid_sib3 = false; + bool has_valid_sib13 = false; + std::map sib_info_map; ///< map of sib_index to index of schedInfoList in SIB1 +}; + +} // namespace srsue + +#endif // SRSLTE_RRC_CELL_H diff --git a/srsue/src/stack/rrc/CMakeLists.txt b/srsue/src/stack/rrc/CMakeLists.txt index 1e5391fab..2f5ac82b3 100644 --- a/srsue/src/stack/rrc/CMakeLists.txt +++ b/srsue/src/stack/rrc/CMakeLists.txt @@ -18,7 +18,7 @@ # and at http://www.gnu.org/licenses/. # -set(SOURCES rrc.cc rrc_procedures.cc rrc_meas.cc) +set(SOURCES rrc.cc rrc_procedures.cc rrc_meas.cc rrc_cell.cc) add_library(srsue_rrc STATIC ${SOURCES}) if(ENABLE_5GNR) diff --git a/srsue/src/stack/rrc/rrc.cc b/srsue/src/stack/rrc/rrc.cc index 4624839d3..7abb2e375 100644 --- a/srsue/src/stack/rrc/rrc.cc +++ b/srsue/src/stack/rrc/rrc.cc @@ -45,40 +45,6 @@ namespace srsue { const static uint32_t NOF_REQUIRED_SIBS = 4; const static uint32_t required_sibs[NOF_REQUIRED_SIBS] = {0, 1, 2, 12}; // SIB1, SIB2, SIB3 and SIB13 (eMBMS) -void cell_t::set_sib1(asn1::rrc::sib_type1_s* sib1_) -{ - sib1 = *sib1_; - has_valid_sib1 = true; - - sib_info_map.clear(); - for (uint32_t i = 0; i < sib1.sched_info_list.size(); ++i) { - for (uint32_t j = 0; j < sib1.sched_info_list[i].sib_map_info.size(); ++j) { - sib_info_map.insert(std::make_pair(sib1.sched_info_list[i].sib_map_info[j].to_number() - 1, i)); - } - } -} - -void cell_t::set_sib2(asn1::rrc::sib_type2_s* sib2_) -{ - sib2 = *sib2_; - has_valid_sib2 = true; -} -void cell_t::set_sib3(asn1::rrc::sib_type3_s* sib3_) -{ - sib3 = *sib3_; - has_valid_sib3 = true; -} -void cell_t::set_sib13(asn1::rrc::sib_type13_r9_s* sib13_) -{ - sib13 = *sib13_; - has_valid_sib13 = true; -} - -bool cell_t::is_sib_scheduled(uint32_t sib_index) const -{ - return sib_info_map.find(sib_index) != sib_info_map.end(); -} - /******************************************************************************* Base functions *******************************************************************************/ @@ -1361,7 +1327,7 @@ void rrc::parse_pdu_bcch_dlsch(unique_byte_buffer_t pdu) if (dlsch_msg.msg.c1().type() == bcch_dl_sch_msg_type_c::c1_c_::types::sib_type1) { rrc_log->info("Processing SIB1 (1/1)\n"); - serving_cell->set_sib1(&dlsch_msg.msg.c1().sib_type1()); + serving_cell->set_sib1(dlsch_msg.msg.c1().sib_type1()); si_acquirer.trigger(si_acquire_proc::sib_received_ev{}); handle_sib1(); } else { @@ -1372,21 +1338,21 @@ void rrc::parse_pdu_bcch_dlsch(unique_byte_buffer_t pdu) switch (sib_list[i].type().value) { case sib_info_item_c::types::sib2: if (not serving_cell->has_sib2()) { - serving_cell->set_sib2(&sib_list[i].sib2()); + serving_cell->set_sib2(sib_list[i].sib2()); si_acquirer.trigger(si_acquire_proc::sib_received_ev{}); } handle_sib2(); break; case sib_info_item_c::types::sib3: if (not serving_cell->has_sib3()) { - serving_cell->set_sib3(&sib_list[i].sib3()); + serving_cell->set_sib3(sib_list[i].sib3()); si_acquirer.trigger(si_acquire_proc::sib_received_ev{}); } handle_sib3(); break; case sib_info_item_c::types::sib13_v920: if (not serving_cell->has_sib13()) { - serving_cell->set_sib13(&sib_list[i].sib13_v920()); + serving_cell->set_sib13(sib_list[i].sib13_v920()); si_acquirer.trigger(si_acquire_proc::sib_received_ev{}); } handle_sib13(); @@ -1400,7 +1366,7 @@ void rrc::parse_pdu_bcch_dlsch(unique_byte_buffer_t pdu) void rrc::handle_sib1() { - sib_type1_s* sib1 = serving_cell->sib1ptr(); + const sib_type1_s* sib1 = serving_cell->sib1ptr(); rrc_log->info("SIB1 received, CellID=%d, si_window=%d, sib2_period=%d\n", serving_cell->get_cell_id() & 0xfff, sib1->si_win_len.to_number(), @@ -1428,7 +1394,7 @@ void rrc::handle_sib2() { rrc_log->info("SIB2 received\n"); - sib_type2_s* sib2 = serving_cell->sib2ptr(); + const sib_type2_s* sib2 = serving_cell->sib2ptr(); // Apply RACH and timeAlginmentTimer configuration set_mac_cfg_t_rach_cfg_common(¤t_mac_cfg, sib2->rr_cfg_common.rach_cfg_common); @@ -1496,7 +1462,7 @@ void rrc::handle_sib3() { rrc_log->info("SIB3 received\n"); - sib_type3_s* sib3 = serving_cell->sib3ptr(); + const sib_type3_s* sib3 = serving_cell->sib3ptr(); // cellReselectionInfoCommon cell_resel_cfg.q_hyst = sib3->cell_resel_info_common.q_hyst.to_number(); @@ -1517,7 +1483,7 @@ void rrc::handle_sib13() { rrc_log->info("SIB13 received\n"); - sib_type13_r9_s* sib13 = serving_cell->sib13ptr(); + const sib_type13_r9_s* sib13 = serving_cell->sib13ptr(); phy->set_config_mbsfn_sib13(srslte::make_sib13(*sib13)); add_mrb(0, 0); // Add MRB0 diff --git a/srsue/src/stack/rrc/rrc_cell.cc b/srsue/src/stack/rrc/rrc_cell.cc new file mode 100644 index 000000000..2cfa8a0b6 --- /dev/null +++ b/srsue/src/stack/rrc/rrc_cell.cc @@ -0,0 +1,149 @@ +/* + * Copyright 2013-2020 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include "srsue/hdr/stack/rrc/rrc_cell.h" + +namespace srsue { + +srslte::plmn_id_t cell_t::get_plmn(uint32_t idx) const +{ + if (idx < sib1.cell_access_related_info.plmn_id_list.size() && has_valid_sib1) { + return srslte::make_plmn_id_t(sib1.cell_access_related_info.plmn_id_list[idx].plmn_id); + } else { + return {}; + } +} + +void cell_t::set_sib1(const asn1::rrc::sib_type1_s& sib1_) +{ + sib1 = sib1_; + has_valid_sib1 = true; + + sib_info_map.clear(); + for (uint32_t i = 0; i < sib1.sched_info_list.size(); ++i) { + for (uint32_t j = 0; j < sib1.sched_info_list[i].sib_map_info.size(); ++j) { + sib_info_map.insert(std::make_pair(sib1.sched_info_list[i].sib_map_info[j].to_number() - 1, i)); + } + } +} + +void cell_t::set_sib2(const asn1::rrc::sib_type2_s& sib2_) +{ + sib2 = sib2_; + has_valid_sib2 = true; +} +void cell_t::set_sib3(const asn1::rrc::sib_type3_s& sib3_) +{ + sib3 = sib3_; + has_valid_sib3 = true; +} +void cell_t::set_sib13(const asn1::rrc::sib_type13_r9_s& sib13_) +{ + sib13 = sib13_; + has_valid_sib13 = true; +} + +bool cell_t::is_sib_scheduled(uint32_t sib_index) const +{ + return sib_info_map.find(sib_index) != sib_info_map.end(); +} + +uint32_t cell_t::timeout_secs(struct timeval now) const +{ + struct timeval t[3]; + memcpy(&t[2], &now, sizeof(struct timeval)); + memcpy(&t[1], &last_update, sizeof(struct timeval)); + get_time_interval(t); + return t[0].tv_sec; +} + +bool cell_t::has_sib(uint32_t index) const +{ + switch (index) { + case 0: + return has_sib1(); + case 1: + return has_sib2(); + case 2: + return has_sib3(); + case 12: + return has_sib13(); + default: + break; + } + return false; +} + +std::string cell_t::to_string() const +{ + char buf[256]; + snprintf(buf, + 256, + "{cell_id: 0x%x, pci: %d, dl_earfcn: %d, rsrp=%+.1f, cfo=%+.1f}", + get_cell_id(), + get_pci(), + get_earfcn(), + get_rsrp(), + get_cfo_hz()); + return std::string{buf}; +} + +bool cell_t::has_plmn_id(asn1::rrc::plmn_id_s plmn_id) const +{ + if (has_valid_sib1) { + for (const auto& e : sib1.cell_access_related_info.plmn_id_list) { + if (plmn_id.mcc == e.plmn_id.mcc && plmn_id.mnc == e.plmn_id.mnc) { + return true; + } + } + } + return false; +} + +uint16_t cell_t::get_mcc() const +{ + uint16_t mcc; + if (has_valid_sib1) { + if (sib1.cell_access_related_info.plmn_id_list.size() > 0) { + if (srslte::bytes_to_mcc(&sib1.cell_access_related_info.plmn_id_list[0].plmn_id.mcc[0], &mcc)) { + return mcc; + } + } + } + return 0; +} + +uint16_t cell_t::get_mnc() const +{ + uint16_t mnc; + if (has_valid_sib1) { + if (sib1.cell_access_related_info.plmn_id_list.size() > 0) { + if (srslte::bytes_to_mnc(&sib1.cell_access_related_info.plmn_id_list[0].plmn_id.mnc[0], + &mnc, + sib1.cell_access_related_info.plmn_id_list[0].plmn_id.mnc.size())) { + return mnc; + } + } + } + return 0; +} + +} // namespace srsue diff --git a/srsue/src/stack/rrc/rrc_procedures.cc b/srsue/src/stack/rrc/rrc_procedures.cc index 835dfbbe9..b8981afb2 100644 --- a/srsue/src/stack/rrc/rrc_procedures.cc +++ b/srsue/src/stack/rrc/rrc_procedures.cc @@ -548,7 +548,7 @@ proc_outcome_t rrc::cell_selection_proc::start_serv_cell_selection() Info("Not camping on serving cell %s. Selecting it...\n", rrc_ptr->serving_cell->to_string().c_str()); state = search_state_t::serv_cell_camp; - if (not rrc_ptr->phy_cell_selector.launch(rrc_ptr->serving_cell->phy_cell)) { + if (not rrc_ptr->phy_cell_selector.launch(*rrc_ptr->serving_cell)) { Error("Failed to launch PHY Cell Selection\n"); return proc_outcome_t::error; } @@ -580,7 +580,7 @@ proc_outcome_t rrc::cell_selection_proc::start_cell_selection() Info("Selected cell: %s\n", rrc_ptr->serving_cell->to_string().c_str()); state = search_state_t::cell_selection; - if (not rrc_ptr->phy_cell_selector.launch(rrc_ptr->serving_cell->phy_cell)) { + if (not rrc_ptr->phy_cell_selector.launch(*rrc_ptr->serving_cell)) { Error("Failed to launch PHY Cell Selection\n"); return proc_outcome_t::error; }