diff --git a/lib/include/srsran/interfaces/enb_s1ap_interfaces.h b/lib/include/srsran/interfaces/enb_s1ap_interfaces.h index 299f1fe4f..6bb07f353 100644 --- a/lib/include/srsran/interfaces/enb_s1ap_interfaces.h +++ b/lib/include/srsran/interfaces/enb_s1ap_interfaces.h @@ -59,8 +59,9 @@ public: virtual bool user_release(uint16_t rnti, asn1::s1ap::cause_radio_network_e cause_radio) = 0; virtual bool is_mme_connected() = 0; - /// TS 36.413, 8.3.1 - Initial Context Setup - virtual void ue_ctxt_setup_complete(uint16_t rnti) = 0; + // Notify S1AP of RRC reconfiguration successful finish. + // Many S1AP procedures use this notification to indicate successful end (e.g InitialContextSetupRequest) + virtual void notify_rrc_reconf_complete(uint16_t rnti) = 0; /** * Command the s1ap to transmit a HandoverRequired message to MME. diff --git a/srsenb/hdr/stack/s1ap/s1ap.h b/srsenb/hdr/stack/s1ap/s1ap.h index 73e214b93..57b330f4e 100644 --- a/srsenb/hdr/stack/s1ap/s1ap.h +++ b/srsenb/hdr/stack/s1ap/s1ap.h @@ -80,7 +80,7 @@ public: bool user_exists(uint16_t rnti) override; void user_mod(uint16_t old_rnti, uint16_t new_rnti) override; bool user_release(uint16_t rnti, asn1::s1ap::cause_radio_network_e cause_radio) override; - void ue_ctxt_setup_complete(uint16_t rnti) override; + void notify_rrc_reconf_complete(uint16_t rnti) override; bool is_mme_connected() override; bool send_ho_required(uint16_t rnti, uint32_t target_eci, @@ -110,7 +110,7 @@ public: // Stack interface bool - handle_mme_rx_msg(srsran::unique_byte_buffer_t pdu, const sockaddr_in& from, const sctp_sndrcvinfo& sri, int flags); + handle_mme_rx_msg(srsran::unique_byte_buffer_t pdu, const sockaddr_in& from, const sctp_sndrcvinfo& sri, int flags); void start_pcap(srsran::s1ap_pcap* pcap_); private: @@ -168,6 +168,8 @@ private: bool handle_erabreleasecommand(const asn1::s1ap::erab_release_cmd_s& msg); bool handle_uecontextmodifyrequest(const asn1::s1ap::ue_context_mod_request_s& msg); + void ue_ctxt_setup_complete(uint16_t rnti); + // handover /** * Source eNB Handler for S1AP "HANDOVER PREPARATION FAILURE" Message @@ -247,6 +249,7 @@ private: uint32_t m_tmsi = 0, uint8_t mmec = 0); void ue_ctxt_setup_complete(); + void notify_rrc_reconf_complete(); bool send_erab_setup_response(const erab_id_list& erabs_setup, const erab_item_list& erabs_failed); bool send_erab_release_response(const erab_id_list& erabs_released, const erab_item_list& erabs_failed); bool send_erab_modify_response(const erab_id_list& erabs_modified, const erab_item_list& erabs_failed); diff --git a/srsenb/src/stack/rrc/rrc_ue.cc b/srsenb/src/stack/rrc/rrc_ue.cc index 4181a6579..deaea1afc 100644 --- a/srsenb/src/stack/rrc/rrc_ue.cc +++ b/srsenb/src/stack/rrc/rrc_ue.cc @@ -332,9 +332,7 @@ void rrc::ue::parse_ul_dcch(uint32_t lcid, srsran::unique_byte_buffer_t pdu) break; case ul_dcch_msg_type_c::c1_c_::types::ue_cap_info: if (handle_ue_cap_info(&ul_dcch_msg.msg.c1().ue_cap_info())) { - parent->s1ap->ue_ctxt_setup_complete(rnti); send_connection_reconf(std::move(pdu)); - state = RRC_STATE_WAIT_FOR_CON_RECONF_COMPLETE; } else { send_connection_reject(procedure_result_code::none); state = RRC_STATE_IDLE; @@ -475,7 +473,6 @@ void rrc::ue::handle_rrc_con_setup_complete(rrc_conn_setup_complete_s* msg, srsr } else { parent->s1ap->initial_ue(rnti, enb_cc_idx, s1ap_cause, std::move(pdu)); } - state = RRC_STATE_WAIT_FOR_CON_RECONF_COMPLETE; // 2> if the UE has radio link failure or handover failure information available if (msg->crit_exts.type().value == c1_or_crit_ext_opts::c1 and @@ -828,6 +825,9 @@ void rrc::ue::handle_rrc_reconf_complete(rrc_conn_recfg_complete_s* msg, srsran: rlf_info_pending = false; send_ue_info_req(); } + + // Many S1AP procedures end with RRC Reconfiguration. Notify S1AP accordingly. + parent->s1ap->notify_rrc_reconf_complete(rnti); } void rrc::ue::send_ue_info_req() diff --git a/srsenb/src/stack/s1ap/s1ap.cc b/srsenb/src/stack/s1ap/s1ap.cc index 8f408627c..6fb0d8e8e 100644 --- a/srsenb/src/stack/s1ap/s1ap.cc +++ b/srsenb/src/stack/s1ap/s1ap.cc @@ -452,6 +452,15 @@ void s1ap::ue_ctxt_setup_complete(uint16_t rnti) u->ue_ctxt_setup_complete(); } +void s1ap::notify_rrc_reconf_complete(uint16_t rnti) +{ + ue* u = users.find_ue_rnti(rnti); + if (u == nullptr) { + return; + } + u->notify_rrc_reconf_complete(); +} + bool s1ap::is_mme_connected() { return mme_connected; @@ -1461,6 +1470,17 @@ bool s1ap::ue::send_uectxtreleasecomplete() return s1ap_ptr->sctp_send_s1ap_pdu(tx_pdu, ctxt.rnti, "UEContextReleaseComplete"); } +void s1ap::ue::notify_rrc_reconf_complete() +{ + if (current_state == s1ap_elem_procs_o::init_msg_c::types_opts::init_context_setup_request) { + logger.info("Procedure %s,rnti=0x%x - Received RRC reconf complete. Finishing UE context setup.", + s1ap_elem_procs_o::init_msg_c::types_opts{current_state}.to_string(), + ctxt.rnti); + ue_ctxt_setup_complete(); + return; + } +} + void s1ap::ue::ue_ctxt_setup_complete() { if (current_state != s1ap_elem_procs_o::init_msg_c::types_opts::init_context_setup_request) { @@ -1510,7 +1530,7 @@ void s1ap::ue::ue_ctxt_setup_complete() // Log event. event_logger::get().log_s1_ctx_create(ctxt.enb_cc_idx, ctxt.mme_ue_s1ap_id.value(), ctxt.enb_ue_s1ap_id, ctxt.rnti); - s1ap_ptr->sctp_send_s1ap_pdu(tx_pdu, ctxt.rnti, "E-RABSetupResponse"); + s1ap_ptr->sctp_send_s1ap_pdu(tx_pdu, ctxt.rnti, "InitialContextSetupResponse"); } bool s1ap::ue::send_erab_setup_response(const erab_id_list& erabs_setup, const erab_item_list& erabs_failed) diff --git a/srsenb/test/common/dummy_classes.h b/srsenb/test/common/dummy_classes.h index f4aff5085..6887b6546 100644 --- a/srsenb/test/common/dummy_classes.h +++ b/srsenb/test/common/dummy_classes.h @@ -104,7 +104,7 @@ public: void write_pdu(uint16_t rnti, srsran::unique_byte_buffer_t pdu) override {} bool user_exists(uint16_t rnti) override { return true; } bool user_release(uint16_t rnti, asn1::s1ap::cause_radio_network_e cause_radio) override { return true; } - void ue_ctxt_setup_complete(uint16_t rnti) override {} + void notify_rrc_reconf_complete(uint16_t rnti) override {} bool is_mme_connected() override { return true; } bool send_ho_required(uint16_t rnti, uint32_t target_eci, diff --git a/srsenb/test/s1ap/s1ap_test.cc b/srsenb/test/s1ap/s1ap_test.cc index c0641b6e4..5cc888e94 100644 --- a/srsenb/test/s1ap/s1ap_test.cc +++ b/srsenb/test/s1ap/s1ap_test.cc @@ -185,7 +185,7 @@ void add_rnti(s1ap& s1ap_obj, mme_dummy& mme) 0x40, 0x0a, 0x0a, 0x1f, 0x7f, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01}; cbref = asn1::cbit_ref(icsresp, sizeof(icsresp)); TESTASSERT(s1ap_pdu.unpack(cbref) == SRSRAN_SUCCESS); - s1ap_obj.ue_ctxt_setup_complete(0x46); + s1ap_obj.notify_rrc_reconf_complete(0x46); sdu = mme.read_msg(); TESTASSERT(sdu->N_bytes > 0); cbref = asn1::cbit_ref{sdu->msg, sdu->N_bytes}; @@ -329,4 +329,4 @@ int main(int argc, char** argv) test_s1ap_erab_setup(test_event::wrong_erabid_mod); test_s1ap_erab_setup(test_event::wrong_mme_s1ap_id); test_s1ap_erab_setup(test_event::repeated_erabid_mod); -} \ No newline at end of file +}