pespin has submitted this change. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/43907?usp=email )
Change subject: smf: Introduce test TC_n11_createSession_pfcp_sess_est_timeout ......................................................................
smf: Introduce test TC_n11_createSession_pfcp_sess_est_timeout
Change-Id: I8edbfb261b8dfe629326410ced3dbf63491ad029 --- M library/NG_NAS_Osmo_Templates.ttcn M smf/SMF_Session_CT_5G.ttcn M smf/SMF_Tests.ttcn M smf/expected-results.xml 4 files changed, 198 insertions(+), 24 deletions(-)
Approvals: osmith: Looks good to me, but someone else must approve Jenkins Builder: Verified pespin: Looks good to me, approved
diff --git a/library/NG_NAS_Osmo_Templates.ttcn b/library/NG_NAS_Osmo_Templates.ttcn index b2d4e83..f7a481e 100644 --- a/library/NG_NAS_Osmo_Templates.ttcn +++ b/library/NG_NAS_Osmo_Templates.ttcn @@ -881,6 +881,34 @@ } }
+/* 24.501 cl. 8.3.3 */ +template (present) NG_NAS_DL_SM_Message_Type +cr_NG_SM_PDU_SESSION_ESTABLISHMENT_REJECT(template (present) NG_PDU_SessionId p_PDU_SessionId := ?, + template (present) ProcedureTransactionIdentifier p_PTI := ?, + template (present) GMM_GSM_Cause p_Cause := ?, + template GPRS_Timer3 p_BackOff := *, + template AllowedSSCMode p_SSC_Mode := *, + template EAP_Message p_EAP := *, + template ExtdProtocolConfigOptions p_ExtdPCO := *, + template ReAttemptIndicator p_ReAttemptIndicator := *, + template NGSM_CongestionReattemptInd p_NGSM_CongestionReattemptInd := *, // @sic R5s190543 sic@ + template ServiceLvlAAContainer p_ServiceLvlAA := *) := { + pdu_Session_Establishment_Reject := { + protocolDiscriminator := tsc_EPD_GSM, /* cl. 9.2 M V 1 */ + pduSessionId := p_PDU_SessionId, /* cl. 9.4 M V 1 */ + procedureTransactionIdentifier := p_PTI, /* cl. 9.6 M V 1 */ + messageType := tsc_MT_NG_PDUSessionEstablishmentReject, /* cl. 9.7 M V 1 */ + gsmCause := p_Cause, /* cl. 9.11.4.2 M V 1 */ + backOffTimerValue := p_BackOff, /* cl. 9.11.2.5 O TLV 3 IEI=37 */ + allowedSSCMode := p_SSC_Mode, /* cl. 9.11.4.5 O TV 1 IEI=F */ + eapMessage := p_EAP, /* cl. 9.11.2.2 O TLV-E 7-1503 IEI=78 */ + ngsmCongestionReattemptInd := p_NGSM_CongestionReattemptInd, /* cl. 9.11.4.2A O TLV 3 IEI=61 Jun19 @sic R5s201387, R5s210444 Baseline Moving sic@ */ + extdProtocolConfigurationOptions := p_ExtdPCO, /* cl. 9.11.4.6 O TLV-E 4-65538 IEI=0x7B */ + reattemptInd := p_ReAttemptIndicator, /* cl. 9.11.4.17 O TLV 3 IEI=1D Sep20 @sic R5s201387 Baseline Moving sic@ */ + serviceLvlAA := p_ServiceLvlAA /* cl. 9.11.2.10 O TLV-E 6-n IEI=72 Sep22 @sic R5s221179 Baseline Moving sic@ */ + } +} + template (value) NG_NAS_UL_Message_Type cs_NG_PDU_SESSION_MODIFICATION_REQUEST(template (value) NG_PDU_SessionId p_PDU_SessionId, template (value) ProcedureTransactionIdentifier p_PTI, diff --git a/smf/SMF_Session_CT_5G.ttcn b/smf/SMF_Session_CT_5G.ttcn index c550ec2..5343dfd 100644 --- a/smf/SMF_Session_CT_5G.ttcn +++ b/smf/SMF_Session_CT_5G.ttcn @@ -177,15 +177,10 @@ return valueof(http2_tx); }
-/* Nsmf_PDUSession_CreateSMContext Request/response - * 3GPP TS 23.502 Figure 4.3.2.2.1-1 - * 3GPP TS 29.502 6.1.3.2 */ -function f_n11_create_session() -runs on SMF_Session_CT { - var HTTP2_Msg http2_tx; - var HTTP2_Msg http2_rx; - var template (present) HTTP2_Msg http2_exp_rx; +function f_n11_prepare_create_sm_context_pdu_sess_establishment() +runs on SMF_Session_CT return HTTP2_Msg { var template (value) SmContextCreateData sm_contexts; + var HTTP2_Msg http2_tx;
sm_contexts := ts_SmContextCreateData(supi := "imsi-" & g_pars.imsi_str, pei := "imeisv-0790219824011594", @@ -203,6 +198,39 @@
var octetstring nas_enc := f_ng_nas_gen_session_establishment_request(); http2_tx := f_n11_prepare_create_sm_context(valueof(sm_contexts), omit, nas_enc); + return http2_tx; +} + +/* Expect to receive "201 Created body={}" answer to our Nsmf sm-contexts request: */ +altstep as_n11_create_sm_context_pdu_sess_establishment_201_Created(HTTP2_Msg http2_tx) +runs on SMF_Session_CT { + var HTTP2_Msg http2_rx; + var template (present) HTTP2_Msg http2_exp_rx := + tr_HTTP2_Msg(http2_tx.conn_id, + http2_tx.stream_id, + tr_HTTP2_header_block(pseudo_headers := tr_HTTP2_pseudo_headers_Resp(201), + headers := {*, tr_HTTP2_Hdr_location(tr_Nsmf_PDUSession_uri_sm_contexts), *}), + tr_HTTP2_Data_frame(stream_id := http2_tx.stream_id, + end_stream_flag := true, + data := char2oct("{}"))); + + [] as_http2_adapter_receive(http2_rx, http2_exp_rx, idx := http2_tx.conn_id) { + /* Store obtained smContextRef:*/ + var charstring created_location := valueof(f_HTTP2_header_list_find_header(http2_rx.hb.headers, c_HTTP2_HDR_location)); + g_pars.nsmf.smContextRef := regexp(created_location, Nsmf_uri_prefix & Nsmf_PDUSession_path_sm_contexts & "/(?+)", 0); + } +} + +/* Nsmf_PDUSession_CreateSMContext Request/response + * 3GPP TS 23.502 Figure 4.3.2.2.1-1 + * 3GPP TS 29.502 6.1.3.2 */ +function f_n11_create_session() +runs on SMF_Session_CT { + var HTTP2_Msg http2_tx; + var HTTP2_Msg http2_rx; + var template (present) HTTP2_Msg http2_exp_rx; + + http2_tx := f_n11_prepare_create_sm_context_pdu_sess_establishment();
f_http2_adapter_connect(mp_smf_hostname, mp_smf_sbi_port, mp_amf_local_ip, idx := http2_tx.conn_id);
@@ -231,17 +259,7 @@ as_nudm_sdm_post_sdm_subscriptions();
/* Expect to receive "201 Created body={}" answer to our Nsmf sm-contexts request: */ - http2_exp_rx := tr_HTTP2_Msg(http2_tx.conn_id, - http2_tx.stream_id, - tr_HTTP2_header_block(pseudo_headers := tr_HTTP2_pseudo_headers_Resp(201), - headers := {*, tr_HTTP2_Hdr_location(tr_Nsmf_PDUSession_uri_sm_contexts), *}), - tr_HTTP2_Data_frame(stream_id := http2_tx.stream_id, - end_stream_flag := true, - data := char2oct("{}"))); - as_http2_adapter_receive(http2_rx, http2_exp_rx, idx := http2_tx.conn_id); - /* Store obtained smContextRef:*/ - var charstring created_location := valueof(f_HTTP2_header_list_find_header(http2_rx.hb.headers, c_HTTP2_HDR_location)); - g_pars.nsmf.smContextRef := regexp(created_location, Nsmf_uri_prefix & Nsmf_PDUSession_path_sm_contexts & "/(?+)", 0); + as_n11_create_sm_context_pdu_sess_establishment_201_Created(http2_tx); /* Prepare expect for the smContextRef: */ f_http2_server_emu_register(valueof(ts_Nsmf_PDUSession_path_sm_contexts(g_pars.nsmf.smContextRef)), idx := HTTP2_CONN_SCP); @@ -263,7 +281,7 @@ f_Mutex_unlock(__BFILE__, __LINE__); /////////// END MUTUAL EXCLUSION ZONE ////////////
- as_namf_comm_post_n1n2_messages_pdu_sess_establishment(); + as_namf_comm_post_n1n2_messages_pdu_sess_establishment_accept(); f_n11_update_sm_context_pdu_sess_establishment();
if (g_pars.pdn_type == c_PFCP_PDN_Type_IPv6 or @@ -534,7 +552,7 @@ }
/* 5.2.2.3.1 N1N2MessageTransfer, PDU Session establishment (see clause 4.3.2 of 3GPP TS 23.502) */ -private altstep as_namf_comm_post_n1n2_messages_pdu_sess_establishment() +private altstep as_namf_comm_post_n1n2_messages_pdu_sess_establishment_accept() runs on SMF_Session_CT { var HTTP2_Msg http2_rx; var HTTP2_multipart_part_list parts; @@ -574,6 +592,29 @@ } }
+/* 5.2.2.3.1 N1N2MessageTransfer, PDU Session establishment (see clause 4.3.2 of 3GPP TS 23.502) */ +altstep as_namf_comm_post_n1n2_messages_pdu_sess_establishment_reject(template (present) GMM_GSM_Cause exp_cause := ?) +runs on SMF_Session_CT { + var HTTP2_Msg http2_rx; + var HTTP2_multipart_part_list parts; + [] as_namf_comm_post_n1n2_messages(http2_rx, parts) { + var N1N2MessageTransferReqData n1n2msg_req; + var NGAP_IEs.PDUSessionResourceSetupRequestTransfer setup_req_transf; + var template (value) N1N2MessageTransferRspData n1n2msg_rsp; + var NG_NAS_DL_SM_Message_Type dl_nas; + var template (value) HTTP2_Msg http2_tx; + var octetstring body_enc; + + /* Decode 1st part: SBI json: */ + f_dec_N1N2MessageTransferReqData(parts[0].data, n1n2msg_req); // TODO: check returned integer. + + /* Decode 2nd part: NG-NAS: */ + dl_nas := dec_NG_NAS_DL_SM_Message_Type(parts[1].data); + f_ng_nas_handle_session_establishment_reject(dl_nas, exp_cause); + setverdict(pass); + } +} + /* 5.2.2.3.1 N1N2MessageTransfer, PDU Session release (see clause 4.3.4 of TS 3GPP 23.502) * 3GPP TS 23.502 4.3.7 CN-initiated selective deactivation of UP connection of an existing PDU Session */ altstep as_namf_comm_post_n1n2_messages_pdu_sess_release_command() @@ -771,7 +812,7 @@ }
/* 3GPP TS 29.503 5.2.2.2.5 Session Management Subscription Data Retrieval */ -private altstep as_nudm_sdm_get_sm_data() +altstep as_nudm_sdm_get_sm_data() runs on SMF_Session_CT { var HTTP2_Msg http2_rx; [] HTTP2_CONN[HTTP2_CONN_SCP].receive(f_tr_Nudm_SDM_get_sm_data()) -> value http2_rx { @@ -835,7 +876,7 @@ }
/* 3GPP TS 29.503 5.2.2.3.2 Subscription to notifications of data change */ -private altstep as_nudm_sdm_post_sdm_subscriptions() +altstep as_nudm_sdm_post_sdm_subscriptions() runs on SMF_Session_CT { var HTTP2_Msg http2_rx; [] HTTP2_CONN[HTTP2_CONN_SCP].receive(f_tr_Nudm_SDM_post_sdm_subscriptions()) -> value http2_rx { @@ -946,7 +987,7 @@ }
/* 3GPP TS 29.512 4.2.2.2 SM Policy Association establishment */ -private altstep as_npcf_smpolicycontrol_post_sm_policies() +altstep as_npcf_smpolicycontrol_post_sm_policies() runs on SMF_Session_CT { var HTTP2_Msg http2_rx; [] HTTP2_CONN[HTTP2_CONN_SCP].receive(f_tr_Npcf_SMPolicyControl_post_sm_policies()) -> value http2_rx { @@ -1126,6 +1167,7 @@ return nas_enc; }
+/* 3GPP TS 24.501 8.3.2 PDU session establishment accept */ private function f_ng_nas_handle_session_establishment_accept(NG_NAS_DL_SM_Message_Type dl_nas) runs on SMF_Session_CT { var template (present) NG_NAS_DL_SM_Message_Type exp_rx_nas; @@ -1178,6 +1220,20 @@ } }
+/* 3GPP TS 24.501 8.3.3 PDU session establishment reject */ +private function f_ng_nas_handle_session_establishment_reject(NG_NAS_DL_SM_Message_Type dl_nas, template (present) GMM_GSM_Cause exp_cause := ?) +runs on SMF_Session_CT { + var template (present) NG_NAS_DL_SM_Message_Type exp_rx_nas; + var BIT3 pdu_sess_type := f_pfcp_pdn_type_2_ng_nas_pdu_session_type(g_pars.pfcp_pars.pdn_type); + + exp_rx_nas := cr_NG_SM_PDU_SESSION_ESTABLISHMENT_REJECT(p_PDU_SessionId := cs_NG_PDU_SessionIdV(int2oct(g_pars.namf.pdu_sess_id, 1)), + p_Cause := exp_cause); + if (not match(dl_nas, exp_rx_nas)) { + Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, + log2str("Rx unexpected DL NG-NAS: ", dl_nas, " vs exp ", exp_rx_nas)); + } +} + private function f_ng_nas_handle_session_release_command(NG_NAS_DL_SM_Message_Type dl_nas) runs on SMF_Session_CT { var template (present) NG_NAS_DL_SM_Message_Type exp_rx_nas; diff --git a/smf/SMF_Tests.ttcn b/smf/SMF_Tests.ttcn index 6101202..c596baf 100644 --- a/smf/SMF_Tests.ttcn +++ b/smf/SMF_Tests.ttcn @@ -32,9 +32,12 @@
import from HTTP2_Types all; import from HTTP2_Templates all; +import from HTTP2_Msg all; import from HTTP2_Adapter all; import from HTTP2_Server_Emulation all;
+import from NG_NAS_Templates all; + import from Mutex all; import from SMF_Session_CT all; import from SMF_Session_CT_4G all; @@ -809,6 +812,91 @@ f_TC_n11_createSession_deleteSession_250(c_PFCP_PDN_Type_IPv4v6); }
+/* create an IPv4 session, then delete it again */ +private function f_TC_n11_createSession_pfcp_sess_est_timeout() runs on SMF_Session_CT { + var HTTP2_Msg http2_tx; + + var PrometheusExpects expects0 := valueof({ + ts_PrometheusExpect("ues_active", GAUGE, min := 0, max := 0), + ts_PrometheusExpect("pfcp_sessions_active", GAUGE, min := 0, max := 0) + }); + var PrometheusExpects expects1 := valueof({ + ts_PrometheusExpect("ues_active", GAUGE, min := 1, max := 1), + ts_PrometheusExpect("pfcp_sessions_active", GAUGE, min := 1, max := 1) + }); + f_prometheus_expect(expects0, wait_converge := true); + + + /* Subscribe for PFCP Session Establishment Request PDU(s), which are + * expected to have SEID set to 0, as per 3GPP TS 29.244, section 7.2.2.4.2. */ + f_PFCPEM_subscribe_seid(c_SEID0); + + http2_tx := f_n11_prepare_create_sm_context_pdu_sess_establishment(); + f_http2_adapter_connect(mp_smf_hostname, mp_smf_sbi_port, mp_amf_local_ip, idx := http2_tx.conn_id); + f_http2_adapter_send(http2_tx); + + /* PCF: register to rx generic path. We take advantage of the fact that + * we are inside a mutual exclusion zone, so only one session can be here at a time. */ + f_http2_server_emu_register(Npcf_SMPolicyControl_path_sm_policies, idx := HTTP2_CONN_SCP); + + /* Expect UDM to receive GET sm-data: */ + as_nudm_sdm_get_sm_data(); + /* Expect UDM to receive POST sdm-subscriptions: */ + as_nudm_sdm_post_sdm_subscriptions(); + + /* Expect to receive "201 Created body={}" answer to our Nsmf sm-contexts request: */ + as_n11_create_sm_context_pdu_sess_establishment_201_Created(http2_tx); + /* Prepare expect for the smContextRef: */ + f_http2_server_emu_register(valueof(ts_Nsmf_PDUSession_path_sm_contexts(g_pars.nsmf.smContextRef)), + idx := HTTP2_CONN_SCP); + /* Close HTTP2 conn: */ + f_http2_adapter_close(idx := http2_tx.conn_id); + + /* Expect PCF to receive POST sm-policies: */ + as_npcf_smpolicycontrol_post_sm_policies(); + f_http2_server_emu_unregister(Npcf_SMPolicyControl_path_sm_policies, idx := HTTP2_CONN_SCP); + + f_prometheus_expect(expects1, wait_converge := true); + + log("Waiting 1st PFCP Sess Est Req"); + PFCP.receive(f_Session_tr_PFCP_Session_Est_Req()); + log("RX 1st PFCP Sess Est Req"); + PFCP.receive(f_Session_tr_PFCP_Session_Est_Req()); + log("RX 2nd PFCP Sess Est Req"); + PFCP.receive(f_Session_tr_PFCP_Session_Est_Req()); + log("RX 3rd PFCP Sess Est Req"); + + /* SMF deletes policy in PCF: */ + as_npcf_smpolicycontrol_post_IndividualSMPOlicyTermination(); + + /* SMF deregisters on UDM: */ + alt { + [] as_nudm_sdm_delete_IndividualSubscription() { setverdict(pass); } /* expected incoming msg */ + [] as_namf_comm_post_n1n2_messages_pdu_sess_establishment_reject() { /* Unexpecte msg: */ + setverdict(fail, "Received PDU SESS REJ while waiting for UDM! https://github.com/open5gs/open5gs/issues/4878"); + repeat; + } + } + as_nudm_uecm_delete_IndividualSmfRegistration(); + + /* SMF Rejects the Create Session back to the UE: */ + as_namf_comm_post_n1n2_messages_pdu_sess_establishment_reject(cs_GMM_GSM_Cause(omit, int2bit(38 /* Network Failure */, 8))); + f_http2_server_emu_unregister(valueof(ts_Nsmf_PDUSession_path_sm_contexts(g_pars.nsmf.smContextRef)), + idx := HTTP2_CONN_SCP); + f_prometheus_expect(expects0, wait_converge := true); + setverdict(pass); +} +testcase TC_n11_createSession_pfcp_sess_est_timeout() runs on SMF_Test_CT { + var SMF_Session_CT vc_conn; + var SessionPars pars := f_SessionPars(13, + rat_type := GTP2C_RAT_NR); + f_init(); + vc_conn := f_start_handler(refers(f_TC_n11_createSession_pfcp_sess_est_timeout), pars); + vc_conn.done; + f_shutdown(); +} + + /* Validate IUT detects PFCP Heartbeat timeout and recovers from it tearing down * existing subscriber connections: */ private template (value) PrometheusExpects t_TC_5g_pfcp_heartbeat_timeout_Metrics_Expect(integer pfcp_peers_active, integer ues_active) := { @@ -945,6 +1033,7 @@ execute( TC_n11_createSession_deleteSession_250() ); execute( TC_n11_createSession_deleteSession_250_ipv6() ); execute( TC_n11_createSession_deleteSession_250_ipv4v6() ); + execute( TC_n11_createSession_pfcp_sess_est_timeout() ); execute( TC_5g_pfcp_heartbeat_timeout() ); execute( TC_5g_pfcp_heartbeat_recovery_timestamp() ); } diff --git a/smf/expected-results.xml b/smf/expected-results.xml index 2d5c61c..aef27e9 100644 --- a/smf/expected-results.xml +++ b/smf/expected-results.xml @@ -21,6 +21,7 @@ <testcase classname='SMF_Tests' name='TC_n11_createSession_deleteSession_250' time='MASKED'/> <testcase classname='SMF_Tests' name='TC_n11_createSession_deleteSession_250_ipv6' time='MASKED'/> <testcase classname='SMF_Tests' name='TC_n11_createSession_deleteSession_250_ipv4v6' time='MASKED'/> + <testcase classname='SMF_Tests' name='TC_n11_createSession_pfcp_sess_est_timeout' time='MASKED'/> <testcase classname='SMF_Tests' name='TC_5g_pfcp_heartbeat_timeout' time='MASKED'/> <testcase classname='SMF_Tests' name='TC_5g_pfcp_heartbeat_recovery_timestamp' time='MASKED'/> </testsuite>