jolly submitted this change.

View Change

Approvals: laforge: Looks good to me, but someone else must approve fixeria: Looks good to me, but someone else must approve pespin: Looks good to me, approved Jenkins Builder: Verified
MME-Tests: Add tests for emergency cappability indication

When an attachment is accepted, MME indicates the capability of
emergency calls, if and only if configured in MME's configuration file.
The emergency numbers that are configured are also indicated.

The tests check if the indications follow the configuration and are
correctly encoded.

Related: SYS#7635
Change-Id: I3d84486dd3826d0f60a3c06693118e36b01ecd2b
---
M mme/ConnHdlr.ttcn
M mme/MME_Tests.ttcn
A mme/MME_Tests_emergency.ttcn
M mme/expected-results.xml
A mme/open5gs-mme_emergency.yaml
A mme/testenv_emergency.cfg
R mme/testenv_generic.cfg
7 files changed, 229 insertions(+), 3 deletions(-)

diff --git a/mme/ConnHdlr.ttcn b/mme/ConnHdlr.ttcn
index ab97983..9d259c5 100644
--- a/mme/ConnHdlr.ttcn
+++ b/mme/ConnHdlr.ttcn
@@ -124,6 +124,16 @@
OCT4 tmsi optional
}

+/* parameters of emergency support */
+type record EmergParams {
+ boolean expect_s1_emergency,
+ BIT1 s1_emergency,
+ boolean expect_number,
+ integer numbers,
+ BIT5 categories[8],
+ octetstring digits[8]
+}
+
type record ConnHdlrPars {
/* copied over from MTC_CT on start of component */
EnbParams enb_pars[NUM_ENB],
@@ -135,7 +145,9 @@
/* currently used MME (index into enb_pars, S1AP, ...) */
integer mme_idx,
/* Currently set KSI */
- NAS_KeySetIdentifierV kset_id
+ NAS_KeySetIdentifierV kset_id,
+ /* Expected emergency parameters */
+ EmergParams emerg_pars
}

type component ConnHdlr extends S1AP_ConnHdlr, SGsAP_ConnHdlr, DIAMETER_ConnHdlr, GTP_ConnHdlr, GTP2_ConnHdlr {
@@ -306,14 +318,39 @@
var template (value) E_RABSetupListCtxtSURes rab_setup_items;
var octetstring esm_enc;
var template (value) PDU_NAS_EPS nas;
+ var PDU_NAS_EPS_AttachAccept attach_accept;
var EPS_MobileIdentityTLV mi_tlv;
+ var EPS_NetworkFeatureSupportTLV nfs_tlv;

S1AP.receive(tr_NAS_AttachAccept()) -> value rx_nas;
- mi_tlv := rx_nas.ePS_messages.ePS_MobilityManagement.pDU_NAS_EPS_AttachAccept.gUTI;
+ attach_accept := rx_nas.ePS_messages.ePS_MobilityManagement.pDU_NAS_EPS_AttachAccept;
+ mi_tlv := attach_accept.gUTI;
if (mi_tlv.ePS_MobileIdentity.ePS_MobileIdentity.typeOfIdentity != '110'B) {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Rx GUTI of unexpected MI type: ", mi_tlv));
}
g_pars.ue_pars.guti := mi_tlv.ePS_MobileIdentity.ePS_MobileIdentity.oddEvenInd_identity.guti
+ nfs_tlv := attach_accept.ePS_NetworkFeatureSupport;
+ if (g_pars.emerg_pars.expect_s1_emergency and nfs_tlv.eMCBS != g_pars.emerg_pars.s1_emergency) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Unexpected emergency support: ", nfs_tlv.eMCBS));
+ }
+ if (g_pars.emerg_pars.expect_number) {
+ var template (present) EmergencyNumberListTLV num_list_tlv;
+ var template (present) EmergencyNumberList num_list;
+ for (var integer i := 0; i < g_pars.emerg_pars.numbers; i := i + 1) {
+ num_list[i] := tr_EmergencyNumber(1 + lengthof(g_pars.emerg_pars.digits[i]),
+ g_pars.emerg_pars.categories[i],
+ g_pars.emerg_pars.digits[i]);
+ }
+
+ num_list_tlv := tr_EmergencyNumberListTLV(num_list);
+ if (not match(attach_accept.emergencyNumberList, num_list_tlv)) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Expected emergency number list '", num_list_tlv,
+ "' does not match '", attach_accept.emergencyNumberList,
+ "'."));
+ }
+ }

rab_setup_it := ts_S1AP_RABSetupItemCtxtSURes(rab_id := 5,
tla := oct2bit(f_inet_addr(g_pars.enb_pars[g_pars.mme_idx].gtp1u_local_ip)),
diff --git a/mme/MME_Tests.ttcn b/mme/MME_Tests.ttcn
index 18740bf..df24a09 100644
--- a/mme/MME_Tests.ttcn
+++ b/mme/MME_Tests.ttcn
@@ -54,6 +54,7 @@
import from ConnHdlr all;

friend module MME_Tests_SGsAP;
+friend module MME_Tests_emergency;

/* (maximum) number of emulated UEs */
const integer NUM_UE := 3;
@@ -334,6 +335,7 @@
/* generate parameters for a connection handler */
friend function f_init_pars(integer ue_idx := 0)
runs on MTC_CT return ConnHdlrPars {
+ var integer i;
var ConnHdlrPars pars := {
enb_pars := g_enb_pars,
hss_pars := {
@@ -357,8 +359,20 @@
},
ue_pars := g_ue_pars[ue_idx],
mme_idx := 0,
- kset_id := valueof(ts_NAS_KeySetIdentifierV('000'B, c_NAS_TSC_NATIVE_SEC_CTX))
+ kset_id := valueof(ts_NAS_KeySetIdentifierV('000'B, c_NAS_TSC_NATIVE_SEC_CTX)),
+ emerg_pars := {
+ expect_s1_emergency := false,
+ s1_emergency := '0'B,
+ expect_number := false,
+ numbers := 0
+ }
};
+ for (i := 0; i < sizeof(pars.emerg_pars.categories); i := i + 1) {
+ pars.emerg_pars.categories[i] := '00000'B;
+ }
+ for (i := 0; i < sizeof(pars.emerg_pars.digits); i := i + 1) {
+ pars.emerg_pars.digits[i] := ''O;
+ }
return pars;
}

@@ -787,6 +801,21 @@
vc_conn.done;
}

+private function f_TC_attach_no_emergency() runs on ConnHdlr {
+ f_attach();
+}
+testcase TC_s1ap_attach_no_emergency() runs on MTC_CT {
+ f_init(8, init_diameter := true, init_gtpv2c_s11 := true);
+ f_s1ap_setup(0);
+
+ var ConnHdlrPars pars := f_init_pars(ue_idx := 0);
+ var ConnHdlr vc_conn;
+ pars.emerg_pars.expect_s1_emergency := true;
+ pars.emerg_pars.s1_emergency := '0'B;
+ vc_conn := f_start_handler_with_pars(refers(f_TC_attach_no_emergency), pars);
+ vc_conn.done;
+}
+
control {
execute( TC_s1ap_setup_unknown_global_enb_id_plmn() );
execute( TC_s1ap_setup_wrong_tac() );
@@ -799,6 +828,7 @@
execute( TC_s1ap_reset() );
execute( TC_ue_cell_reselect_eutran_to_geran() );
execute( TC_ue_cell_reselect_geran_to_eutran() );
+ execute( TC_s1ap_attach_no_emergency() );
}


diff --git a/mme/MME_Tests_emergency.ttcn b/mme/MME_Tests_emergency.ttcn
new file mode 100644
index 0000000..4340a58
--- /dev/null
+++ b/mme/MME_Tests_emergency.ttcn
@@ -0,0 +1,66 @@
+module MME_Tests_emergency {
+
+/* Osmocom MME test suite in TTCN-3, emergency call related procedures (3GPP TS 24.301)
+ * (C) 2025 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * All rights reserved.
+ * Author: Andreas Eversberg <aeversberg@sysmocom.de>
+ *
+ * Released under the terms of GNU General Public License, Version 2 or
+ * (at your option) any later version.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+import from General_Types all;
+import from Osmocom_Types all;
+import from Misc_Helpers all;
+import from L3_Templates all;
+import from DNS_Helpers all;
+import from MME_Tests all;
+
+import from NAS_EPS_Templates all;
+
+import from ConnHdlr all;
+
+private function f_TC_emergency_supported() runs on ConnHdlr {
+ f_attach();
+}
+testcase TC_emergency_supported() runs on MTC_CT {
+ f_init(4, init_diameter := true, init_gtpv2c_s11 := true);
+ f_s1ap_setup(0);
+
+ var ConnHdlrPars pars := f_init_pars(ue_idx := 0);
+ var ConnHdlr vc_conn;
+ pars.emerg_pars.expect_s1_emergency := true;
+ pars.emerg_pars.s1_emergency := '1'B;
+ vc_conn := f_start_handler_with_pars(refers(f_TC_emergency_supported), pars);
+ vc_conn.done;
+}
+
+private function f_TC_emergency_number_included() runs on ConnHdlr {
+ f_attach();
+}
+testcase TC_emergency_number_included() runs on MTC_CT {
+ f_init(4, init_diameter := true, init_gtpv2c_s11 := true);
+ f_s1ap_setup(0);
+
+ var ConnHdlrPars pars := f_init_pars(ue_idx := 0);
+ var ConnHdlr vc_conn;
+ pars.emerg_pars.expect_s1_emergency := true;
+ pars.emerg_pars.s1_emergency := '1'B;
+ pars.emerg_pars.expect_number := true;
+ pars.emerg_pars.numbers := 2;
+ pars.emerg_pars.categories[0] := '00001'B; /* police */
+ pars.emerg_pars.digits[0] := '11F0'O; /* 110 */
+ pars.emerg_pars.categories[1] := '00110'B; /* fire + ambulance */
+ pars.emerg_pars.digits[1] := '11F2'O; /* 112 */
+ vc_conn := f_start_handler_with_pars(refers(f_TC_emergency_number_included), pars);
+ vc_conn.done;
+}
+
+control {
+ execute( TC_emergency_supported() );
+ execute( TC_emergency_number_included() );
+}
+
+}
diff --git a/mme/expected-results.xml b/mme/expected-results.xml
index 694b119..c420315 100644
--- a/mme/expected-results.xml
+++ b/mme/expected-results.xml
@@ -11,10 +11,13 @@
<testcase classname='MME_Tests' name='TC_s1ap_reset' time='MASKED'/>
<testcase classname='MME_Tests' name='TC_ue_cell_reselect_eutran_to_geran' time='MASKED'/>
<testcase classname='MME_Tests' name='TC_ue_cell_reselect_geran_to_eutran' time='MASKED'/>
+ <testcase classname='MME_Tests' name='TC_s1ap_attach_no_emergency' time='MASKED'/>
<testcase classname='MME_Tests_SGsAP' name='TC_sgsap_vlr_reset' time='MASKED'/>
<testcase classname='MME_Tests_SGsAP' name='TC_sgsap_paging_sms' time='MASKED'/>
<testcase classname='MME_Tests_SGsAP' name='TC_sgsap_paging_cs' time='MASKED'/>
<testcase classname='MME_Tests_SGsAP' name='TC_sgsap_paging_reject' time='MASKED'/>
<testcase classname='MME_Tests_SGsAP' name='TC_sgsap_alert' time='MASKED'/>
<testcase classname='MME_Tests_SGsAP' name='TC_sgsap_alert_rej' time='MASKED'/>
+ <testcase classname='MME_Tests_emergency' name='TC_emergency_supported' time='MASKED'/>
+ <testcase classname='MME_Tests_emergency' name='TC_emergency_number_included' time='MASKED'/>
</testsuite>
diff --git a/mme/open5gs-mme_emergency.yaml b/mme/open5gs-mme_emergency.yaml
new file mode 100644
index 0000000..5675599
--- /dev/null
+++ b/mme/open5gs-mme_emergency.yaml
@@ -0,0 +1,80 @@
+# See https://github.com/open5gs/open5gs/blob/main/configs/open5gs/mme.yaml.in
+
+logger:
+ level: debug
+
+global:
+ max:
+ ue: 1024
+
+mme:
+ freeDiameter: freediameter.conf
+ s1ap:
+ server:
+ - address: 127.0.0.201
+ gtpc:
+ server:
+ - address: 127.0.0.201
+ client:
+ sgwc:
+ - address: 127.0.0.202
+ smf:
+ - address: 127.0.0.201
+ - address: ::1
+ sgsn:
+ - address:
+ - 127.0.0.202
+ port: 2124
+ routes:
+ - rai:
+ lai:
+ plmn_id:
+ mcc: 262
+ mnc: 42
+ lac: 39594
+ rac: 187
+ ci: 1223
+ metrics:
+ server:
+ - address: 127.0.0.201
+ port: 9090
+ gummei:
+ - plmn_id:
+ mcc: 001
+ mnc: 01
+ mme_gid: 2
+ mme_code: 1
+ tai:
+ - plmn_id:
+ mcc: 001
+ mnc: 01
+ tac: 12345
+ security:
+ integrity_order : [ EIA2, EIA1, EIA0 ]
+ ciphering_order : [ EEA0, EEA1, EEA2 ]
+ network_name:
+ full: Open5GS
+ mme_name: open5gs-mme0
+ sgsap:
+ client:
+ - address: 127.0.0.202 # SCTP server address configured on the MSC/VLR
+ local_address: 127.0.0.201 # SCTP local IP addresses to be bound in the MME
+ map:
+ tai:
+ plmn_id:
+ mcc: 001
+ mnc: 01
+ tac: 12345
+ lai:
+ plmn_id:
+ mcc: 001
+ mnc: 01
+ lac: 43691
+ emergency:
+ dnn: test.sos
+ number:
+ - digits: 110
+ categories: police
+ number:
+ - digits: 112
+ categories: [ fire, ambulance ]
diff --git a/mme/testenv_emergency.cfg b/mme/testenv_emergency.cfg
new file mode 100644
index 0000000..4c1ff91
--- /dev/null
+++ b/mme/testenv_emergency.cfg
@@ -0,0 +1,10 @@
+[testsuite]
+titan_min=11.1.0
+program=MME_Tests
+config=MME_Tests_emergency.cfg
+
+[mme]
+program=open5gs-mmed -c open5gs-mme_emergency.yaml
+make=open5gs
+package=open5gs-mme
+copy=open5gs-mme_emergency.yaml freediameter.conf
diff --git a/mme/testenv.cfg b/mme/testenv_generic.cfg
similarity index 100%
rename from mme/testenv.cfg
rename to mme/testenv_generic.cfg

To view, visit change 41188. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-MessageType: merged
Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Change-Id: I3d84486dd3826d0f60a3c06693118e36b01ecd2b
Gerrit-Change-Number: 41188
Gerrit-PatchSet: 3
Gerrit-Owner: jolly <andreas@eversberg.eu>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanitskiy@sysmocom.de>
Gerrit-Reviewer: jolly <andreas@eversberg.eu>
Gerrit-Reviewer: laforge <laforge@osmocom.org>
Gerrit-Reviewer: pespin <pespin@sysmocom.de>