diff --git a/srsenb/hdr/stack/rrc/rrc_bearer_cfg.h b/srsenb/hdr/stack/rrc/rrc_bearer_cfg.h index 900f67abc..d90ae1891 100644 --- a/srsenb/hdr/stack/rrc/rrc_bearer_cfg.h +++ b/srsenb/hdr/stack/rrc/rrc_bearer_cfg.h @@ -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& 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& 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 get_pending_addmod_drbs() const { return drbs_to_add; } + srslte::span get_pending_rem_drbs() const { return drbs_to_release; } + srslte::span get_pending_addmod_srbs() const { return srbs_to_add; } std::map > erab_info_list; std::map erabs; diff --git a/srsenb/hdr/stack/rrc/rrc_mobility.h b/srsenb/hdr/stack/rrc/rrc_mobility.h index e4507553b..a2ba87a40 100644 --- a/srsenb/hdr/stack/rrc/rrc_mobility.h +++ b/srsenb/hdr/stack/rrc/rrc_mobility.h @@ -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 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 { 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 states{this, - idle_st{}, - intraenb_ho_st{}, - s1_target_ho_st{}, - s1_source_ho_st{this}}; + state_list 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 }; diff --git a/srsenb/hdr/stack/rrc/rrc_ue.h b/srsenb/hdr/stack/rrc/rrc_ue.h index e5def91c1..50642e819 100644 --- a/srsenb/hdr/stack/rrc/rrc_ue.h +++ b/srsenb/hdr/stack/rrc/rrc_ue.h @@ -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 diff --git a/srsenb/src/stack/rrc/rrc.cc b/srsenb/src/stack/rrc/rrc.cc index d25a36280..ba6a25edf 100644 --- a/srsenb/src/stack/rrc/rrc.cc +++ b/srsenb/src/stack/rrc/rrc.cc @@ -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); } /******************************************************************************* diff --git a/srsenb/src/stack/rrc/rrc_bearer_cfg.cc b/srsenb/src/stack/rrc/rrc_bearer_cfg.cc index 6550b94b7..3cc4f166c 100644 --- a/srsenb/src/stack/rrc/rrc_bearer_cfg.cc +++ b/srsenb/src/stack/rrc/rrc_bearer_cfg.cc @@ -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); diff --git a/srsenb/src/stack/rrc/rrc_mobility.cc b/srsenb/src/stack/rrc/rrc_mobility.cc index 79e5f5f71..8f2f70391 100644 --- a/srsenb/src/stack/rrc/rrc_mobility.cc +++ b/srsenb/src/stack/rrc/rrc_mobility.cc @@ -763,36 +763,6 @@ bool rrc::ue::rrc_mobility::start_s1_tenb_ho( return is_in_state(); } -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); } diff --git a/srsenb/src/stack/rrc/rrc_ue.cc b/srsenb/src/stack/rrc/rrc_ue.cc index 20d91df21..5888bd30c 100644 --- a/srsenb/src/stack/rrc/rrc_ue.cc +++ b/srsenb/src/stack/rrc/rrc_ue.cc @@ -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);