fix+refactor of the ue rrc handover preparation procedure to avoid deadlocking

master
Francisco Paisana 5 years ago committed by Francisco Paisana
parent 960c0e97cd
commit 37ce475398

@ -113,13 +113,14 @@ public:
} }
} }
cell_t() { cell_t()
{
gettimeofday(&last_update, nullptr); gettimeofday(&last_update, nullptr);
has_valid_sib1 = false; has_valid_sib1 = false;
has_valid_sib2 = false; has_valid_sib2 = false;
has_valid_sib3 = false; has_valid_sib3 = false;
has_valid_sib13 = false; has_valid_sib13 = false;
phy_cell = {0,0,0}; phy_cell = {0, 0, 0};
rsrp = NAN; rsrp = NAN;
rsrq = NAN; rsrq = NAN;
sib1 = {}; sib1 = {};
@ -128,14 +129,11 @@ public:
sib13 = {}; sib13 = {};
} }
cell_t(phy_interface_rrc_lte::phy_cell_t phy_cell_) : cell_t() cell_t(phy_interface_rrc_lte::phy_cell_t phy_cell_) : cell_t() { phy_cell = phy_cell_; }
{
phy_cell = phy_cell_;
}
uint32_t get_earfcn() { return phy_cell.earfcn; } uint32_t get_earfcn() const { return phy_cell.earfcn; }
uint32_t get_pci() { return phy_cell.pci; } uint32_t get_pci() const { return phy_cell.pci; }
void set_rsrp(float rsrp_) void set_rsrp(float rsrp_)
{ {
@ -157,9 +155,9 @@ public:
} }
} }
float get_rsrp() { return rsrp; } float get_rsrp() const { return rsrp; }
float get_rsrq() { return rsrq; } float get_rsrq() const { return rsrq; }
float get_cfo_hz() { return phy_cell.cfo_hz; } float get_cfo_hz() const { return phy_cell.cfo_hz; }
void set_sib1(asn1::rrc::sib_type1_s* sib1_); void set_sib1(asn1::rrc::sib_type1_s* sib1_);
void set_sib2(asn1::rrc::sib_type2_s* sib2_); void set_sib2(asn1::rrc::sib_type2_s* sib2_);
@ -181,7 +179,7 @@ public:
asn1::rrc::sib_type3_s* sib3ptr() { return &sib3; } asn1::rrc::sib_type3_s* sib3ptr() { return &sib3; }
asn1::rrc::sib_type13_r9_s* sib13ptr() { return &sib13; } asn1::rrc::sib_type13_r9_s* sib13ptr() { return &sib13; }
uint32_t get_cell_id() { return (uint32_t)sib1.cell_access_related_info.cell_id.to_number(); } 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_sib1() { return has_valid_sib1; }
bool has_sib2() { return has_valid_sib2; } bool has_sib2() { return has_valid_sib2; }
@ -239,7 +237,7 @@ public:
return 0; return 0;
} }
std::string to_string() std::string to_string() const
{ {
char buf[256]; char buf[256];
snprintf(buf, snprintf(buf,
@ -370,16 +368,16 @@ private:
void process_pcch(srslte::unique_byte_buffer_t pdu); void process_pcch(srslte::unique_byte_buffer_t pdu);
stack_interface_rrc* stack = nullptr; stack_interface_rrc* stack = nullptr;
srslte::byte_buffer_pool* pool = nullptr; srslte::byte_buffer_pool* pool = nullptr;
srslte::log_ref rrc_log; srslte::log_ref rrc_log;
phy_interface_rrc_lte* phy = nullptr; phy_interface_rrc_lte* phy = nullptr;
mac_interface_rrc* mac = nullptr; mac_interface_rrc* mac = nullptr;
rlc_interface_rrc* rlc = nullptr; rlc_interface_rrc* rlc = nullptr;
pdcp_interface_rrc* pdcp = nullptr; pdcp_interface_rrc* pdcp = nullptr;
nas_interface_rrc* nas = nullptr; nas_interface_rrc* nas = nullptr;
usim_interface_rrc* usim = nullptr; usim_interface_rrc* usim = nullptr;
gw_interface_rrc* gw = nullptr; gw_interface_rrc* gw = nullptr;
srslte::unique_byte_buffer_t dedicated_info_nas; srslte::unique_byte_buffer_t dedicated_info_nas;
@ -407,8 +405,8 @@ private:
srslte::phy_cfg_t current_phy_cfg, previous_phy_cfg = {}; srslte::phy_cfg_t current_phy_cfg, previous_phy_cfg = {};
srslte::mac_cfg_t current_mac_cfg, previous_mac_cfg = {}; srslte::mac_cfg_t current_mac_cfg, previous_mac_cfg = {};
bool current_scell_configured[SRSLTE_MAX_CARRIERS] = {}; bool current_scell_configured[SRSLTE_MAX_CARRIERS] = {};
bool pending_mob_reconf = false; bool pending_mob_reconf = false;
asn1::rrc::rrc_conn_recfg_s mob_reconf = {}; asn1::rrc::rrc_conn_recfg_s mob_reconf = {};
srslte::as_security_config_t sec_cfg = {}; srslte::as_security_config_t sec_cfg = {};
@ -516,6 +514,7 @@ private:
enum class cs_result_t { changed_cell, same_cell, no_cell }; enum class cs_result_t { changed_cell, same_cell, no_cell };
// RRC procedures (fwd declared) // RRC procedures (fwd declared)
class phy_cell_select_proc;
class cell_search_proc; class cell_search_proc;
class si_acquire_proc; class si_acquire_proc;
class serving_cell_config_proc; class serving_cell_config_proc;
@ -526,6 +525,8 @@ private:
class go_idle_proc; class go_idle_proc;
class cell_reselection_proc; class cell_reselection_proc;
class connection_reest_proc; class connection_reest_proc;
class ho_prep_proc;
srslte::proc_t<phy_cell_select_proc> phy_cell_selector;
srslte::proc_t<cell_search_proc, phy_interface_rrc_lte::cell_search_ret_t> cell_searcher; srslte::proc_t<cell_search_proc, phy_interface_rrc_lte::cell_search_ret_t> cell_searcher;
srslte::proc_t<si_acquire_proc> si_acquirer; srslte::proc_t<si_acquire_proc> si_acquirer;
srslte::proc_t<serving_cell_config_proc> serv_cell_cfg; srslte::proc_t<serving_cell_config_proc> serv_cell_cfg;
@ -536,6 +537,7 @@ private:
srslte::proc_t<plmn_search_proc> plmn_searcher; srslte::proc_t<plmn_search_proc> plmn_searcher;
srslte::proc_t<cell_reselection_proc> cell_reselector; srslte::proc_t<cell_reselection_proc> cell_reselector;
srslte::proc_t<connection_reest_proc> connection_reest; srslte::proc_t<connection_reest_proc> connection_reest;
srslte::proc_t<ho_prep_proc> ho_prep_proc;
srslte::proc_manager_list_t callback_list; srslte::proc_manager_list_t callback_list;
@ -572,9 +574,7 @@ private:
bool con_reconfig(asn1::rrc::rrc_conn_recfg_s* reconfig); bool con_reconfig(asn1::rrc::rrc_conn_recfg_s* reconfig);
void con_reconfig_failed(); void con_reconfig_failed();
bool con_reconfig_ho(asn1::rrc::rrc_conn_recfg_s* reconfig); bool con_reconfig_ho(asn1::rrc::rrc_conn_recfg_s* reconfig);
bool ho_prepare();
void ho_failed(); void ho_failed();
void start_ho();
void start_go_idle(); void start_go_idle();
void rrc_connection_release(const std::string& cause); void rrc_connection_release(const std::string& cause);
void radio_link_failure(); void radio_link_failure();

@ -35,7 +35,7 @@ namespace srsue {
// background workers use this event to signal the result of a cell select phy procedure // background workers use this event to signal the result of a cell select phy procedure
struct cell_select_event_t { struct cell_select_event_t {
cell_select_event_t(bool c_) : cs_ret(c_) {} explicit cell_select_event_t(bool c_) : cs_ret(c_) {}
bool cs_ret; bool cs_ret;
}; };
@ -43,6 +43,22 @@ struct cell_select_event_t {
* Procedures * Procedures
*******************************/ *******************************/
class rrc::phy_cell_select_proc
{
public:
explicit phy_cell_select_proc(rrc* parent_);
srslte::proc_outcome_t init(const cell_t& target_cell);
srslte::proc_outcome_t react(cell_select_event_t ev);
void then(const srslte::proc_state_t& result);
srslte::proc_outcome_t step() { return srslte::proc_outcome_t::yield; }
static const char* name() { return "PHY Cell Select"; }
private:
// args
rrc* rrc_ptr;
const cell_t* target_cell;
};
class rrc::cell_search_proc class rrc::cell_search_proc
{ {
public: public:
@ -85,8 +101,7 @@ public:
struct si_acq_timer_expired { struct si_acq_timer_expired {
uint32_t timer_id; uint32_t timer_id;
}; };
struct sib_received_ev { struct sib_received_ev {};
};
explicit si_acquire_proc(rrc* parent_); explicit si_acquire_proc(rrc* parent_);
srslte::proc_outcome_t init(uint32_t sib_index_); srslte::proc_outcome_t init(uint32_t sib_index_);
@ -287,6 +302,31 @@ private:
srslte::proc_outcome_t cell_criteria(); srslte::proc_outcome_t cell_criteria();
}; };
class rrc::ho_prep_proc
{
public:
struct t304_expiry {};
explicit ho_prep_proc(rrc* rrc_);
srslte::proc_outcome_t init(const asn1::rrc::rrc_conn_recfg_s& rrc_reconf);
srslte::proc_outcome_t react(cell_select_event_t ev);
srslte::proc_outcome_t react(t304_expiry ev);
srslte::proc_outcome_t step();
void then(const srslte::proc_state_t& result);
static const char* name() { return "Handover Preparation"; }
private:
rrc* rrc_ptr = nullptr;
// args
asn1::rrc::rrc_conn_recfg_r8_ies_s recfg_r8;
cell_t ho_src_cell;
uint16_t ho_src_rnti = 0;
// state
uint32_t target_earfcn;
};
} // namespace srsue } // namespace srsue
#endif // SRSLTE_RRC_PROCEDURES_H #endif // SRSLTE_RRC_PROCEDURES_H

@ -89,6 +89,7 @@ rrc::rrc(stack_interface_rrc* stack_) :
last_state(RRC_STATE_CONNECTED), last_state(RRC_STATE_CONNECTED),
drb_up(false), drb_up(false),
rrc_log("RRC"), rrc_log("RRC"),
phy_cell_selector(this),
cell_searcher(this), cell_searcher(this),
si_acquirer(this), si_acquirer(this),
serv_cell_cfg(this), serv_cell_cfg(this),
@ -99,6 +100,7 @@ rrc::rrc(stack_interface_rrc* stack_) :
plmn_searcher(this), plmn_searcher(this),
cell_reselector(this), cell_reselector(this),
connection_reest(this), connection_reest(this),
ho_prep_proc(this),
serving_cell(unique_cell_t(new cell_t())) serving_cell(unique_cell_t(new cell_t()))
{ {
measurements = std::unique_ptr<rrc_meas>(new rrc_meas()); measurements = std::unique_ptr<rrc_meas>(new rrc_meas());
@ -1042,103 +1044,6 @@ void rrc::send_rrc_con_reconfig_complete()
send_ul_dcch_msg(RB_ID_SRB1, ul_dcch_msg); send_ul_dcch_msg(RB_ID_SRB1, ul_dcch_msg);
} }
bool rrc::ho_prepare()
{
if (pending_mob_reconf) {
rrc_conn_recfg_r8_ies_s* mob_reconf_r8 = &mob_reconf.crit_exts.c1().rrc_conn_recfg_r8();
mob_ctrl_info_s* mob_ctrl_info = &mob_reconf_r8->mob_ctrl_info;
rrc_log->info("Processing HO command to target PCell=%d\n", mob_ctrl_info->target_pci);
uint32_t target_earfcn = (mob_ctrl_info->carrier_freq_present) ? mob_ctrl_info->carrier_freq.dl_carrier_freq
: serving_cell->get_earfcn();
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);
return false;
}
// Section 5.3.5.4
t310.stop();
t304.set(mob_ctrl_info->t304.to_number(), [this](uint32_t tid) { timer_expired(tid); });
// Save serving cell and current configuration
ho_src_cell = *serving_cell;
mac_interface_rrc::ue_rnti_t uernti;
mac->get_rntis(&uernti);
ho_src_rnti = uernti.crnti;
// Reset/Reestablish stack
pdcp->reestablish();
rlc->reestablish();
mac->wait_uplink();
mac->clear_rntis();
mac->reset();
phy->reset();
mac->set_ho_rnti(mob_ctrl_info->new_ue_id.to_number(), mob_ctrl_info->target_pci);
// Apply common config, but do not send to lower layers if Dedicated is present (to avoid sending twice)
apply_rr_config_common(&mob_ctrl_info->rr_cfg_common, !mob_reconf_r8->rr_cfg_ded_present);
if (mob_reconf_r8->rr_cfg_ded_present) {
apply_rr_config_dedicated(&mob_reconf_r8->rr_cfg_ded);
}
cell_t* target_cell = get_neighbour_cell_handle(target_earfcn, mob_ctrl_info->target_pci);
if (not phy->cell_select(&target_cell->phy_cell)) {
rrc_log->error("Could not synchronize with target cell %s. Removing cell and trying to return to source %s\n",
target_cell->to_string().c_str(),
serving_cell->to_string().c_str());
// Remove cell from list to avoid cell re-selection, picking the same cell
target_cell->set_rsrp(-INFINITY);
return false;
}
set_serving_cell(target_cell->phy_cell, false);
// Extract and apply scell config if any
apply_scell_config(mob_reconf_r8);
if (mob_ctrl_info->rach_cfg_ded_present) {
rrc_log->info("Starting non-contention based RA with preamble_idx=%d, mask_idx=%d\n",
mob_ctrl_info->rach_cfg_ded.ra_preamb_idx,
mob_ctrl_info->rach_cfg_ded.ra_prach_mask_idx);
mac->start_noncont_ho(mob_ctrl_info->rach_cfg_ded.ra_preamb_idx, mob_ctrl_info->rach_cfg_ded.ra_prach_mask_idx);
} else {
rrc_log->info("Starting contention-based RA\n");
mac->start_cont_ho();
}
int ncc = -1;
if (mob_reconf_r8->security_cfg_ho_present) {
ncc = mob_reconf_r8->security_cfg_ho.handov_type.intra_lte().next_hop_chaining_count;
if (mob_reconf_r8->security_cfg_ho.handov_type.intra_lte().key_change_ind) {
rrc_log->console("keyChangeIndicator in securityConfigHO not supported\n");
return false;
}
if (mob_reconf_r8->security_cfg_ho.handov_type.intra_lte().security_algorithm_cfg_present) {
sec_cfg.cipher_algo = (CIPHERING_ALGORITHM_ID_ENUM)mob_reconf_r8->security_cfg_ho.handov_type.intra_lte()
.security_algorithm_cfg.ciphering_algorithm.to_number();
sec_cfg.integ_algo = (INTEGRITY_ALGORITHM_ID_ENUM)mob_reconf_r8->security_cfg_ho.handov_type.intra_lte()
.security_algorithm_cfg.integrity_prot_algorithm.to_number();
rrc_log->info("Changed Ciphering to %s and Integrity to %s\n",
ciphering_algorithm_id_text[sec_cfg.cipher_algo],
integrity_algorithm_id_text[sec_cfg.integ_algo]);
}
}
usim->generate_as_keys_ho(mob_ctrl_info->target_pci, serving_cell->get_earfcn(), ncc, &sec_cfg);
pdcp->config_security_all(sec_cfg);
send_rrc_con_reconfig_complete();
}
return true;
}
void rrc::ho_ra_completed(bool ra_successful) void rrc::ho_ra_completed(bool ra_successful)
{ {
cmd_msg_t msg; cmd_msg_t msg;
@ -1170,39 +1075,17 @@ void rrc::process_ho_ra_completed(bool ra_successful)
bool rrc::con_reconfig_ho(rrc_conn_recfg_s* reconfig) bool rrc::con_reconfig_ho(rrc_conn_recfg_s* reconfig)
{ {
rrc_conn_recfg_r8_ies_s* mob_reconf_r8 = &reconfig->crit_exts.c1().rrc_conn_recfg_r8();
if (mob_reconf_r8->mob_ctrl_info.target_pci == serving_cell->get_pci()) {
rrc_log->console("Warning: Received HO command to own cell\n");
rrc_log->warning("Received HO command to own cell\n");
return false;
}
rrc_log->info("Received HO command to target PCell=%d\n", mob_reconf_r8->mob_ctrl_info.target_pci);
rrc_log->console("Received HO command to target PCell=%d, NCC=%d\n",
mob_reconf_r8->mob_ctrl_info.target_pci,
mob_reconf_r8->security_cfg_ho.handov_type.intra_lte().next_hop_chaining_count);
// store mobilityControlInfo // store mobilityControlInfo
mob_reconf = *reconfig; mob_reconf = *reconfig;
pending_mob_reconf = true; pending_mob_reconf = true;
start_ho(); if (not ho_prep_proc.launch(*reconfig)) {
return true; rrc_log->error("Unable to launch Handover Preparation procedure\n");
} return false;
}
callback_list.add_proc(ho_prep_proc);
void rrc::start_ho() return true;
{
callback_list.add_task([this]() {
if (state != RRC_STATE_CONNECTED) {
rrc_log->info("HO interrupted, since RRC is no longer in connected state\n");
return srslte::proc_outcome_t::success;
}
if (not ho_prepare()) {
con_reconfig_failed();
return srslte::proc_outcome_t::error;
}
return srslte::proc_outcome_t::success;
});
} }
void rrc::start_go_idle() void rrc::start_go_idle()
@ -1275,6 +1158,7 @@ bool rrc::con_reconfig(rrc_conn_recfg_s* reconfig)
// HO failure from T304 expiry 5.3.5.6 // HO failure from T304 expiry 5.3.5.6
void rrc::ho_failed() void rrc::ho_failed()
{ {
ho_prep_proc.trigger(ho_prep_proc::t304_expiry{});
start_con_restablishment(reest_cause_e::ho_fail); start_con_restablishment(reest_cause_e::ho_fail);
} }
@ -1304,9 +1188,7 @@ void rrc::handle_rrc_con_reconfig(uint32_t lcid, rrc_conn_recfg_s* reconfig)
rrc_conn_recfg_r8_ies_s* reconfig_r8 = &reconfig->crit_exts.c1().rrc_conn_recfg_r8(); rrc_conn_recfg_r8_ies_s* reconfig_r8 = &reconfig->crit_exts.c1().rrc_conn_recfg_r8();
if (reconfig_r8->mob_ctrl_info_present) { if (reconfig_r8->mob_ctrl_info_present) {
if (!con_reconfig_ho(reconfig)) { con_reconfig_ho(reconfig);
con_reconfig_failed();
}
} else { } else {
if (!con_reconfig(reconfig)) { if (!con_reconfig(reconfig)) {
con_reconfig_failed(); con_reconfig_failed();
@ -1401,9 +1283,7 @@ void rrc::cell_search_completed(const phy_interface_rrc_lte::cell_search_ret_t&
void rrc::cell_select_completed(bool cs_ret) void rrc::cell_select_completed(bool cs_ret)
{ {
cell_select_event_t ev{cs_ret}; phy_cell_selector.trigger(cell_select_event_t{cs_ret});
cell_searcher.trigger(ev);
cell_selector.trigger(ev);
} }
/******************************************************************************* /*******************************************************************************

@ -20,6 +20,7 @@
*/ */
#include "srsue/hdr/stack/rrc/rrc_procedures.h" #include "srsue/hdr/stack/rrc/rrc_procedures.h"
#include "srslte/common/security.h"
#include "srslte/common/tti_point.h" #include "srslte/common/tti_point.h"
#include <inttypes.h> // for printing uint64_t #include <inttypes.h> // for printing uint64_t
@ -33,6 +34,36 @@ namespace srsue {
using srslte::proc_outcome_t; using srslte::proc_outcome_t;
using srslte::tti_point; using srslte::tti_point;
/**************************************
* PHY Cell Select Procedure
*************************************/
rrc::phy_cell_select_proc::phy_cell_select_proc(rrc* parent_) : rrc_ptr(parent_) {}
srslte::proc_outcome_t rrc::phy_cell_select_proc::init(const cell_t& target_cell_)
{
target_cell = &target_cell_;
Info("Starting for %s\n", target_cell->to_string().c_str());
rrc_ptr->stack->start_cell_select(&target_cell->phy_cell);
return proc_outcome_t::yield;
}
srslte::proc_outcome_t rrc::phy_cell_select_proc::react(cell_select_event_t ev)
{
if (not ev.cs_ret) {
Error("Couldn't select new serving cell\n");
return proc_outcome_t::error;
}
return proc_outcome_t::success;
}
void rrc::phy_cell_select_proc::then(const srslte::proc_state_t& result)
{
// Warn other procedures that depend on this procedure
rrc_ptr->cell_searcher.trigger(cell_select_event_t{result.is_success()});
rrc_ptr->cell_selector.trigger(cell_select_event_t{result.is_success()});
}
/************************************** /**************************************
* Cell Search Procedure * Cell Search Procedure
*************************************/ *************************************/
@ -92,7 +123,10 @@ proc_outcome_t rrc::cell_search_proc::handle_cell_found(const phy_interface_rrc_
// set new serving cell in PHY // set new serving cell in PHY
state = state_t::phy_cell_select; state = state_t::phy_cell_select;
rrc_ptr->stack->start_cell_select(&rrc_ptr->serving_cell->phy_cell); if (not rrc_ptr->phy_cell_selector.launch(rrc_ptr->serving_cell->phy_cell)) {
Error("Couldn't start phy cell selection\n");
return proc_outcome_t::error;
}
return proc_outcome_t::yield; return proc_outcome_t::yield;
} }
@ -366,8 +400,7 @@ proc_outcome_t rrc::si_acquire_proc::react(si_acq_timer_expired ev)
rrc::serving_cell_config_proc::serving_cell_config_proc(rrc* parent_) : rrc::serving_cell_config_proc::serving_cell_config_proc(rrc* parent_) :
rrc_ptr(parent_), rrc_ptr(parent_),
log_h(srslte::logmap::get("RRC")) log_h(srslte::logmap::get("RRC"))
{ {}
}
/* /*
* Retrieves all required SIB or configures them if already retrieved before * Retrieves all required SIB or configures them if already retrieved before
@ -508,7 +541,10 @@ proc_outcome_t rrc::cell_selection_proc::start_cell_selection()
Info("Selected cell: %s\n", rrc_ptr->serving_cell->to_string().c_str()); Info("Selected cell: %s\n", rrc_ptr->serving_cell->to_string().c_str());
state = search_state_t::cell_selection; state = search_state_t::cell_selection;
rrc_ptr->stack->start_cell_select(&rrc_ptr->serving_cell->phy_cell); if (not rrc_ptr->phy_cell_selector.launch(rrc_ptr->serving_cell->phy_cell)) {
Error("Failed to launch PHY Cell Selection\n");
return proc_outcome_t::error;
}
return proc_outcome_t::yield; return proc_outcome_t::yield;
} }
} }
@ -735,8 +771,7 @@ void rrc::plmn_search_proc::then(const srslte::proc_state_t& result) const
rrc::connection_request_proc::connection_request_proc(rrc* parent_) : rrc::connection_request_proc::connection_request_proc(rrc* parent_) :
rrc_ptr(parent_), rrc_ptr(parent_),
log_h(srslte::logmap::get("RRC")) log_h(srslte::logmap::get("RRC"))
{ {}
}
proc_outcome_t rrc::connection_request_proc::init(srslte::establishment_cause_t cause_, proc_outcome_t rrc::connection_request_proc::init(srslte::establishment_cause_t cause_,
srslte::unique_byte_buffer_t dedicated_info_nas_) srslte::unique_byte_buffer_t dedicated_info_nas_)
@ -1292,4 +1327,158 @@ proc_outcome_t rrc::connection_reest_proc::step()
return ret; return ret;
} }
/**************************************
* Handover Preparation Procedure
*************************************/
rrc::ho_prep_proc::ho_prep_proc(srsue::rrc* rrc_) : rrc_ptr(rrc_) {}
srslte::proc_outcome_t rrc::ho_prep_proc::init(const asn1::rrc::rrc_conn_recfg_s& rrc_reconf)
{
Info("Starting...\n");
recfg_r8 = rrc_reconf.crit_exts.c1().rrc_conn_recfg_r8();
asn1::rrc::mob_ctrl_info_s* mob_ctrl_info = &recfg_r8.mob_ctrl_info;
if (recfg_r8.mob_ctrl_info.target_pci == rrc_ptr->serving_cell->get_pci()) {
rrc_ptr->rrc_log->console("Warning: Received HO command to own cell\n");
Warning("Received HO command to own cell\n");
return proc_outcome_t::error;
}
Info("Received HO command to target PCell=%d\n", recfg_r8.mob_ctrl_info.target_pci);
rrc_ptr->rrc_log->console("Received HO command to target PCell=%d, NCC=%d\n",
recfg_r8.mob_ctrl_info.target_pci,
recfg_r8.security_cfg_ho.handov_type.intra_lte().next_hop_chaining_count);
target_earfcn = (mob_ctrl_info->carrier_freq_present) ? mob_ctrl_info->carrier_freq.dl_carrier_freq
: rrc_ptr->serving_cell->get_earfcn();
if (not rrc_ptr->has_neighbour_cell(target_earfcn, mob_ctrl_info->target_pci)) {
rrc_ptr->rrc_log->console("Received HO command to unknown PCI=%d\n", mob_ctrl_info->target_pci);
Error("Could not find target cell earfcn=%d, pci=%d\n",
rrc_ptr->serving_cell->get_earfcn(),
mob_ctrl_info->target_pci);
return proc_outcome_t::error;
}
// Section 5.3.5.4
rrc_ptr->t310.stop();
rrc_ptr->t304.set(mob_ctrl_info->t304.to_number(), [this](uint32_t tid) { rrc_ptr->timer_expired(tid); });
// Save serving cell and current configuration
ho_src_cell = *rrc_ptr->serving_cell;
mac_interface_rrc::ue_rnti_t uernti;
rrc_ptr->mac->get_rntis(&uernti);
ho_src_rnti = uernti.crnti;
// Reset/Reestablish stack
rrc_ptr->pdcp->reestablish();
rrc_ptr->rlc->reestablish();
rrc_ptr->mac->wait_uplink();
rrc_ptr->mac->clear_rntis();
rrc_ptr->mac->reset();
rrc_ptr->phy->reset();
rrc_ptr->mac->set_ho_rnti(mob_ctrl_info->new_ue_id.to_number(), mob_ctrl_info->target_pci);
// Apply common config, but do not send to lower layers if Dedicated is present (to avoid sending twice)
rrc_ptr->apply_rr_config_common(&mob_ctrl_info->rr_cfg_common, !recfg_r8.rr_cfg_ded_present);
if (recfg_r8.rr_cfg_ded_present) {
rrc_ptr->apply_rr_config_dedicated(&recfg_r8.rr_cfg_ded);
}
cell_t* target_cell = rrc_ptr->get_neighbour_cell_handle(target_earfcn, recfg_r8.mob_ctrl_info.target_pci);
if (not rrc_ptr->phy_cell_selector.launch(*target_cell)) {
Error("Failed to launch the selection of target cell %s\n", target_cell->to_string().c_str());
return proc_outcome_t::error;
}
return proc_outcome_t::yield;
}
srslte::proc_outcome_t rrc::ho_prep_proc::react(srsue::cell_select_event_t ev)
{
// Check if cell has not been deleted in the meantime
cell_t* target_cell = rrc_ptr->get_neighbour_cell_handle(target_earfcn, recfg_r8.mob_ctrl_info.target_pci);
if (target_cell == nullptr) {
Error("Cell removed from list of neighbours. Aborting handover preparation\n");
return proc_outcome_t::error;
}
if (not ev.cs_ret) {
Error("Could not synchronize with target cell %s. Removing cell and trying to return to source %s\n",
target_cell->to_string().c_str(),
rrc_ptr->serving_cell->to_string().c_str());
// Remove cell from list to avoid cell re-selection, picking the same cell
target_cell->set_rsrp(-INFINITY);
return proc_outcome_t::error;
}
rrc_ptr->set_serving_cell(target_cell->phy_cell, false);
// Extract and apply scell config if any
rrc_ptr->apply_scell_config(&recfg_r8);
if (recfg_r8.mob_ctrl_info.rach_cfg_ded_present) {
Info("Starting non-contention based RA with preamble_idx=%d, mask_idx=%d\n",
recfg_r8.mob_ctrl_info.rach_cfg_ded.ra_preamb_idx,
recfg_r8.mob_ctrl_info.rach_cfg_ded.ra_prach_mask_idx);
rrc_ptr->mac->start_noncont_ho(recfg_r8.mob_ctrl_info.rach_cfg_ded.ra_preamb_idx,
recfg_r8.mob_ctrl_info.rach_cfg_ded.ra_prach_mask_idx);
} else {
Info("Starting contention-based RA\n");
rrc_ptr->mac->start_cont_ho();
}
int ncc = -1;
if (recfg_r8.security_cfg_ho_present) {
auto& sec_intralte = recfg_r8.security_cfg_ho.handov_type.intra_lte();
ncc = sec_intralte.next_hop_chaining_count;
if (sec_intralte.key_change_ind) {
rrc_ptr->rrc_log->console("keyChangeIndicator in securityConfigHO not supported\n");
return proc_outcome_t::error;
}
if (sec_intralte.security_algorithm_cfg_present) {
rrc_ptr->sec_cfg.cipher_algo =
(srslte::CIPHERING_ALGORITHM_ID_ENUM)sec_intralte.security_algorithm_cfg.ciphering_algorithm.to_number();
rrc_ptr->sec_cfg.integ_algo =
(srslte::INTEGRITY_ALGORITHM_ID_ENUM)sec_intralte.security_algorithm_cfg.integrity_prot_algorithm.to_number();
Info("Changed Ciphering to %s and Integrity to %s\n",
srslte::ciphering_algorithm_id_text[rrc_ptr->sec_cfg.cipher_algo],
srslte::integrity_algorithm_id_text[rrc_ptr->sec_cfg.integ_algo]);
}
}
rrc_ptr->usim->generate_as_keys_ho(
recfg_r8.mob_ctrl_info.target_pci, rrc_ptr->serving_cell->get_earfcn(), ncc, &rrc_ptr->sec_cfg);
rrc_ptr->pdcp->config_security_all(rrc_ptr->sec_cfg);
return proc_outcome_t::success;
}
srslte::proc_outcome_t rrc::ho_prep_proc::step()
{
if (rrc_ptr->state != RRC_STATE_CONNECTED) {
Info("HO interrupted, since RRC is no longer in connected state\n");
return srslte::proc_outcome_t::error;
}
return proc_outcome_t::success;
}
srslte::proc_outcome_t rrc::ho_prep_proc::react(t304_expiry ev)
{
Info("HO preparation timed out.\n");
return proc_outcome_t::error;
}
void rrc::ho_prep_proc::then(const srslte::proc_state_t& result)
{
if (result.is_error()) {
rrc_ptr->con_reconfig_failed();
} else {
rrc_ptr->send_rrc_con_reconfig_complete();
}
}
} // namespace srsue } // namespace srsue

Loading…
Cancel
Save