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);
has_valid_sib1 = false;
has_valid_sib2 = false;
has_valid_sib3 = false;
has_valid_sib13 = false;
phy_cell = {0,0,0};
phy_cell = {0, 0, 0};
rsrp = NAN;
rsrq = NAN;
sib1 = {};
@ -128,14 +129,11 @@ public:
sib13 = {};
}
cell_t(phy_interface_rrc_lte::phy_cell_t phy_cell_) : cell_t()
{
phy_cell = phy_cell_;
}
cell_t(phy_interface_rrc_lte::phy_cell_t phy_cell_) : cell_t() { 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_)
{
@ -157,9 +155,9 @@ public:
}
}
float get_rsrp() { return rsrp; }
float get_rsrq() { return rsrq; }
float get_cfo_hz() { return phy_cell.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_);
@ -181,7 +179,7 @@ public:
asn1::rrc::sib_type3_s* sib3ptr() { return &sib3; }
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_sib2() { return has_valid_sib2; }
@ -239,7 +237,7 @@ public:
return 0;
}
std::string to_string()
std::string to_string() const
{
char buf[256];
snprintf(buf,
@ -370,16 +368,16 @@ private:
void process_pcch(srslte::unique_byte_buffer_t pdu);
stack_interface_rrc* stack = nullptr;
srslte::byte_buffer_pool* pool = nullptr;
srslte::log_ref rrc_log;
phy_interface_rrc_lte* phy = nullptr;
mac_interface_rrc* mac = nullptr;
rlc_interface_rrc* rlc = nullptr;
pdcp_interface_rrc* pdcp = nullptr;
nas_interface_rrc* nas = nullptr;
usim_interface_rrc* usim = nullptr;
gw_interface_rrc* gw = nullptr;
stack_interface_rrc* stack = nullptr;
srslte::byte_buffer_pool* pool = nullptr;
srslte::log_ref rrc_log;
phy_interface_rrc_lte* phy = nullptr;
mac_interface_rrc* mac = nullptr;
rlc_interface_rrc* rlc = nullptr;
pdcp_interface_rrc* pdcp = nullptr;
nas_interface_rrc* nas = nullptr;
usim_interface_rrc* usim = nullptr;
gw_interface_rrc* gw = nullptr;
srslte::unique_byte_buffer_t dedicated_info_nas;
@ -407,8 +405,8 @@ private:
srslte::phy_cfg_t current_phy_cfg, previous_phy_cfg = {};
srslte::mac_cfg_t current_mac_cfg, previous_mac_cfg = {};
bool current_scell_configured[SRSLTE_MAX_CARRIERS] = {};
bool pending_mob_reconf = false;
asn1::rrc::rrc_conn_recfg_s mob_reconf = {};
bool pending_mob_reconf = false;
asn1::rrc::rrc_conn_recfg_s mob_reconf = {};
srslte::as_security_config_t sec_cfg = {};
@ -516,6 +514,7 @@ private:
enum class cs_result_t { changed_cell, same_cell, no_cell };
// RRC procedures (fwd declared)
class phy_cell_select_proc;
class cell_search_proc;
class si_acquire_proc;
class serving_cell_config_proc;
@ -526,6 +525,8 @@ private:
class go_idle_proc;
class cell_reselection_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<si_acquire_proc> si_acquirer;
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<cell_reselection_proc> cell_reselector;
srslte::proc_t<connection_reest_proc> connection_reest;
srslte::proc_t<ho_prep_proc> ho_prep_proc;
srslte::proc_manager_list_t callback_list;
@ -572,9 +574,7 @@ private:
bool con_reconfig(asn1::rrc::rrc_conn_recfg_s* reconfig);
void con_reconfig_failed();
bool con_reconfig_ho(asn1::rrc::rrc_conn_recfg_s* reconfig);
bool ho_prepare();
void ho_failed();
void start_ho();
void start_go_idle();
void rrc_connection_release(const std::string& cause);
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
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;
};
@ -43,6 +43,22 @@ struct cell_select_event_t {
* 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
{
public:
@ -85,8 +101,7 @@ public:
struct si_acq_timer_expired {
uint32_t timer_id;
};
struct sib_received_ev {
};
struct sib_received_ev {};
explicit si_acquire_proc(rrc* parent_);
srslte::proc_outcome_t init(uint32_t sib_index_);
@ -287,6 +302,31 @@ private:
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
#endif // SRSLTE_RRC_PROCEDURES_H

@ -89,6 +89,7 @@ rrc::rrc(stack_interface_rrc* stack_) :
last_state(RRC_STATE_CONNECTED),
drb_up(false),
rrc_log("RRC"),
phy_cell_selector(this),
cell_searcher(this),
si_acquirer(this),
serv_cell_cfg(this),
@ -99,6 +100,7 @@ rrc::rrc(stack_interface_rrc* stack_) :
plmn_searcher(this),
cell_reselector(this),
connection_reest(this),
ho_prep_proc(this),
serving_cell(unique_cell_t(new cell_t()))
{
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);
}
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)
{
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)
{
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
mob_reconf = *reconfig;
pending_mob_reconf = true;
start_ho();
return true;
}
if (not ho_prep_proc.launch(*reconfig)) {
rrc_log->error("Unable to launch Handover Preparation procedure\n");
return false;
}
callback_list.add_proc(ho_prep_proc);
void rrc::start_ho()
{
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;
});
return true;
}
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
void rrc::ho_failed()
{
ho_prep_proc.trigger(ho_prep_proc::t304_expiry{});
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();
if (reconfig_r8->mob_ctrl_info_present) {
if (!con_reconfig_ho(reconfig)) {
con_reconfig_failed();
}
con_reconfig_ho(reconfig);
} else {
if (!con_reconfig(reconfig)) {
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)
{
cell_select_event_t ev{cs_ret};
cell_searcher.trigger(ev);
cell_selector.trigger(ev);
phy_cell_selector.trigger(cell_select_event_t{cs_ret});
}
/*******************************************************************************

@ -20,6 +20,7 @@
*/
#include "srsue/hdr/stack/rrc/rrc_procedures.h"
#include "srslte/common/security.h"
#include "srslte/common/tti_point.h"
#include <inttypes.h> // for printing uint64_t
@ -33,6 +34,36 @@ namespace srsue {
using srslte::proc_outcome_t;
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
*************************************/
@ -92,7 +123,10 @@ proc_outcome_t rrc::cell_search_proc::handle_cell_found(const phy_interface_rrc_
// set new serving cell in PHY
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;
}
@ -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_ptr(parent_),
log_h(srslte::logmap::get("RRC"))
{
}
{}
/*
* 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());
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;
}
}
@ -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_ptr(parent_),
log_h(srslte::logmap::get("RRC"))
{
}
{}
proc_outcome_t rrc::connection_request_proc::init(srslte::establishment_cause_t cause_,
srslte::unique_byte_buffer_t dedicated_info_nas_)
@ -1292,4 +1327,158 @@ proc_outcome_t rrc::connection_reest_proc::step()
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

Loading…
Cancel
Save