added extra state to S1 target enb mobility FSM. Accounts for out-of-order arrival of MMEStatusTransfer. Also, now we avoid creating DRBs before the MMEStatusTransfer

This commit is contained in:
Francisco Paisana 2020-08-21 16:12:18 +01:00
parent 9149cf852d
commit 0036941af4
7 changed files with 156 additions and 118 deletions

View File

@ -81,15 +81,15 @@ public:
void rr_ded_cfg_complete();
// Methods to apply bearer updates
void apply_pdcp_bearer_updates(pdcp_interface_rrc* pdcp, const security_cfg_handler& ue_sec_cfg);
void apply_rlc_bearer_updates(rlc_interface_rrc* rlc);
void add_gtpu_bearer(gtpu_interface_rrc* gtpu, uint32_t erab_id);
void fill_pending_nas_info(asn1::rrc::rrc_conn_recfg_r8_ies_s* msg);
const std::map<uint8_t, erab_t>& get_erabs() const { return erabs; }
const asn1::rrc::drb_to_add_mod_list_l& get_established_drbs() const { return current_drbs; }
const asn1::rrc::srb_to_add_mod_list_l& get_established_srbs() const { return current_srbs; }
const asn1::rrc::drb_to_add_mod_list_l& get_pending_addmod_drbs() const { return drbs_to_add; }
const std::map<uint8_t, erab_t>& get_erabs() const { return erabs; }
const asn1::rrc::drb_to_add_mod_list_l& get_established_drbs() const { return current_drbs; }
const asn1::rrc::srb_to_add_mod_list_l& get_established_srbs() const { return current_srbs; }
srslte::span<const asn1::rrc::drb_to_add_mod_s> get_pending_addmod_drbs() const { return drbs_to_add; }
srslte::span<const uint8_t> get_pending_rem_drbs() const { return drbs_to_release; }
srslte::span<const asn1::rrc::srb_to_add_mod_s> get_pending_addmod_srbs() const { return srbs_to_add; }
std::map<uint8_t, std::vector<uint8_t> > erab_info_list;
std::map<uint8_t, erab_t> erabs;

View File

@ -114,7 +114,6 @@ public:
// S1-Handover
bool start_s1_tenb_ho(const asn1::s1ap::ho_request_s& msg,
const asn1::s1ap::sourceenb_to_targetenb_transparent_container_s& container);
void set_erab_status(const asn1::s1ap::bearers_subject_to_status_transfer_list_l& erabs);
private:
// Handover from source cell
@ -139,6 +138,7 @@ private:
// vars
std::shared_ptr<const var_meas_cfg_t> ue_var_meas;
asn1::rrc::rrc_conn_recfg_complete_s pending_recfg_complete;
// events
struct ho_meas_report_ev {
@ -152,6 +152,7 @@ private:
};
using unsuccessful_outcome_ev = std::false_type;
using recfg_complete_ev = asn1::rrc::rrc_conn_recfg_complete_s;
using status_transfer_ev = asn1::s1ap::bearers_subject_to_status_transfer_list_l;
// states
struct idle_st {};
@ -163,6 +164,7 @@ private:
void enter(rrc_mobility* f, const ho_meas_report_ev& meas_report);
};
struct s1_target_ho_st {};
struct wait_recfg_comp {};
struct s1_source_ho_st : public subfsm_t<s1_source_ho_st> {
ho_meas_report_ev report;
using ho_cmd_msg = srslte::unique_byte_buffer_t;
@ -204,33 +206,38 @@ private:
// FSM transition handlers
void handle_crnti_ce(intraenb_ho_st& s, const user_crnti_upd_ev& ev);
void handle_recfg_complete(s1_target_ho_st& s, const recfg_complete_ev& ev);
void handle_recfg_complete(intraenb_ho_st& s, const recfg_complete_ev& ev);
void handle_ho_req(idle_st& s, const ho_req_rx_ev& ho_req);
void handle_status_transfer(s1_target_ho_st& s, const status_transfer_ev& ev);
void defer_recfg_complete(s1_target_ho_st& s, const recfg_complete_ev& ev);
void handle_recfg_complete(wait_recfg_comp& s, const recfg_complete_ev& ev);
protected:
// states
state_list<idle_st, intraenb_ho_st, s1_target_ho_st, s1_source_ho_st> states{this,
idle_st{},
intraenb_ho_st{},
s1_target_ho_st{},
s1_source_ho_st{this}};
state_list<idle_st, intraenb_ho_st, s1_target_ho_st, wait_recfg_comp, s1_source_ho_st> states{this,
idle_st{},
intraenb_ho_st{},
s1_target_ho_st{},
wait_recfg_comp{},
s1_source_ho_st{this}};
// transitions
using fsm = rrc_mobility;
// clang-format off
using transitions = transition_table<
// Start Target Event Action Guard
// +----------------+----------------+--------------------+---------------------------+-------------------------+
row< idle_st, s1_source_ho_st, ho_meas_report_ev, nullptr, &fsm::needs_s1_ho >,
row< idle_st, intraenb_ho_st, ho_meas_report_ev, nullptr, &fsm::needs_intraenb_ho >,
row< idle_st, s1_target_ho_st, ho_req_rx_ev, &fsm::handle_ho_req >,
// +----------------+----------------+--------------------+---------------------------+-------------------------+
upd< intraenb_ho_st, user_crnti_upd_ev, &fsm::handle_crnti_ce >,
row< intraenb_ho_st, idle_st, recfg_complete_ev, &fsm::handle_recfg_complete >,
// +----------------+----------------+--------------------+---------------------------+-------------------------+
row< s1_target_ho_st, idle_st, recfg_complete_ev, &fsm::handle_recfg_complete >
// +----------------+----------------+--------------------+---------------------------+-------------------------+
// Start Target Event Action Guard
// +----------------+-------------------+---------------------+----------------------------+-------------------------+
row< idle_st, s1_source_ho_st, ho_meas_report_ev, nullptr, &fsm::needs_s1_ho >,
row< idle_st, intraenb_ho_st, ho_meas_report_ev, nullptr, &fsm::needs_intraenb_ho >,
row< idle_st, s1_target_ho_st, ho_req_rx_ev, &fsm::handle_ho_req >,
// +----------------+-------------------+---------------------+----------------------------+-------------------------+
upd< intraenb_ho_st, user_crnti_upd_ev, &fsm::handle_crnti_ce >,
row< intraenb_ho_st, idle_st, recfg_complete_ev, &fsm::handle_recfg_complete >,
// +----------------+-------------------+---------------------+----------------------------+-------------------------+
row< s1_target_ho_st, wait_recfg_comp, status_transfer_ev, &fsm::handle_status_transfer >,
upd< s1_target_ho_st, recfg_complete_ev, &fsm::defer_recfg_complete >,
row< wait_recfg_comp, idle_st, recfg_complete_ev, &fsm::handle_recfg_complete >
// +----------------+-------------------+---------------------+----------------------------+-------------------------+
>;
// clang-format on
};

View File

@ -174,6 +174,14 @@ private:
* @param reconfig_r8 ASN1 reconfiguration message
*/
void apply_reconf_phy_config(const asn1::rrc::rrc_conn_recfg_r8_ies_s& reconfig_r8);
/**
* Reconfigures PDCP bearers
* @param srbs_to_add SRBs to add
*/
void apply_pdcp_srb_updates();
void apply_pdcp_drb_updates();
void apply_rlc_rb_updates();
}; // class ue
} // namespace srsenb

View File

@ -475,7 +475,7 @@ void rrc::set_erab_status(uint16_t rnti, const asn1::s1ap::bearers_subject_to_st
rrc_log->warning("rnti=0x%x does not exist\n", rnti);
return;
}
ue_it->second->mobility_handler->set_erab_status(erabs);
ue_it->second->mobility_handler->trigger(erabs);
}
/*******************************************************************************

View File

@ -339,56 +339,6 @@ bool bearer_cfg_handler::fill_rr_cfg_ded(asn1::rrc::rr_cfg_ded_s& msg)
return msg.srb_to_add_mod_list_present or msg.drb_to_add_mod_list_present or msg.drb_to_release_list_present;
}
void bearer_cfg_handler::apply_pdcp_bearer_updates(pdcp_interface_rrc* pdcp, const security_cfg_handler& ue_sec_cfg)
{
for (const srb_to_add_mod_s& srb : srbs_to_add) {
pdcp->add_bearer(rnti, srb.srb_id, srslte::make_srb_pdcp_config_t(srb.srb_id, false));
// For SRB2, enable security/encryption/integrity
if (ue_sec_cfg.is_as_sec_cfg_valid()) {
pdcp->config_security(rnti, srb.srb_id, ue_sec_cfg.get_as_sec_cfg());
pdcp->enable_integrity(rnti, srb.srb_id);
pdcp->enable_encryption(rnti, srb.srb_id);
}
}
for (uint8_t drb_id : drbs_to_release) {
pdcp->del_bearer(rnti, drb_id + 2);
}
for (const drb_to_add_mod_s& drb : drbs_to_add) {
// Configure DRB1 in PDCP
if (drb.pdcp_cfg_present) {
srslte::pdcp_config_t pdcp_cnfg_drb = srslte::make_drb_pdcp_config_t(drb.drb_id, false, drb.pdcp_cfg);
pdcp->add_bearer(rnti, drb.lc_ch_id, pdcp_cnfg_drb);
} else {
srslte::pdcp_config_t pdcp_cnfg_drb = srslte::make_drb_pdcp_config_t(drb.drb_id, false);
pdcp->add_bearer(rnti, drb.lc_ch_id, pdcp_cnfg_drb);
}
if (ue_sec_cfg.is_as_sec_cfg_valid()) {
pdcp->config_security(rnti, drb.lc_ch_id, ue_sec_cfg.get_as_sec_cfg());
pdcp->enable_integrity(rnti, drb.lc_ch_id);
pdcp->enable_encryption(rnti, drb.lc_ch_id);
}
}
}
void bearer_cfg_handler::apply_rlc_bearer_updates(rlc_interface_rrc* rlc)
{
for (const srb_to_add_mod_s& srb : srbs_to_add) {
rlc->add_bearer(rnti, srb.srb_id, srslte::rlc_config_t::srb_config(srb.srb_id));
}
if (drbs_to_release.size() > 0) {
log_h->error("Removing DRBs not currently supported\n");
}
for (const drb_to_add_mod_s& drb : drbs_to_add) {
if (not drb.rlc_cfg_present) {
log_h->warning("Default RLC DRB config not supported\n");
}
rlc->add_bearer(rnti, drb.lc_ch_id, srslte::make_rlc_config_t(drb.rlc_cfg));
}
}
void bearer_cfg_handler::add_gtpu_bearer(srsenb::gtpu_interface_rrc* gtpu, uint32_t erab_id)
{
auto it = erabs.find(erab_id);

View File

@ -763,36 +763,6 @@ bool rrc::ue::rrc_mobility::start_s1_tenb_ho(
return is_in_state<s1_target_ho_st>();
}
void rrc::ue::rrc_mobility::set_erab_status(const asn1::s1ap::bearers_subject_to_status_transfer_list_l& erabs)
{
for (const auto& erab : erabs) {
const auto& erab_item = erab.value.bearers_subject_to_status_transfer_item();
auto erab_it = rrc_ue->bearer_list.get_erabs().find(erab_item.erab_id);
if (erab_it == rrc_ue->bearer_list.get_erabs().end()) {
rrc_log->warning("The E-RAB Id=%d is not recognized\n", erab_item.erab_id);
continue;
}
const auto& drbs = rrc_ue->bearer_list.get_pending_addmod_drbs();
uint8_t drbid = erab_item.erab_id - 4;
auto drb_it =
std::find_if(drbs.begin(), drbs.end(), [drbid](const drb_to_add_mod_s& drb) { return drb.drb_id == drbid; });
if (drb_it == drbs.end()) {
rrc_log->warning("The DRB id=%d does not exist\n", erab_item.erab_id - 4);
}
srslte::pdcp_lte_state_t drb_state{};
drb_state.tx_hfn = erab_item.dl_coun_tvalue.hfn;
drb_state.next_pdcp_tx_sn = erab_item.dl_coun_tvalue.pdcp_sn;
drb_state.rx_hfn = erab_item.ul_coun_tvalue.hfn;
drb_state.next_pdcp_rx_sn = erab_item.ul_coun_tvalue.pdcp_sn;
rrc_log->info("Setting lcid=%d PDCP state to {Tx SN: %d, Rx SN: %d}\n",
drb_it->lc_ch_id,
drb_state.next_pdcp_tx_sn,
drb_state.next_pdcp_rx_sn);
rrc_enb->pdcp->set_bearer_state(rrc_ue->rnti, drb_it->lc_ch_id, drb_state);
}
}
bool rrc::ue::rrc_mobility::update_ue_var_meas_cfg(const asn1::rrc::meas_cfg_s& source_meas_cfg,
uint32_t target_enb_cc_idx,
asn1::rrc::meas_cfg_s* diff_meas_cfg)
@ -1113,9 +1083,9 @@ void rrc::ue::rrc_mobility::handle_ho_req(idle_st& s, const ho_req_rx_ev& ho_req
ho_cmd_pdu->N_bytes = bref2.distance_bytes();
/* Configure remaining layers based on pending changes */
// Update RLC + PDCP
rrc_ue->bearer_list.apply_pdcp_bearer_updates(rrc_enb->pdcp, rrc_ue->ue_security_cfg);
rrc_ue->bearer_list.apply_rlc_bearer_updates(rrc_enb->rlc);
// Update RLC + PDCP SRBs (no DRBs until MME Status Transfer)
rrc_ue->apply_pdcp_srb_updates();
rrc_ue->apply_rlc_rb_updates();
// Update MAC
rrc_ue->mac_ctrl->handle_ho_prep(hoprep_r8, recfg_r8);
// Apply PHY updates
@ -1195,7 +1165,7 @@ bool rrc::ue::rrc_mobility::apply_ho_prep_cfg(const ho_prep_info_r8_ies_s& ho
return true;
}
void rrc::ue::rrc_mobility::handle_recfg_complete(s1_target_ho_st& s, const recfg_complete_ev& ev)
void rrc::ue::rrc_mobility::handle_recfg_complete(wait_recfg_comp& s, const recfg_complete_ev& ev)
{
cell_ctxt_dedicated* target_cell = rrc_ue->cell_ded_list.get_ue_cc_idx(UE_PCELL_CC_IDX);
rrc_log->info("User rnti=0x%x successfully handovered to cell_id=0x%x\n",
@ -1206,6 +1176,51 @@ void rrc::ue::rrc_mobility::handle_recfg_complete(s1_target_ho_st& s, const recf
rrc_enb->s1ap->send_ho_notify(rrc_ue->rnti, target_eci);
}
void rrc::ue::rrc_mobility::handle_status_transfer(s1_target_ho_st& s, const status_transfer_ev& erabs)
{
// Establish DRBs
rrc_ue->apply_pdcp_drb_updates();
// Set DRBs SNs
for (const auto& erab : erabs) {
const auto& erab_item = erab.value.bearers_subject_to_status_transfer_item();
auto erab_it = rrc_ue->bearer_list.get_erabs().find(erab_item.erab_id);
if (erab_it == rrc_ue->bearer_list.get_erabs().end()) {
rrc_log->warning("The E-RAB Id=%d is not recognized\n", erab_item.erab_id);
continue;
}
const auto& drbs = rrc_ue->bearer_list.get_pending_addmod_drbs();
uint8_t drbid = erab_item.erab_id - 4;
auto drb_it =
std::find_if(drbs.begin(), drbs.end(), [drbid](const drb_to_add_mod_s& drb) { return drb.drb_id == drbid; });
if (drb_it == drbs.end()) {
rrc_log->warning("The DRB id=%d does not exist\n", erab_item.erab_id - 4);
}
srslte::pdcp_lte_state_t drb_state{};
drb_state.tx_hfn = erab_item.dl_coun_tvalue.hfn;
drb_state.next_pdcp_tx_sn = erab_item.dl_coun_tvalue.pdcp_sn;
drb_state.rx_hfn = erab_item.ul_coun_tvalue.hfn;
drb_state.next_pdcp_rx_sn = erab_item.ul_coun_tvalue.pdcp_sn;
rrc_log->info("Setting lcid=%d PDCP state to {Tx SN: %d, Rx SN: %d}\n",
drb_it->lc_ch_id,
drb_state.next_pdcp_tx_sn,
drb_state.next_pdcp_rx_sn);
rrc_enb->pdcp->set_bearer_state(rrc_ue->rnti, drb_it->lc_ch_id, drb_state);
}
// Check if there is any pending Reconfiguration Complete. If there is, self-trigger
if (pending_recfg_complete.crit_exts.type().value != rrc_conn_recfg_complete_s::crit_exts_c_::types_opts::nulltype) {
trigger(pending_recfg_complete);
pending_recfg_complete.crit_exts.set(rrc_conn_recfg_complete_s::crit_exts_c_::types_opts::nulltype);
}
}
void rrc::ue::rrc_mobility::defer_recfg_complete(s1_target_ho_st& s, const recfg_complete_ev& ev)
{
pending_recfg_complete = ev;
}
/*************************************************************************************************
* intraENB Handover sub-FSM
************************************************************************************************/
@ -1277,7 +1292,8 @@ void rrc::ue::rrc_mobility::handle_crnti_ce(intraenb_ho_st& s, const user_crnti_
rrc_ue->ue_security_cfg.regenerate_keys_handover(s.target_cell->cell_cfg.pci, s.target_cell->cell_cfg.dl_earfcn);
rrc_ue->bearer_list.reest_bearers();
rrc_ue->bearer_list.apply_pdcp_bearer_updates(rrc_enb->pdcp, rrc_ue->ue_security_cfg);
rrc_ue->apply_pdcp_srb_updates();
rrc_ue->apply_pdcp_drb_updates();
} else {
rrc_log->info("Received duplicate C-RNTI CE during rnti=0x%x handover.\n", rrc_ue->rnti);
}

View File

@ -271,8 +271,9 @@ void rrc::ue::send_connection_setup()
mac_ctrl->handle_con_setup(setup);
// Add SRBs/DRBs, and configure RLC+PDCP
bearer_list.apply_pdcp_bearer_updates(parent->pdcp, ue_security_cfg);
bearer_list.apply_rlc_bearer_updates(parent->rlc);
apply_pdcp_srb_updates();
apply_pdcp_drb_updates();
apply_rlc_rb_updates();
// Configure PHY layer
apply_setup_phy_config_dedicated(*phy_cfg); // It assumes SCell has not been set before
@ -406,8 +407,9 @@ void rrc::ue::send_connection_reest()
mac_ctrl->handle_con_reest(reest);
// Add SRBs/DRBs, and configure RLC+PDCP
bearer_list.apply_pdcp_bearer_updates(parent->pdcp, ue_security_cfg);
bearer_list.apply_rlc_bearer_updates(parent->rlc);
apply_pdcp_srb_updates();
apply_pdcp_drb_updates();
apply_rlc_rb_updates();
// Configure PHY layer
apply_setup_phy_config_dedicated(*phy_cfg); // It assumes SCell has not been set before
@ -536,8 +538,9 @@ void rrc::ue::send_connection_reconf(srslte::unique_byte_buffer_t pdu)
apply_reconf_phy_config(*conn_reconf);
// setup SRB2/DRBs in PDCP and RLC
bearer_list.apply_pdcp_bearer_updates(parent->pdcp, ue_security_cfg);
bearer_list.apply_rlc_bearer_updates(parent->rlc);
apply_pdcp_srb_updates();
apply_pdcp_drb_updates();
apply_rlc_rb_updates();
// Add pending NAS info
bearer_list.fill_pending_nas_info(conn_reconf);
@ -642,8 +645,9 @@ void rrc::ue::send_connection_reconf_new_bearer()
conn_reconf->rr_cfg_ded_present = bearer_list.fill_rr_cfg_ded(conn_reconf->rr_cfg_ded);
// Setup new bearer
bearer_list.apply_pdcp_bearer_updates(parent->pdcp, ue_security_cfg);
bearer_list.apply_rlc_bearer_updates(parent->rlc);
apply_pdcp_srb_updates();
apply_pdcp_drb_updates();
apply_rlc_rb_updates();
// Add pending NAS info
bearer_list.fill_pending_nas_info(conn_reconf);
@ -1394,6 +1398,59 @@ void rrc::ue::apply_reconf_phy_config(const asn1::rrc::rrc_conn_recfg_r8_ies_s&
}
}
void rrc::ue::apply_pdcp_srb_updates()
{
for (const srb_to_add_mod_s& srb : bearer_list.get_pending_addmod_srbs()) {
parent->pdcp->add_bearer(rnti, srb.srb_id, srslte::make_srb_pdcp_config_t(srb.srb_id, false));
// For SRB2, enable security/encryption/integrity
if (ue_security_cfg.is_as_sec_cfg_valid()) {
parent->pdcp->config_security(rnti, srb.srb_id, ue_security_cfg.get_as_sec_cfg());
parent->pdcp->enable_integrity(rnti, srb.srb_id);
parent->pdcp->enable_encryption(rnti, srb.srb_id);
}
}
}
void rrc::ue::apply_pdcp_drb_updates()
{
for (uint8_t drb_id : bearer_list.get_pending_rem_drbs()) {
parent->pdcp->del_bearer(rnti, drb_id + 2);
}
for (const drb_to_add_mod_s& drb : bearer_list.get_pending_addmod_drbs()) {
// Configure DRB1 in PDCP
if (drb.pdcp_cfg_present) {
srslte::pdcp_config_t pdcp_cnfg_drb = srslte::make_drb_pdcp_config_t(drb.drb_id, false, drb.pdcp_cfg);
parent->pdcp->add_bearer(rnti, drb.lc_ch_id, pdcp_cnfg_drb);
} else {
srslte::pdcp_config_t pdcp_cnfg_drb = srslte::make_drb_pdcp_config_t(drb.drb_id, false);
parent->pdcp->add_bearer(rnti, drb.lc_ch_id, pdcp_cnfg_drb);
}
if (ue_security_cfg.is_as_sec_cfg_valid()) {
parent->pdcp->config_security(rnti, drb.lc_ch_id, ue_security_cfg.get_as_sec_cfg());
parent->pdcp->enable_integrity(rnti, drb.lc_ch_id);
parent->pdcp->enable_encryption(rnti, drb.lc_ch_id);
}
}
}
void rrc::ue::apply_rlc_rb_updates()
{
for (const srb_to_add_mod_s& srb : bearer_list.get_pending_addmod_srbs()) {
parent->rlc->add_bearer(rnti, srb.srb_id, srslte::rlc_config_t::srb_config(srb.srb_id));
}
if (bearer_list.get_pending_rem_drbs().size() > 0) {
parent->rrc_log->error("Removing DRBs not currently supported\n");
}
for (const drb_to_add_mod_s& drb : bearer_list.get_pending_addmod_drbs()) {
if (not drb.rlc_cfg_present) {
parent->rrc_log->warning("Default RLC DRB config not supported\n");
}
parent->rlc->add_bearer(rnti, drb.lc_ch_id, srslte::make_rlc_config_t(drb.rlc_cfg));
}
}
int rrc::ue::get_cqi(uint16_t* pmi_idx, uint16_t* n_pucch, uint32_t ue_cc_idx)
{
cell_ctxt_dedicated* c = cell_ded_list.get_ue_cc_idx(ue_cc_idx);