From 31f2ed71940ba595ca651c451fae36951f196447 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 12 Apr 2024 11:00:37 +0200 Subject: [PATCH] cu-cp: fix for drb removal --- lib/cu_cp/du_processor/du_processor_impl.cpp | 2 +- .../du_processor_routine_manager.cpp | 2 + .../du_processor_routine_manager.h | 1 + .../inter_cu_handover_target_routine.cpp | 1 + .../mobility/inter_du_handover_routine.cpp | 1 + ..._session_resource_modification_routine.cpp | 5 +- .../pdu_session_resource_release_routine.cpp | 64 +++++++++++++++++-- .../pdu_session_resource_release_routine.h | 25 +++++--- .../pdu_session_resource_setup_routine.cpp | 5 +- .../routines/pdu_session_routine_helpers.cpp | 30 ++++++--- .../routines/pdu_session_routine_helpers.h | 8 ++- ...blishment_context_modification_routine.cpp | 1 + .../up_resource_manager_helpers.cpp | 6 +- lib/ngap/ngap_impl.cpp | 14 ---- ..._session_resource_release_routine_test.cpp | 2 +- 15 files changed, 118 insertions(+), 49 deletions(-) diff --git a/lib/cu_cp/du_processor/du_processor_impl.cpp b/lib/cu_cp/du_processor/du_processor_impl.cpp index e38faa09df..1ae2435535 100644 --- a/lib/cu_cp/du_processor/du_processor_impl.cpp +++ b/lib/cu_cp/du_processor/du_processor_impl.cpp @@ -395,7 +395,7 @@ du_processor_impl::handle_new_pdu_session_resource_release_command( srsran_assert(ue != nullptr, "ue={}: Could not find DU UE", msg.ue_index); return routine_mng->start_pdu_session_resource_release_routine( - msg, ngap_ctrl_notifier, task_sched, ue->get_up_resource_manager()); + msg, ngap_ctrl_notifier, ue->get_rrc_ue_notifier(), task_sched, ue->get_up_resource_manager()); } void du_processor_impl::handle_paging_message(cu_cp_paging_message& msg) diff --git a/lib/cu_cp/routine_managers/du_processor_routine_manager.cpp b/lib/cu_cp/routine_managers/du_processor_routine_manager.cpp index f61588b8e7..4c8ce614ff 100644 --- a/lib/cu_cp/routine_managers/du_processor_routine_manager.cpp +++ b/lib/cu_cp/routine_managers/du_processor_routine_manager.cpp @@ -80,6 +80,7 @@ async_task du_processor_routine_manager::start_pdu_session_resource_release_routine( const cu_cp_pdu_session_resource_release_command& release_cmd, du_processor_ngap_control_notifier& ngap_ctrl_notifier, + du_processor_rrc_ue_control_message_notifier& rrc_ue_ctrl_notifier, du_processor_ue_task_scheduler& task_sched, up_resource_manager& rrc_ue_up_resource_manager) { @@ -87,6 +88,7 @@ du_processor_routine_manager::start_pdu_session_resource_release_routine( e1ap_ctrl_notifier, f1ap_ue_ctxt_notifier, ngap_ctrl_notifier, + rrc_ue_ctrl_notifier, task_sched, rrc_ue_up_resource_manager, logger); diff --git a/lib/cu_cp/routine_managers/du_processor_routine_manager.h b/lib/cu_cp/routine_managers/du_processor_routine_manager.h index 14304df91b..0bbc80669b 100644 --- a/lib/cu_cp/routine_managers/du_processor_routine_manager.h +++ b/lib/cu_cp/routine_managers/du_processor_routine_manager.h @@ -49,6 +49,7 @@ class du_processor_routine_manager async_task start_pdu_session_resource_release_routine(const cu_cp_pdu_session_resource_release_command& release_cmd, du_processor_ngap_control_notifier& ngap_ctrl_notifier, + du_processor_rrc_ue_control_message_notifier& rrc_ue_ctrl_notifier, du_processor_ue_task_scheduler& task_sched, up_resource_manager& rrc_ue_up_resource_manager); diff --git a/lib/cu_cp/routines/mobility/inter_cu_handover_target_routine.cpp b/lib/cu_cp/routines/mobility/inter_cu_handover_target_routine.cpp index 7b34703847..887924f04a 100644 --- a/lib/cu_cp/routines/mobility/inter_cu_handover_target_routine.cpp +++ b/lib/cu_cp/routines/mobility/inter_cu_handover_target_routine.cpp @@ -167,6 +167,7 @@ void inter_cu_handover_target_routine::operator()( if (!fill_rrc_reconfig_args(rrc_reconfig_args, ue_context_setup_request.srbs_to_be_setup_list, next_config.pdu_sessions_to_setup_list, + {} /* No DRB to be removed */, ue_context_setup_response.du_to_cu_rrc_info, {} /* No NAS PDUs required */, ue->get_rrc_ue_notifier().generate_meas_config(), diff --git a/lib/cu_cp/routines/mobility/inter_du_handover_routine.cpp b/lib/cu_cp/routines/mobility/inter_du_handover_routine.cpp index b734a5877c..9197e6359b 100644 --- a/lib/cu_cp/routines/mobility/inter_du_handover_routine.cpp +++ b/lib/cu_cp/routines/mobility/inter_du_handover_routine.cpp @@ -176,6 +176,7 @@ void inter_du_handover_routine::operator()(coro_contextget_rrc_ue_notifier().generate_meas_config(source_rrc_context.meas_cfg), diff --git a/lib/cu_cp/routines/pdu_session_resource_modification_routine.cpp b/lib/cu_cp/routines/pdu_session_resource_modification_routine.cpp index 32dd019de6..2d0b9adf9c 100644 --- a/lib/cu_cp/routines/pdu_session_resource_modification_routine.cpp +++ b/lib/cu_cp/routines/pdu_session_resource_modification_routine.cpp @@ -151,16 +151,17 @@ void pdu_session_resource_modification_routine::operator()( // prepare RRC Reconfiguration and call RRC UE notifier { // get NAS PDUs as received by AMF - std::map nas_pdus; + std::vector nas_pdus; for (const auto& pdu_session : modify_request.pdu_session_res_modify_items) { if (!pdu_session.nas_pdu.empty()) { - nas_pdus.emplace(pdu_session.pdu_session_id, pdu_session.nas_pdu); + nas_pdus.push_back(pdu_session.nas_pdu); } } if (!fill_rrc_reconfig_args(rrc_reconfig_args, {}, next_config.pdu_sessions_to_modify_list, + {} /* No extra DRB to be removed */, ue_context_modification_response.du_to_cu_rrc_info, nas_pdus, rrc_ue_notifier.generate_meas_config(), diff --git a/lib/cu_cp/routines/pdu_session_resource_release_routine.cpp b/lib/cu_cp/routines/pdu_session_resource_release_routine.cpp index 17ac0f9296..1ab4c050ac 100644 --- a/lib/cu_cp/routines/pdu_session_resource_release_routine.cpp +++ b/lib/cu_cp/routines/pdu_session_resource_release_routine.cpp @@ -21,6 +21,7 @@ */ #include "pdu_session_resource_release_routine.h" +#include "pdu_session_routine_helpers.h" using namespace srsran; using namespace srsran::srs_cu_cp; @@ -31,6 +32,7 @@ pdu_session_resource_release_routine::pdu_session_resource_release_routine( du_processor_e1ap_control_notifier& e1ap_ctrl_notif_, du_processor_f1ap_ue_context_notifier& f1ap_ue_ctxt_notif_, du_processor_ngap_control_notifier& ngap_ctrl_notifier_, + du_processor_rrc_ue_control_message_notifier& rrc_ue_notifier_, du_processor_ue_task_scheduler& task_sched_, up_resource_manager& rrc_ue_up_resource_manager_, srslog::basic_logger& logger_) : @@ -38,12 +40,27 @@ pdu_session_resource_release_routine::pdu_session_resource_release_routine( e1ap_ctrl_notifier(e1ap_ctrl_notif_), f1ap_ue_ctxt_notifier(f1ap_ue_ctxt_notif_), ngap_ctrl_notifier(ngap_ctrl_notifier_), + rrc_ue_notifier(rrc_ue_notifier_), task_sched(task_sched_), rrc_ue_up_resource_manager(rrc_ue_up_resource_manager_), logger(logger_) { } +// Handle RRC reconfiguration result. +bool handle_procedure_response(cu_cp_pdu_session_resource_release_response& response_msg, + const cu_cp_pdu_session_resource_release_command& release_cmd, + bool rrc_reconfig_result, + const srslog::basic_logger& logger) +{ + // Let all PDU sessions fail if response is negative. + if (!rrc_reconfig_result) { + // TODO: decide how to manage negative RRC reconfig result + } + + return rrc_reconfig_result; +} + void pdu_session_resource_release_routine::operator()( coro_context>& ctx) { @@ -54,7 +71,7 @@ void pdu_session_resource_release_routine::operator()( // Perform initial sanity checks on incoming message. if (!rrc_ue_up_resource_manager.validate_request(release_cmd)) { logger.warning("ue={}: \"{}\" Invalid PduSessionResourceReleaseCommand", release_cmd.ue_index, name()); - CORO_EARLY_RETURN(generate_pdu_session_resource_release_response(false)); + CORO_EARLY_RETURN(handle_pdu_session_resource_release_response(false)); } { @@ -113,13 +130,48 @@ void pdu_session_resource_release_routine::operator()( } } - CORO_RETURN(generate_pdu_session_resource_release_response(true)); + { + // prepare RRC Reconfiguration and call RRC UE notifier + { + // get NAS PDUs as received by AMF + std::vector nas_pdus; + if (!release_cmd.nas_pdu.empty()) { + nas_pdus.push_back(release_cmd.nas_pdu); + } + + if (!fill_rrc_reconfig_args(rrc_reconfig_args, + {}, + next_config.pdu_sessions_to_modify_list, + next_config.drb_to_remove_list, + ue_context_modification_response.du_to_cu_rrc_info, + nas_pdus, + rrc_ue_notifier.generate_meas_config(), + false, + false, + false, + logger)) { + logger.warning("ue={}: \"{}\" Failed to fill RrcReconfiguration", release_cmd.ue_index, name()); + CORO_EARLY_RETURN(handle_pdu_session_resource_release_response(false)); + } + } + + CORO_AWAIT_VALUE(rrc_reconfig_result, rrc_ue_notifier.on_rrc_reconfiguration_request(rrc_reconfig_args)); + + // Handle RRC Reconfiguration result. + if (handle_procedure_response(response_msg, release_cmd, rrc_reconfig_result, logger) == false) { + logger.warning("ue={}: \"{}\" RRC reconfiguration failed", release_cmd.ue_index, name()); + CORO_EARLY_RETURN(handle_pdu_session_resource_release_response(false)); + } + } + + CORO_RETURN(handle_pdu_session_resource_release_response(true)); } cu_cp_pdu_session_resource_release_response -pdu_session_resource_release_routine::generate_pdu_session_resource_release_response(bool success) +pdu_session_resource_release_routine::handle_pdu_session_resource_release_response(bool success) { if (success) { + logger.debug("ue={}: \"{}\" finalized", release_cmd.ue_index, name()); for (const auto& setup_item : release_cmd.pdu_session_res_to_release_list_rel_cmd) { cu_cp_pdu_session_res_released_item_rel_res item; item.pdu_session_id = setup_item.pdu_session_id; @@ -136,7 +188,11 @@ pdu_session_resource_release_routine::generate_pdu_session_resource_release_resp } rrc_ue_up_resource_manager.apply_config_update(result); + } else { + logger.info("ue={}: \"{}\" failed", release_cmd.ue_index, name()); + + // Trigger UE context release request? } return response_msg; -} +} \ No newline at end of file diff --git a/lib/cu_cp/routines/pdu_session_resource_release_routine.h b/lib/cu_cp/routines/pdu_session_resource_release_routine.h index 9033807869..e5ea247c49 100644 --- a/lib/cu_cp/routines/pdu_session_resource_release_routine.h +++ b/lib/cu_cp/routines/pdu_session_resource_release_routine.h @@ -38,9 +38,11 @@ class pdu_session_resource_release_routine du_processor_e1ap_control_notifier& e1ap_ctrl_notif_, du_processor_f1ap_ue_context_notifier& f1ap_ue_ctxt_notif_, du_processor_ngap_control_notifier& ngap_ctrl_notifier_, + du_processor_rrc_ue_control_message_notifier& rrc_ue_notifier_, du_processor_ue_task_scheduler& task_sched_, - up_resource_manager& rrc_ue_up_resource_manager_, - srslog::basic_logger& logger_); + + up_resource_manager& rrc_ue_up_resource_manager_, + srslog::basic_logger& logger_); void operator()(coro_context>& ctx); @@ -50,30 +52,33 @@ class pdu_session_resource_release_routine void fill_e1ap_bearer_context_modification_request(e1ap_bearer_context_modification_request& e1ap_request); bool valid_5qi(const qos_flow_setup_request_item& flow); - cu_cp_pdu_session_resource_release_response generate_pdu_session_resource_release_response(bool success); + cu_cp_pdu_session_resource_release_response handle_pdu_session_resource_release_response(bool success); const cu_cp_pdu_session_resource_release_command release_cmd; up_config_update next_config; - du_processor_e1ap_control_notifier& e1ap_ctrl_notifier; // to trigger bearer context setup at CU-UP - du_processor_f1ap_ue_context_notifier& f1ap_ue_ctxt_notifier; // to trigger UE context modification at DU - du_processor_ngap_control_notifier& ngap_ctrl_notifier; // to request UE release - du_processor_ue_task_scheduler& task_sched; // to schedule UE release request (over NGAP) - up_resource_manager& rrc_ue_up_resource_manager; // to get RRC DRB config - srslog::basic_logger& logger; + du_processor_e1ap_control_notifier& e1ap_ctrl_notifier; // to trigger bearer context setup at CU-UP + du_processor_f1ap_ue_context_notifier& f1ap_ue_ctxt_notifier; // to trigger UE context modification at DU + du_processor_ngap_control_notifier& ngap_ctrl_notifier; // to request UE release + du_processor_rrc_ue_control_message_notifier& rrc_ue_notifier; // to trigger RRC Reconfiguration at UE + du_processor_ue_task_scheduler& task_sched; // to schedule UE release request (over NGAP) + up_resource_manager& rrc_ue_up_resource_manager; // to get RRC DRB config + srslog::basic_logger& logger; // (sub-)routine requests f1ap_ue_context_modification_request ue_context_mod_request; e1ap_bearer_context_modification_request bearer_context_modification_request; e1ap_bearer_context_release_command bearer_context_release_command; + rrc_reconfiguration_procedure_request rrc_reconfig_args; cu_cp_ue_context_release_request ue_context_release_request; // (sub-)routine results cu_cp_pdu_session_resource_release_response response_msg; f1ap_ue_context_modification_response ue_context_modification_response; // to inform DU about the new DRBs e1ap_bearer_context_modification_response - bearer_context_modification_response; // to inform CU-UP about the new TEID for UL F1u traffic + bearer_context_modification_response; // to inform CU-UP about the new TEID for UL F1u traffic + bool rrc_reconfig_result = false; // the final UE reconfiguration }; } // namespace srs_cu_cp diff --git a/lib/cu_cp/routines/pdu_session_resource_setup_routine.cpp b/lib/cu_cp/routines/pdu_session_resource_setup_routine.cpp index 302a3ff786..7692b32a8f 100644 --- a/lib/cu_cp/routines/pdu_session_resource_setup_routine.cpp +++ b/lib/cu_cp/routines/pdu_session_resource_setup_routine.cpp @@ -211,16 +211,17 @@ void pdu_session_resource_setup_routine::operator()( // if default DRB is being setup, SRB2 needs to be setup as well { // get NAS PDUs as received by AMF - std::map nas_pdus; + std::vector nas_pdus; for (const auto& pdu_session : setup_msg.pdu_session_res_setup_items) { if (!pdu_session.pdu_session_nas_pdu.empty()) { - nas_pdus.emplace(pdu_session.pdu_session_id, pdu_session.pdu_session_nas_pdu); + nas_pdus.push_back(pdu_session.pdu_session_nas_pdu); } } if (!fill_rrc_reconfig_args(rrc_reconfig_args, ue_context_mod_request.srbs_to_be_setup_mod_list, next_config.pdu_sessions_to_setup_list, + {} /* No extra DRB to be removed */, ue_context_modification_response.du_to_cu_rrc_info, nas_pdus, next_config.initial_context_creation ? rrc_ue_notifier.generate_meas_config() diff --git a/lib/cu_cp/routines/pdu_session_routine_helpers.cpp b/lib/cu_cp/routines/pdu_session_routine_helpers.cpp index 1e17e09a4a..f951ccf80a 100644 --- a/lib/cu_cp/routines/pdu_session_routine_helpers.cpp +++ b/lib/cu_cp/routines/pdu_session_routine_helpers.cpp @@ -88,8 +88,9 @@ bool srsran::srs_cu_cp::fill_rrc_reconfig_args( rrc_reconfiguration_procedure_request& rrc_reconfig_args, const slotted_id_vector& srbs_to_be_setup_mod_list, const std::map& pdu_sessions, + const std::vector& drb_to_remove, const f1ap_du_to_cu_rrc_info& du_to_cu_rrc_info, - const std::map& nas_pdus, + const std::vector& nas_pdus, const optional rrc_meas_cfg, bool reestablish_srbs, bool reestablish_drbs, @@ -142,18 +143,27 @@ bool srsran::srs_cu_cp::fill_rrc_reconfig_args( radio_bearer_config.drb_to_add_mod_list.emplace(drb_to_add.first, drb_to_add_mod); } - for (const auto& drb_to_remove : pdu_session_to_add_mod.second.drb_to_remove) { - radio_bearer_config.drb_to_release_list.push_back(drb_to_remove); + // Remove DRB from a PDU session (PDU session itself still exists with out DRBs). + for (const auto& drb_id : pdu_session_to_add_mod.second.drb_to_remove) { + radio_bearer_config.drb_to_release_list.push_back(drb_id); } + } - // append NAS PDUs as received by AMF - if (!nas_pdus.empty()) { - if (nas_pdus.find(pdu_session_to_add_mod.first) != nas_pdus.end()) { - if (!nas_pdus.at(pdu_session_to_add_mod.first).empty()) { - rrc_recfg_v1530_ies.ded_nas_msg_list.push_back(nas_pdus.at(pdu_session_to_add_mod.first).copy()); - } - } + // Remove DRB (if not already) that are not associated with any PDU session anymore. + for (const auto& drb_id : drb_to_remove) { + if (std::any_of(radio_bearer_config.drb_to_release_list.begin(), + radio_bearer_config.drb_to_release_list.end(), + [drb_id](const auto& item) { return item == drb_id; })) { + // The DRB is already set to be removed. + continue; } + + radio_bearer_config.drb_to_release_list.push_back(drb_id); + } + + // append NAS PDUs as received by AMF + for (const auto& nas_pdu : nas_pdus) { + rrc_recfg_v1530_ies.ded_nas_msg_list.push_back(nas_pdu.copy()); } if (update_keys) { diff --git a/lib/cu_cp/routines/pdu_session_routine_helpers.h b/lib/cu_cp/routines/pdu_session_routine_helpers.h index a99760d34e..2c16f8a4df 100644 --- a/lib/cu_cp/routines/pdu_session_routine_helpers.h +++ b/lib/cu_cp/routines/pdu_session_routine_helpers.h @@ -61,8 +61,9 @@ void fill_drb_to_remove_list(std::vector& e1ap_drb_to_remove_lis /// \brief Fill RRC Reconfiguration message content. /// \param[out] rrc_reconfig_args The RRC Reconfiguration Arguments struct to fill. /// \param[in] srbs_to_be_setup_mod_list SRBs to be setup (only needed if default DRB is being setup). -/// \param[in] pdu_sessions The PDU sessions to add to the reconfiguration. -/// \param[in] ue_context_modification_response The UE Context Modification Response as received by the DU. +/// \param[in] pdu_sessions The PDU sessions to add/mod in the reconfiguration. +/// \param[in] drb_to_remove DRB to remove from the configurations. +/// \param[in] du_to_cu_rrc_info RRC container forwarded from the DU to the CU. /// \param[in] nas_pdus NAS PDUs to forward to the UE as received by the AMF. /// \param[in] rrc_meas_cfg Optional measurement config to include in Reconfiguration. /// \param[in] reestablish_srbs Whether to request SRB reestablishment. @@ -73,8 +74,9 @@ bool fill_rrc_reconfig_args( rrc_reconfiguration_procedure_request& rrc_reconfig_args, const slotted_id_vector& srbs_to_be_setup_mod_list, const std::map& pdu_sessions, + const std::vector& drb_to_remove, const f1ap_du_to_cu_rrc_info& du_to_cu_rrc_info, - const std::map& nas_pdus, + const std::vector& nas_pdus, const optional rrc_meas_cfg, bool reestablish_srbs, bool reestablish_drbs, diff --git a/lib/cu_cp/routines/reestablishment_context_modification_routine.cpp b/lib/cu_cp/routines/reestablishment_context_modification_routine.cpp index 403375238f..a9015a35b1 100644 --- a/lib/cu_cp/routines/reestablishment_context_modification_routine.cpp +++ b/lib/cu_cp/routines/reestablishment_context_modification_routine.cpp @@ -124,6 +124,7 @@ void reestablishment_context_modification_routine::operator()(coro_contextnas_pdu_present) { - byte_buffer nas_pdu; - if (!nas_pdu.resize(command->nas_pdu.size())) { - ue_ctxt.logger.log_warning("Unable to resize the storage for the PduSessionResourceReleaseCommand PDU"); - schedule_error_indication(ue_ctxt.ue_ids.ue_index, ngap_cause_radio_network_t::unspecified); - return; - } - std::copy(command->nas_pdu.begin(), command->nas_pdu.end(), nas_pdu.begin()); - ue_ctxt.logger.log_debug(nas_pdu.begin(), nas_pdu.end(), "DlNasTransport PDU ({} B)", nas_pdu.length()); - - ue->get_rrc_ue_pdu_notifier().on_new_pdu(std::move(nas_pdu)); - } - // Convert to common type cu_cp_pdu_session_resource_release_command msg; msg.ue_index = ue_ctxt.ue_ids.ue_index; diff --git a/tests/unittests/cu_cp/du_processor/pdu_session_resource_release_routine_test.cpp b/tests/unittests/cu_cp/du_processor/pdu_session_resource_release_routine_test.cpp index 6a2f5a5118..fec82a8b80 100644 --- a/tests/unittests/cu_cp/du_processor/pdu_session_resource_release_routine_test.cpp +++ b/tests/unittests/cu_cp/du_processor/pdu_session_resource_release_routine_test.cpp @@ -41,7 +41,7 @@ class pdu_session_resource_release_test : public du_processor_routine_manager_te e1ap_ctrl_notifier.set_second_message_outcome(bearer_context_modification_outcome); t = routine_mng->start_pdu_session_resource_release_routine( - msg, ngap_control_notifier, *ue_task_sched, *rrc_ue_up_resource_manager); + msg, ngap_control_notifier, rrc_ue_ctrl_notifier, *ue_task_sched, *rrc_ue_up_resource_manager); t_launcher.emplace(t); }