pespin has submitted this change. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/43905?usp=email )
Change subject: smf: Introduce test TC_5g_pfcp_heartbeat_timeout ......................................................................
smf: Introduce test TC_5g_pfcp_heartbeat_timeout
Change-Id: Id1db247658aa11e10626357fbb47616ba425fb7f --- 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, 223 insertions(+), 5 deletions(-)
Approvals: pespin: Looks good to me, approved Jenkins Builder: Verified osmith: Looks good to me, but someone else must approve
diff --git a/library/NG_NAS_Osmo_Templates.ttcn b/library/NG_NAS_Osmo_Templates.ttcn index eabe221..b2d4e83 100644 --- a/library/NG_NAS_Osmo_Templates.ttcn +++ b/library/NG_NAS_Osmo_Templates.ttcn @@ -1023,6 +1023,33 @@ } };
+template (present) NG_NAS_DL_SM_Message_Type +cr_NG_SM_PDU_SESSION_RELEASE_COMMAND(template (present) NG_PDU_SessionId p_PDU_SessionId := ?, + template (present) ProcedureTransactionIdentifier p_PTI := ?, + template (present) GMM_GSM_Cause p_Cause := ?, + template GPRS_Timer3 p_BackOffTimer := *, + template EAP_Message p_EAP := *, + template NGSM_CongestionReattemptInd p_NGSM_CongestionReattemptInd := *, // @sic R5s190543 sic@ + template ExtdProtocolConfigOptions p_ExtdPCO := *, + template AccessType p_AccessType := *, + template ServiceLvlAAContainer p_ServiceLvlAA := *) := +{ + /* 24.501 cl. 8.3.14 */ + pdu_Session_Release_Command := { + 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_PDUSessionReleaseCommand, /* cl. 9.7 M V 1 */ + gsmCause := p_Cause, /* cl. 9.11.4.2 M V 1 */ + backOffTimerValue := p_BackOffTimer, /* cl. 9.11.2.5 O TLV 3 IEI=37 */ + 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 R5s190543 sic@ */ + extdProtocolConfigurationOptions := p_ExtdPCO, /* cl. 9.11.4.6 O TLV-E 4-65538 IEI=0x7B */ + accessType := p_AccessType, /* cl. 9.11.2.1A O TV 1 IEI=D 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@ */ + } +}; + /* 24.501 cl. 8.3.15 */ template (value) NG_NAS_UL_Message_Type cs_NG_PDU_SESSION_RELEASE_COMPLETE(template (value) NG_PDU_SessionId p_PDU_SessionId, diff --git a/smf/SMF_Session_CT_5G.ttcn b/smf/SMF_Session_CT_5G.ttcn index ab35f03..c550ec2 100644 --- a/smf/SMF_Session_CT_5G.ttcn +++ b/smf/SMF_Session_CT_5G.ttcn @@ -354,7 +354,57 @@ setverdict(pass); }
-/* 3GPP TS 29.502 5.2.2.4 Release SM Context service operation */ +/* 3GPP TS 23.502 4.3.7 CN-initiated selective deactivation of UP connection of an existing PDU Session (step 9) + * 3GPP TS 23.502 Figure 4.3.4.2-1 step 7a */ +function f_n11_update_sm_context_pdu_sess_release_ngap() +runs on SMF_Session_CT { + var template (value) SmContextUpdateData sm_ctx_update; + var template (value) octetstring body_enc; + var integer http2_stream_id := 3; + var HTTP2_Msg http2_tx; + var HTTP2_Msg http2_rx; + + sm_ctx_update := ts_SmContextUpdateData(ueLocation := f_ts_UserLocation(), + n2SmInfo := TS29502_Nsmf_PDUSession_Templates.ts_RefToBinaryData("ngap-sm"), + n2SmInfoType := ts_N2SmInfoType(PDU_RES_REL_RSP)); + var octetstring ngap_enc := enc_NGAP_PDUSessionResourceReleaseResponseTransfer(valueof(m_pDUSessionResourceReleaseResponseTransfer())); + + http2_tx := f_n11_prepare_update_sm_context(valueof(sm_ctx_update), ngap_enc, omit); + + 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); + + /* Successful answer with no content: */ + as_http2_adapter_receive(http2_rx, tr_HTTP2_Msg_204_No_Content(), idx := http2_tx.conn_id); + f_http2_adapter_close(idx := http2_tx.conn_id); + setverdict(pass); +} + +function f_n11_update_sm_context_pdu_sess_release_ngnas() +runs on SMF_Session_CT { + var template (value) SmContextUpdateData sm_ctx_update; + var template (value) octetstring body_enc; + var integer http2_stream_id := 3; + var HTTP2_Msg http2_tx; + var HTTP2_Msg http2_rx; + + sm_ctx_update := ts_SmContextUpdateData(ueLocation := f_ts_UserLocation(), + n1SmMsg := TS29502_Nsmf_PDUSession_Templates.ts_RefToBinaryData("5gnas-sm")); + var octetstring ngnas_enc := f_ng_nas_gen_session_release_complete(); + + http2_tx := f_n11_prepare_update_sm_context(valueof(sm_ctx_update), omit, ngnas_enc); + + 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); + + /* Successful answer with no content: */ + as_http2_adapter_receive(http2_rx, tr_HTTP2_Msg_204_No_Content(), idx := http2_tx.conn_id); + f_http2_adapter_close(idx := http2_tx.conn_id); + setverdict(pass); +} + +/* 3GPP TS 29.502 5.2.2.4 Release SM Context service operation + * 3GPP TS 23.502 Figure 4.3.4.2-1 step 10a */ private function f_n11_prepare_release_sm_context(SmContextReleaseData sm_ctx_rel, template (omit) octetstring ngap_enc := omit) runs on SMF_Session_CT return HTTP2_Msg { @@ -524,6 +574,48 @@ } }
+/* 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() +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.PDUSessionResourceReleaseCommandTransfer rel_cmd_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_release_command(dl_nas); + + /* Decode 3rd part: NGAP: 3GPP TS 24.501 8.3.14 */ + rel_cmd_transf := dec_NGAP_PDUSessionResourceReleaseCommandTransfer(parts[2].data); + f_ngap_pdu_handle_PDUSessionResourceReleaseCommandTransfer(rel_cmd_transf); + + /* Tx answer: */ + n1n2msg_rsp := ts_N1N2MessageTransferRspData(cause := ts_N1N2MessageTransferCause(N1_N2_TRANSFER_INITIATED)) + body_enc := f_enc_N1N2MessageTransferRspData(valueof(n1n2msg_rsp)); + + http2_tx := ts_HTTP2_Msg_200_OK(http2_rx.conn_id, + http2_rx.stream_id, + headers := { + ts_HTTP2_Hdr_content_type("application/json; charset=utf-8") + }, + body := ts_HTTP2_Data_frame(http2_rx.stream_id, + end_stream_flag := true, + data := body_enc)); + HTTP2_CONN[HTTP2_CONN_SCP].send(http2_tx); + setverdict(pass); + } +} + /************************************************ * N10 Nudm (SBI): Emulated UDM, 3GPP TS 29.503 ************************************************/ @@ -642,7 +734,7 @@ }
/* 3GPP TS 29.503 5.3.2.4.4 SMF deregistration */ -private altstep as_nudm_uecm_delete_IndividualSmfRegistration() +altstep as_nudm_uecm_delete_IndividualSmfRegistration() runs on SMF_Session_CT { var HTTP2_Msg http2_rx; [] HTTP2_CONN[HTTP2_CONN_SCP].receive(f_tr_Nudm_UECM_delete_IndividualSmfRegistration()) -> value http2_rx { @@ -793,7 +885,7 @@ }
/* 3GPP TS 29.503 5.2.2.3.2 Subscription to notifications of data change */ -private altstep as_nudm_sdm_delete_IndividualSubscription() +altstep as_nudm_sdm_delete_IndividualSubscription() runs on SMF_Session_CT { var HTTP2_Msg http2_rx; [] HTTP2_CONN[HTTP2_CONN_SCP].receive(f_tr_Nudm_SDM_delete_IndividualSubscription()) -> value http2_rx { @@ -900,7 +992,7 @@ }
/* 3GPP TS 29.503 4.2.5.2 SM Policy Association termination */ -private altstep as_npcf_smpolicycontrol_post_IndividualSMPOlicyTermination() +altstep as_npcf_smpolicycontrol_post_IndividualSMPOlicyTermination() runs on SMF_Session_CT { var HTTP2_Msg http2_rx; [] HTTP2_CONN[HTTP2_CONN_SCP].receive(f_tr_SMPolicyControl_post_IndividualSMPolicyTermination()) -> value http2_rx { @@ -968,6 +1060,17 @@ } }
+private function f_ngap_pdu_handle_PDUSessionResourceReleaseCommandTransfer(NGAP_IEs.PDUSessionResourceReleaseCommandTransfer rel_cmd_transf) +runs on SMF_Session_CT { + var template (present) PDUSessionResourceReleaseCommandTransfer exp; + + exp := mw_pDUSessionResourceReleaseCommandTransfer(p_cause := m_cause_nas(normal_release)) + if (not match(rel_cmd_transf, exp)) { + Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, + log2str("Rx unexpected DL NGAP: ", rel_cmd_transf, " vs exp ", exp)); + } +} + private function f_ngap_pdu_gen_PDUSessionResourceSetupResponseTransfer() runs on SMF_Session_CT return octetstring { var template (value) UPTransportLayerInformation utla; @@ -1075,4 +1178,31 @@ } }
+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; + + exp_rx_nas := cr_NG_SM_PDU_SESSION_RELEASE_COMMAND(p_PDU_SessionId := cs_NG_PDU_SessionIdV(int2oct(g_pars.namf.pdu_sess_id, 1)), + p_Cause := cs_GMM_GSM_Cause(omit, int2bit(39 /* Reactivation Requested */, 8))); + 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)); + } +} + +/* 3GPP TS 24.501 8.3.15 PDU session release complete */ +private function f_ng_nas_gen_session_release_complete() +runs on SMF_Session_CT return octetstring { + var BIT3 pdu_sess_type := f_pfcp_pdn_type_2_ng_nas_pdu_session_type(g_pars.pfcp_pars.pdn_type); + var ProcedureTransactionIdentifier pti := f_next_pti(); + var template (value) NG_NAS_UL_Message_Type nas_ul_msg; + var octetstring nas_enc; + + nas_ul_msg := cs_NG_PDU_SESSION_RELEASE_COMPLETE(cs_NG_PDU_SessionIdV(int2oct(g_pars.namf.pdu_sess_id, 1)), + pti, + cs_GMM_GSM_Cause('59'O, '00100100'B)); + nas_enc := enc_NG_NAS_UL_Message_Type(valueof(nas_ul_msg)); + return nas_enc; +} + } diff --git a/smf/SMF_Tests.ttcn b/smf/SMF_Tests.ttcn index d737688..2c6067b 100644 --- a/smf/SMF_Tests.ttcn +++ b/smf/SMF_Tests.ttcn @@ -809,6 +809,66 @@ f_TC_n11_createSession_deleteSession_250(c_PFCP_PDN_Type_IPv4v6); }
+/* 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) := { + ts_PrometheusExpect("pfcp_peers_active", GAUGE, min := pfcp_peers_active, max := pfcp_peers_active), + ts_PrometheusExpect("ues_active", GAUGE, min := ues_active, max := ues_active), + ts_PrometheusExpect("pfcp_sessions_active", GAUGE, min := ues_active, max := ues_active) +}; +private function f_TC_5g_pfcp_heartbeat_timeout() runs on SMF_Session_CT { + var PDU_PFCP m; + var integer rts := f_PFCPEM_get_recovery_timestamp(); + + f_prometheus_expect(valueof(t_TC_5g_pfcp_heartbeat_timeout_Metrics_Expect(1, 0)), wait_converge := true); + + /* Drop all received Hearbeat requests from IUT: */ + f_PFCPEM_subscribe_bcast(); + var default d := activate(as_pfcp_ignore(PFCP, tr_PFCP_Heartbeat_Req)); + + f_n11_create_session(); + f_prometheus_expect(valueof(t_TC_5g_pfcp_heartbeat_timeout_Metrics_Expect(1, 1)), wait_converge := true); + + /* Wait for IUT to detect peer went down after Heartbeat timeout, ie. wait for sessions + * being released and another ASSOC SETUP REQ to attempt re-association: */ + as_namf_comm_post_n1n2_messages_pdu_sess_release_command(); + f_n11_update_sm_context_pdu_sess_release_ngap(); + f_n11_update_sm_context_pdu_sess_release_ngnas(); + + /* SMF deletes policy in PCF: */ + as_npcf_smpolicycontrol_post_IndividualSMPOlicyTermination(); + + /* SMF deregisters on UDM: */ + as_nudm_sdm_delete_IndividualSubscription(); + as_nudm_uecm_delete_IndividualSmfRegistration(); + + f_prometheus_expect(valueof(t_TC_5g_pfcp_heartbeat_timeout_Metrics_Expect(0, 0)), wait_converge := true); + + PFCP.receive(tr_PFCP_Assoc_Setup_Req()) -> value m; + deactivate(d); + activate(as_pfcp_handle_heartbeat_req(rts, do_repeat := true)); + PFCP.send(ts_PFCP_Assoc_Setup_Resp(m.sequence_number, + ts_PFCP_Node_ID_ipv4(f_inet_addr(mp_pfcp_ip_local)), + ts_PFCP_Cause(PFCP_Cause_REQUEST_ACCEPTED), + rts, + up_function_features := ts_PFCP_UP_Function_Features(ftup := '1'B, + vtime := '1'B))); + + /* After we answer the ASSOC SETUP RESP, IUT detects peer up: */ + f_prometheus_expect(valueof(t_TC_5g_pfcp_heartbeat_timeout_Metrics_Expect(1, 0)), wait_converge := true); + setverdict(pass); +} +testcase TC_5g_pfcp_heartbeat_timeout() runs on SMF_Test_CT { + var SMF_Session_CT vc_conn; + var SessionPars pars := f_SessionPars(9, + rat_type := GTP2C_RAT_NR); + g_pfcp_answer_heartbeat_req := false; + f_init(guard_timeout := 60.0); + vc_conn := f_start_handler(refers(f_TC_5g_pfcp_heartbeat_timeout), pars); + vc_conn.done; + f_shutdown(); +} + control { execute( TC_tx_echo() ); execute( TC_createSession_deleteSession() ); @@ -830,10 +890,10 @@ execute( TC_n11_createSession_deleteSession() ); execute( TC_n11_createSession_deleteSession_ipv6() ); execute( TC_n11_createSession_deleteSession_ipv4v6() ); - execute( TC_n11_createSession_deleteSession_250() ); execute( TC_n11_createSession_deleteSession_250_ipv6() ); execute( TC_n11_createSession_deleteSession_250_ipv4v6() ); + execute( TC_5g_pfcp_heartbeat_timeout() ); }
diff --git a/smf/expected-results.xml b/smf/expected-results.xml index 1493d31..77ba9ca 100644 --- a/smf/expected-results.xml +++ b/smf/expected-results.xml @@ -21,4 +21,5 @@ <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_5g_pfcp_heartbeat_timeout' time='MASKED'/> </testsuite>