Sending Initial Context Setup Response after RRC reconfiguration.

master
Pedro Alvarez 4 years ago
parent 4f7a94acb6
commit 18e2149d68

@ -59,8 +59,9 @@ public:
virtual bool user_release(uint16_t rnti, asn1::s1ap::cause_radio_network_e cause_radio) = 0; virtual bool user_release(uint16_t rnti, asn1::s1ap::cause_radio_network_e cause_radio) = 0;
virtual bool is_mme_connected() = 0; virtual bool is_mme_connected() = 0;
/// TS 36.413, 8.3.1 - Initial Context Setup // Notify S1AP of RRC reconfiguration successful finish.
virtual void ue_ctxt_setup_complete(uint16_t rnti) = 0; // 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. * Command the s1ap to transmit a HandoverRequired message to MME.

@ -80,7 +80,7 @@ public:
bool user_exists(uint16_t rnti) override; bool user_exists(uint16_t rnti) override;
void user_mod(uint16_t old_rnti, uint16_t new_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; 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 is_mme_connected() override;
bool send_ho_required(uint16_t rnti, bool send_ho_required(uint16_t rnti,
uint32_t target_eci, uint32_t target_eci,
@ -110,7 +110,7 @@ public:
// Stack interface // Stack interface
bool 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_); void start_pcap(srsran::s1ap_pcap* pcap_);
private: private:
@ -168,6 +168,8 @@ private:
bool handle_erabreleasecommand(const asn1::s1ap::erab_release_cmd_s& msg); bool handle_erabreleasecommand(const asn1::s1ap::erab_release_cmd_s& msg);
bool handle_uecontextmodifyrequest(const asn1::s1ap::ue_context_mod_request_s& msg); bool handle_uecontextmodifyrequest(const asn1::s1ap::ue_context_mod_request_s& msg);
void ue_ctxt_setup_complete(uint16_t rnti);
// handover // handover
/** /**
* Source eNB Handler for S1AP "HANDOVER PREPARATION FAILURE" Message * Source eNB Handler for S1AP "HANDOVER PREPARATION FAILURE" Message
@ -247,6 +249,7 @@ private:
uint32_t m_tmsi = 0, uint32_t m_tmsi = 0,
uint8_t mmec = 0); uint8_t mmec = 0);
void ue_ctxt_setup_complete(); 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_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_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); bool send_erab_modify_response(const erab_id_list& erabs_modified, const erab_item_list& erabs_failed);

@ -332,9 +332,7 @@ void rrc::ue::parse_ul_dcch(uint32_t lcid, srsran::unique_byte_buffer_t pdu)
break; break;
case ul_dcch_msg_type_c::c1_c_::types::ue_cap_info: 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())) { 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)); send_connection_reconf(std::move(pdu));
state = RRC_STATE_WAIT_FOR_CON_RECONF_COMPLETE;
} else { } else {
send_connection_reject(procedure_result_code::none); send_connection_reject(procedure_result_code::none);
state = RRC_STATE_IDLE; state = RRC_STATE_IDLE;
@ -475,7 +473,6 @@ void rrc::ue::handle_rrc_con_setup_complete(rrc_conn_setup_complete_s* msg, srsr
} else { } else {
parent->s1ap->initial_ue(rnti, enb_cc_idx, s1ap_cause, std::move(pdu)); 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 // 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 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; rlf_info_pending = false;
send_ue_info_req(); 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() void rrc::ue::send_ue_info_req()

@ -452,6 +452,15 @@ void s1ap::ue_ctxt_setup_complete(uint16_t rnti)
u->ue_ctxt_setup_complete(); 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() bool s1ap::is_mme_connected()
{ {
return 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"); 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() void s1ap::ue::ue_ctxt_setup_complete()
{ {
if (current_state != s1ap_elem_procs_o::init_msg_c::types_opts::init_context_setup_request) { 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. // 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); 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) bool s1ap::ue::send_erab_setup_response(const erab_id_list& erabs_setup, const erab_item_list& erabs_failed)

@ -104,7 +104,7 @@ public:
void write_pdu(uint16_t rnti, srsran::unique_byte_buffer_t pdu) override {} void write_pdu(uint16_t rnti, srsran::unique_byte_buffer_t pdu) override {}
bool user_exists(uint16_t rnti) override { return true; } 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; } 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 is_mme_connected() override { return true; }
bool send_ho_required(uint16_t rnti, bool send_ho_required(uint16_t rnti,
uint32_t target_eci, uint32_t target_eci,

@ -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}; 0x40, 0x0a, 0x0a, 0x1f, 0x7f, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01};
cbref = asn1::cbit_ref(icsresp, sizeof(icsresp)); cbref = asn1::cbit_ref(icsresp, sizeof(icsresp));
TESTASSERT(s1ap_pdu.unpack(cbref) == SRSRAN_SUCCESS); 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(); sdu = mme.read_msg();
TESTASSERT(sdu->N_bytes > 0); TESTASSERT(sdu->N_bytes > 0);
cbref = asn1::cbit_ref{sdu->msg, sdu->N_bytes}; 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_erabid_mod);
test_s1ap_erab_setup(test_event::wrong_mme_s1ap_id); test_s1ap_erab_setup(test_event::wrong_mme_s1ap_id);
test_s1ap_erab_setup(test_event::repeated_erabid_mod); test_s1ap_erab_setup(test_event::repeated_erabid_mod);
} }

Loading…
Cancel
Save