blob: cf6bcfc690696e6d189da44e58b31e2667e8e1cc [file] [log] [blame]
Harald Welteb8a4ac82019-06-23 11:04:12 +02001/* MME (Mobility Management Engine) test suite in TTCN-3
2 * (C) 2019 Harald Welte <laforge@gnumonks.org>
3 * All rights reserved.
4 *
5 * Released under the terms of GNU General Public License, Version 2 or
6 * (at your option) any later version.
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11module MME_Tests {
12
Harald Welte95333a12019-07-11 22:51:45 +080013import from General_Types all;
Philipp Maier74d776a2023-07-12 14:04:14 +020014import from Native_Functions all;
15import from IPL4asp_Types all;
Harald Welte95333a12019-07-11 22:51:45 +080016import from S1AP_Types all;
17import from S1AP_Templates all;
18import from S1AP_Emulation all;
19import from S1AP_PDU_Descriptions all;
20import from S1AP_IEs all;
21
22import from NAS_EPS_Types all;
23import from NAS_Templates all;
24
Harald Welte6ec64392019-08-14 12:37:07 +020025import from DIAMETER_Types all;
26import from DIAMETER_Templates all;
27import from DIAMETER_Emulation all;
28
Harald Welteb8a4ac82019-06-23 11:04:12 +020029import from SGsAP_Types all;
30import from SGsAP_Templates all;
31import from SGsAP_Emulation all;
32
Philipp Maier74d776a2023-07-12 14:04:14 +020033import from GTP_Emulation all;
34import from GTP_Templates all;
35import from GTP_CodecPort all;
36import from GTPC_Types all;
37
Harald Welte95333a12019-07-11 22:51:45 +080038import from LTE_CryptoFunctions all;
39
Harald Welteb8a4ac82019-06-23 11:04:12 +020040import from L3_Templates all;
41import from DNS_Helpers all;
Harald Welte95333a12019-07-11 22:51:45 +080042import from Osmocom_Types all;
Harald Welteb8a4ac82019-06-23 11:04:12 +020043
44friend module MME_Tests_SGsAP;
45
Harald Welte95333a12019-07-11 22:51:45 +080046/* (maximum) number of emulated eNBs */
47const integer NUM_ENB := 3;
48
49/* (maximum) number of emulated UEs */
50const integer NUM_UE := 3;
51
52/* parameters of emulated ENB */
53type record EnbParams {
54 Global_ENB_ID global_enb_id,
55 integer cell_identity,
56 SupportedTAs supported_tas
57}
58
59/* parameters of emulated UE */
60type record UeParams {
61 hexstring imsi
62}
63
Harald Welteb8a4ac82019-06-23 11:04:12 +020064type component MTC_CT {
Harald Welte95333a12019-07-11 22:51:45 +080065 /* S1 intreface of emulated ENBs */
66 var EnbParams g_enb_pars[NUM_ENB];
67 var S1AP_Emulation_CT vc_S1AP[NUM_ENB];
68 port S1AP_PT S1AP_UNIT[NUM_ENB];
69 port S1APEM_PROC_PT S1AP_PROC[NUM_ENB];
70
Harald Welte6ec64392019-08-14 12:37:07 +020071 /* S6a/S6d interface of emulated HSS */
72 var DIAMETER_Emulation_CT vc_DIAMETER;
73 port DIAMETER_PT DIAMETER_UNIT;
74 port DIAMETEREM_PROC_PT DIAMETER_PROC;
75
Harald Welte95333a12019-07-11 22:51:45 +080076 /* SGs interface of emulated MSC/VLR */
Harald Welteb8a4ac82019-06-23 11:04:12 +020077 var SGsAP_Emulation_CT vc_SGsAP;
78 port SGsAP_PT SGsAP_UNIT;
79 port SGsAPEM_PROC_PT SGsAP_PROC;
Harald Welte95333a12019-07-11 22:51:45 +080080
Philipp Maier74d776a2023-07-12 14:04:14 +020081 /* Gn interface (GTPv1C) of emulated SGSN (Rel. 7) */
82 var GTP_Emulation_CT vc_GTP;
83
Harald Welte95333a12019-07-11 22:51:45 +080084 var UeParams g_ue_pars[NUM_UE];
Harald Welteb8a4ac82019-06-23 11:04:12 +020085}
86
Philipp Maier74d776a2023-07-12 14:04:14 +020087type component ConnHdlr extends S1AP_ConnHdlr, SGsAP_ConnHdlr, DIAMETER_ConnHdlr, GTP_ConnHdlr {
Harald Welteb8a4ac82019-06-23 11:04:12 +020088 var ConnHdlrPars g_pars;
89 timer g_Tguard := 30.0;
Philipp Maier74d776a2023-07-12 14:04:14 +020090
91 var GtpPeer g_gn_iface_peer := { connId := 1, remName := mp_gn_remote_ip, remPort := mp_gn_local_port };
Harald Welteb8a4ac82019-06-23 11:04:12 +020092}
93
94type record ConnHdlrPars {
Harald Welte95333a12019-07-11 22:51:45 +080095 /* copied over from MTC_CT on start of component */
96 EnbParams enb_pars[NUM_ENB],
97 /* copied over from MTC_CT on start of component */
98 UeParams ue_pars,
99 /* currently used MME (index into enb_pars, S1AP, ...) */
100 integer mme_idx
Harald Welteb8a4ac82019-06-23 11:04:12 +0200101}
102
103modulepar {
Harald Welte95333a12019-07-11 22:51:45 +0800104 /* S1 interface */
105 charstring mp_mme_ip := "127.0.0.1";
106 integer mp_mme_s1ap_port := 36412;
107 charstring mp_s1_local_ip := "127.0.0.1";
108 integer mp_s1_local_port := 50000;
109
Harald Welte6ec64392019-08-14 12:37:07 +0200110 /* S6 interface */
111 charstring mp_s6_local_ip := "127.0.0.4";
112 integer mp_s6_local_port := 3868;
113
Harald Welte95333a12019-07-11 22:51:45 +0800114 /* SGs interface */
Harald Welteb8a4ac82019-06-23 11:04:12 +0200115 charstring mp_sgs_local_ip := "127.0.0.1";
116 integer mp_sgs_local_port := 29118;
117 charstring mp_vlr_name := "vlr.example.net";
118 charstring mp_mme_name := "mmec01.mmegi0001.mme.epc.mnc070.mcc901.3gppnetwork.org";
Philipp Maier74d776a2023-07-12 14:04:14 +0200119
120 /* Gn interface (GTPv1C) */
121 charstring mp_gn_local_ip := "127.0.0.22";
122 integer mp_gn_local_port := 2123;
123 charstring mp_gn_remote_ip := "127.0.0.2";
Harald Welteb8a4ac82019-06-23 11:04:12 +0200124}
125
126/* send incoming unit data messages (like reset) to global SGsAP_UNIT port */
127friend function ForwardUnitdataCallback(PDU_SGsAP msg)
128runs on SGsAP_Emulation_CT return template PDU_SGsAP {
129 SGsAP_UNIT.send(msg);
130 return omit;
131}
132
133friend function f_init_sgsap(charstring id) runs on MTC_CT {
134 id := id & "-SGsAP";
135 var SGsAPOps ops := {
136 create_cb := refers(SGsAP_Emulation.ExpectedCreateCallback),
137 unitdata_cb := refers(ForwardUnitdataCallback)
138 }
139 var SGsAP_conn_parameters pars := {
140 remote_ip := "",
141 remote_sctp_port := -1,
142 local_ip := mp_sgs_local_ip,
143 local_sctp_port := mp_sgs_local_port
144 }
145
146 vc_SGsAP := SGsAP_Emulation_CT.create(id);
147 map(vc_SGsAP:SGsAP, system:SGsAP_CODEC_PT);
148 connect(vc_SGsAP:SGsAP_PROC, self:SGsAP_PROC);
149 connect(vc_SGsAP:SGsAP_UNIT, self:SGsAP_UNIT);
150 vc_SGsAP.start(SGsAP_Emulation.main(ops, pars, id));
151}
152
Harald Welte95333a12019-07-11 22:51:45 +0800153/* send incoming unit data messages (like reset) to global S1AP_UNIT port */
154friend function S1apForwardUnitdataCallback(S1AP_PDU msg)
155runs on S1AP_Emulation_CT return template S1AP_PDU {
156 S1AP_UNIT.send(msg);
157 return omit;
158}
159
Harald Welte95333a12019-07-11 22:51:45 +0800160friend function f_init_one_enb(charstring id, integer num := 0) runs on MTC_CT {
161 id := id & "-S1AP" & int2str(num);
162 var S1APOps ops := {
Philipp Maier7147c922023-07-07 14:18:32 +0200163 create_cb := refers(S1AP_Emulation.ExpectedCreateCallback),
Harald Welte95333a12019-07-11 22:51:45 +0800164 unitdata_cb := refers(S1apForwardUnitdataCallback)
165 }
166 var S1AP_conn_parameters pars := {
167 remote_ip := mp_mme_ip,
168 remote_sctp_port := mp_mme_s1ap_port,
169 local_ip := mp_s1_local_ip,
170 local_sctp_port := mp_s1_local_port + num,
171 role := NAS_ROLE_UE
172 }
173 var PLMNidentity plmn_id := '00f110'O;
174 var EnbParams enb_pars := {
175 global_enb_id := {
176 pLMNidentity := plmn_id,
177 eNB_ID := {
178 macroENB_ID := int2bit(num, 20)
179 },
180 iE_Extensions := omit
181 },
182 cell_identity := num,
183 supported_tas := {
184 {
185 tAC := int2oct(12345, 2),
186 broadcastPLMNs := { plmn_id },
187 iE_Extensions := omit
188 }
189 }
190 };
191
192 g_enb_pars[num] := enb_pars;
193 vc_S1AP[num] := S1AP_Emulation_CT.create(id);
194 map(vc_S1AP[num]:S1AP, system:S1AP_CODEC_PT);
195 connect(vc_S1AP[num]:S1AP_PROC, self:S1AP_PROC[num]);
196 connect(vc_S1AP[num]:S1AP_UNIT, self:S1AP_UNIT[num]);
197 vc_S1AP[num].start(S1AP_Emulation.main(ops, pars, id));
198 S1AP_UNIT[num].receive(S1APEM_Event:{up_down:=S1APEM_EVENT_UP});
199}
200friend function f_init_one_ue(inout UeParams uep, integer imsi_suffix) {
201 uep := {
202 imsi := f_gen_imsi(imsi_suffix)
203 }
204}
205friend function f_init_s1ap(charstring id, integer imsi_suffix) runs on MTC_CT {
206 var integer i;
207 for (i := 0; i < NUM_ENB; i := i+1) {
208 f_init_one_enb(id, i);
209 }
210 for (i := 0; i < NUM_UE; i := i+1) {
211 f_init_one_ue(g_ue_pars[i], i*1000 + imsi_suffix);
212 }
213}
214
Harald Welte6ec64392019-08-14 12:37:07 +0200215friend function DiameterForwardUnitdataCallback(PDU_DIAMETER msg)
216runs on DIAMETER_Emulation_CT return template PDU_DIAMETER {
217 DIAMETER_UNIT.send(msg);
218 return omit;
219}
220
221friend function f_init_diameter(charstring id) runs on MTC_CT {
222 var DIAMETEROps ops := {
223 create_cb := refers(DIAMETER_Emulation.ExpectedCreateCallback),
Vadim Yanitskiyb46f01e2021-12-06 03:23:13 +0300224 unitdata_cb := refers(DiameterForwardUnitdataCallback),
225 raw := false /* handler mode (IMSI based routing) */
Harald Welte6ec64392019-08-14 12:37:07 +0200226 };
227 var DIAMETER_conn_parameters pars := {
228 remote_ip := mp_mme_ip,
229 remote_sctp_port := -1,
230 local_ip := mp_s6_local_ip,
Harald Welte61f73d52020-04-26 21:41:12 +0200231 local_sctp_port := mp_s6_local_port,
232 origin_host := "hss.localdomain",
233 origin_realm := "localdomain",
Pau Espin Pedrol33b47492022-03-08 17:43:01 +0100234 auth_app_id := omit,
Harald Welte61f73d52020-04-26 21:41:12 +0200235 vendor_app_id := c_DIAMETER_3GPP_S6_AID
Harald Welte6ec64392019-08-14 12:37:07 +0200236 };
237 vc_DIAMETER := DIAMETER_Emulation_CT.create(id);
238 map(vc_DIAMETER:DIAMETER, system:DIAMETER_CODEC_PT);
239 connect(vc_DIAMETER:DIAMETER_UNIT, self:DIAMETER_UNIT);
240 connect(vc_DIAMETER:DIAMETER_PROC, self:DIAMETER_PROC);
241 vc_DIAMETER.start(DIAMETER_Emulation.main(ops, pars, id));
Harald Welted01b5d02020-04-26 22:05:53 +0200242
243 f_diameter_wait_capability(DIAMETER_UNIT);
Harald Welte6ec64392019-08-14 12:37:07 +0200244}
245
Philipp Maier74d776a2023-07-12 14:04:14 +0200246friend function f_init_gtp(charstring id) runs on MTC_CT {
247 id := id & "-GTP";
248
249 var GtpEmulationCfg gtp_cfg := {
250 gtpc_bind_ip := mp_gn_local_ip,
251 gtpc_bind_port := mp_gn_local_port,
252 gtpu_bind_ip := omit,
253 gtpu_bind_port := omit,
254 sgsn_role := true
255 };
256
257 vc_GTP := GTP_Emulation_CT.create(id);
258 vc_GTP.start(GTP_Emulation.main(gtp_cfg));
259}
260
Harald Welte95333a12019-07-11 22:51:45 +0800261friend template (value) TAI ts_enb_S1AP_TAI(EnbParams enb) := {
262 pLMNidentity := enb.global_enb_id.pLMNidentity,
263 tAC := enb.supported_tas[0].tAC,
264 iE_Extensions := omit
265}
266
267friend template (value) EUTRAN_CGI ts_enb_S1AP_CGI(EnbParams enb) := {
268 pLMNidentity := enb.global_enb_id.pLMNidentity,
269 cell_ID := int2bit(enb.cell_identity, 28),
270 iE_Extensions := omit
271}
272
273
Harald Welteb8a4ac82019-06-23 11:04:12 +0200274/* generate parameters for a connection handler */
Harald Welte95333a12019-07-11 22:51:45 +0800275friend function f_init_pars(integer ue_idx := 0)
Harald Welteb8a4ac82019-06-23 11:04:12 +0200276runs on MTC_CT return ConnHdlrPars {
277 var ConnHdlrPars pars := {
Harald Welte95333a12019-07-11 22:51:45 +0800278 enb_pars := g_enb_pars,
279 ue_pars := g_ue_pars[ue_idx],
280 mme_idx := 0
Harald Welteb8a4ac82019-06-23 11:04:12 +0200281 };
282 return pars;
283}
284
285type function void_fn(ConnHdlrPars pars) runs on ConnHdlr;
286
287/* start a connection handler with given parameters */
288friend function f_start_handler_with_pars(void_fn fn, ConnHdlrPars pars, integer s1ap_idx := 0)
289runs on MTC_CT return ConnHdlr {
290 var ConnHdlr vc_conn;
291 var charstring id := testcasename() & int2str(s1ap_idx);
292
293 vc_conn := ConnHdlr.create(id);
Harald Welte95333a12019-07-11 22:51:45 +0800294 /* S1AP part */
295 connect(vc_conn:S1AP, vc_S1AP[s1ap_idx]:S1AP_CLIENT);
296 connect(vc_conn:S1AP_PROC, vc_S1AP[s1ap_idx]:S1AP_PROC);
297 if (isbound(vc_SGsAP)) {
298 /* SGsAP part */
299 connect(vc_conn:SGsAP, vc_SGsAP:SGsAP_CLIENT);
300 connect(vc_conn:SGsAP_PROC, vc_SGsAP:SGsAP_PROC);
301 }
Harald Welte6ec64392019-08-14 12:37:07 +0200302 if (isbound(vc_DIAMETER)) {
303 connect(vc_conn:DIAMETER, vc_DIAMETER:DIAMETER_CLIENT);
304 connect(vc_conn:DIAMETER_PROC, vc_DIAMETER:DIAMETER_PROC);
305 }
Philipp Maier74d776a2023-07-12 14:04:14 +0200306 if (isbound(vc_GTP)) {
307 connect(vc_conn:GTP, vc_GTP:CLIENT);
308 connect(vc_conn:GTP_PROC, vc_GTP:CLIENT_PROC);
309 }
Harald Welteb8a4ac82019-06-23 11:04:12 +0200310
311 /* We cannot use vc_conn.start(f_init_handler(fn, id, pars)); as we cannot have
312 * a stand-alone 'derefers()' call, see https://www.eclipse.org/forums/index.php/t/1091364/ */
313 vc_conn.start(derefers(fn)(pars));
314 return vc_conn;
315}
316
317/* altstep for the global guard timer */
318private altstep as_Tguard()runs on ConnHdlr {
319 [] g_Tguard.timeout {
320 setverdict(fail, "Tguard timeout");
321 mtc.stop;
322 }
323}
324
325friend function f_init_handler(ConnHdlrPars pars, float t_guard := 30.0) runs on ConnHdlr {
326 /* make parameters available via component variable */
327 g_pars := pars;
328 /* start guard timre and activate it as default */
329 g_Tguard.start(t_guard);
330 activate(as_Tguard());
Harald Welte6ec64392019-08-14 12:37:07 +0200331 if (DIAMETER_PROC.checkstate("Connected")) {
332 f_diameter_expect(g_pars.ue_pars.imsi);
333 }
Harald Welte95333a12019-07-11 22:51:45 +0800334 if (SGsAP_PROC.checkstate("Connected")) {
335 /* Route all SGsAP mesages for our IMSIto us */
336 f_create_sgsap_expect(pars.ue_pars.imsi);
337 }
338}
339
340
341
342friend function f_s1ap_setup(integer idx := 0, template Cause cause := omit) runs on MTC_CT {
343 var template (present) Cause exp_cause;
344 var boolean exp_fail := false;
345 timer T := 5.0;
346 if (not istemplatekind(cause, "omit")) {
347 exp_fail := true;
348 exp_cause := cause;
349 }
350
351 S1AP_UNIT[idx].send(ts_S1AP_SetupReq(g_enb_pars[idx].global_enb_id,
352 g_enb_pars[idx].supported_tas, v32));
353 T.start;
354 alt {
355 [exp_fail] S1AP_UNIT[idx].receive(tr_S1AP_SetupFail(exp_cause)) {
356 setverdict(pass);
357 }
358 [not exp_fail] S1AP_UNIT[idx].receive(tr_S1AP_SetupResp) {
359 setverdict(pass);
360 }
361 [] S1AP_UNIT[idx].receive {
362 setverdict(fail, "Received unexpected S1AP");
363 }
364 [] T.timeout {
365 setverdict(fail, "Timeout waiting for S1AP Setup result");
366 }
367 }
368}
369
370/* Unsuccessful S1 Setup procedure to MME (wrong PLMN) */
371testcase TC_s1ap_setup_wrong_plmn() runs on MTC_CT {
372 var charstring id := testcasename();
373 f_init_s1ap(id, 1);
374 g_enb_pars[0].global_enb_id.pLMNidentity := '62F224'O;
375 f_s1ap_setup(0, {misc:=unknown_PLMN});
376}
377
378/* Unsuccessful S1 Setup procedure to MME (wrong PLMN) */
379testcase TC_s1ap_setup_wrong_tac() runs on MTC_CT {
380 var charstring id := testcasename();
381 f_init_s1ap(id, 2);
382 g_enb_pars[0].supported_tas[0].broadcastPLMNs[0] := '62F224'O;
383 f_s1ap_setup(0, {misc:=unknown_PLMN});
384}
385
386/* Successful S1 Setup procedure to MME */
387testcase TC_s1ap_setup() runs on MTC_CT {
388 var charstring id := testcasename();
389 f_init_s1ap(id, 3);
390 f_s1ap_setup(0);
391}
392
393private const EPS_QualityOfServiceV c_NAS_defaultQoS := {
394 qCI := '00'O,
395 maxBitRateUplink := omit,
396 maxBitRateDownlink := omit,
397 guaranteedBitRateUplink := omit,
398 guaranteedBitRateDownlink := omit,
399 maxBitRateUplinkExt := omit,
400 maxBitRateDownlinkExt := omit,
401 guaranteedBitRateUplinkExt := omit,
402 guaranteedBitRateDownlinkExt := omit,
403 maxBitRateUplinkExt2 := omit,
404 maxBitRateDownlinkExt2 := omit,
405 guaranteedBitRateUplinkExt2 := omit,
406 guaranteedBitRateDownlinkExt2 := omit
407};
408
409private const UENetworkCapabilityV c_NAS_defaultUeNetCap := {
410 eEA := '10000000'B,
411 eIA := '11000000'B,
412 uEA := omit,
413 uIA := omit,
414 uCS2 := omit,
415 nF := omit,
416 vCC := omit,
417 lCS := omit,
418 lPP := omit,
419 aCC_CSFB := omit,
420 h245_ASH := omit,
421 proSe := omit,
422 proSe_dd := omit,
423 proSe_dc := omit,
424 proSe_relay := omit,
425 cP_CIoT := omit,
426 uP_CIoT := omit,
427 s1_Udata := omit,
428 eRwoPDN := omit,
429 hC_CP_CIoT := omit,
430 ePCO := omit,
431 multipleDRB := omit,
432 v2XPC5 := omit,
433 restrictEC := omit,
434 cPbackoff := omit,
435 dCNR := omit,
436 n1Mode := omit,
437 sGC := omit,
438 spare1 := omit,
439 spare := omit
440};
441
442private const octetstring c_NAS_defaultAPN := '00'O;
443
444private altstep as_s1ap_handle_auth() runs on ConnHdlr {
445 var PDU_NAS_EPS rx_nas;
446 [] S1AP.receive(tr_NAS_AuthReq) -> value rx_nas {
447 /* static XRES result as we fixed the HSS RAND value and always have the following
448 RAND: 20080c3818183b522614162c07601d0d
449 AUTN: f11b89a2a8be00001f9c526f3d75d44c
450 IK: 11329aae8e8d2941bb226b2061137c58
451 CK: 740d62df9803eebde5120acf358433d0
452 RES: 6a91970e838fd079
453 SRES: e91e4777
454 Kc: 3b0f999e42198874
455 SQN: 32
456 IND: 0
457 */
458 /* KASME: 95AFAD9A0D29AFAA079A9451DF7161D7EE4CBF2AF9387F766D058BB6B44B905D */
459 const OCT16 ck := '740d62df9803eebde5120acf358433d0'O;
460 const OCT16 ik := '11329aae8e8d2941bb226b2061137c58'O;
461 const OCT16 autn := 'f11b89a2a8be00001f9c526f3d75d44c'O;
462 const OCT8 res := '6a91970e838fd079'O;
463 const OCT3 plmn_id := '00F110'O;
464 const OCT6 sqn := '000000000020'O;
465 const OCT6 ak := substr(autn, 0, 6) xor4b sqn;
466 var octetstring kasme := f_kdf_kasme(ck, ik, plmn_id, sqn, ak);
467 var S1APEM_Config cfg := {
468 set_nas_keys := {
469 k_nas_int := f_kdf_nas_int(1, kasme),
470 k_nas_enc := f_kdf_nas_enc(1, kasme)
471 }
472 };
473 S1AP.send(cfg);
474 S1AP.send(ts_NAS_AuthResp(res));
475 }
476}
477
478private altstep as_s1ap_handle_sec_mode() runs on ConnHdlr {
479 var PDU_NAS_EPS rx_nas;
480 var NAS_SecurityAlgorithmsV alg := {
481 typeOfIntegrityProtection := '001'B,
482 spare1 := '0'B,
483 typeOfCiphering := '000'B,
484 spare2 := '0'B
485 };
486 var NAS_KeySetIdentifierV kset_id := {
487 identifier := '000'B,
488 tSC := '0'B
489 };
490 [] S1AP.receive(tr_NAS_SecModeCmd(alg, kset_id, ?)) {
491 S1AP.send(ts_NAS_SecModeCmpl);
492 }
493}
494
Harald Welte6ec64392019-08-14 12:37:07 +0200495/* Exepect AuthInfoReq (AIR) from HSS; respond with AuthInforAnswer (AIA) */
496private altstep as_DIA_AuthInfo() runs on ConnHdlr {
497 var PDU_DIAMETER rx_dia;
498 [] DIAMETER.receive(tr_DIA_AIR(g_pars.ue_pars.imsi)) -> value rx_dia {
499 var template (omit) AVP avp;
500 var octetstring sess_id;
501 var octetstring vplmn_id;
502 var hexstring imsi;
503 var template (value) AVP_list auth_info_content;
504
505 /* retrieve input data */
506 imsi := valueof(f_DIAMETER_get_imsi(rx_dia));
507 avp := f_DIAMETER_get_avp(rx_dia, c_AVP_Code_BASE_NONE_Session_Id);
508 sess_id := valueof(avp.avp_data.avp_BASE_NONE_Session_Id);
509 avp := f_DIAMETER_get_avp(rx_dia, c_AVP_Code_AAA_3GPP_Visited_PLMN_Id);
510 vplmn_id := valueof(avp.avp_data.avp_AAA_3GPP_Visited_PLMN_Id);
511
512 /* compute tuple */
513 auth_info_content := { ts_AVP_EutranVec(1, '20080c3818183b522614162c07601d0d'O, '6a91970e838fd079'O, 'f11b89a2a8be00001f9c526f3d75d44c'O, '95AFAD9A0D29AFAA079A9451DF7161D7EE4CBF2AF9387F766D058BB6B44B905D'O) };
514
Vadim Yanitskiy2dba4942021-12-11 15:46:30 +0300515 DIAMETER.send(ts_DIA_AIA(auth_info_content, sess_id,
516 hbh_id := rx_dia.hop_by_hop_id,
517 ete_id := rx_dia.end_to_end_id));
Harald Welte6ec64392019-08-14 12:37:07 +0200518 }
519}
520
521/* Expect UpdateLocationReq (ULR); respond with UpdateLocationAnswer (ULA) */
522private altstep as_DIA_UpdLoc() runs on ConnHdlr {
523 var PDU_DIAMETER rx_dia;
524 [] DIAMETER.receive(tr_DIA_ULR(g_pars.ue_pars.imsi)) -> value rx_dia {
525 var template (omit) AVP avp;
Harald Welte6ec64392019-08-14 12:37:07 +0200526 var hexstring imsi;
527 var template (value) AVP_list sub_data;
528
529 /* retrieve input data */
530 imsi := valueof(f_DIAMETER_get_imsi(rx_dia));
531 avp := f_DIAMETER_get_avp(rx_dia, c_AVP_Code_BASE_NONE_Session_Id);
Harald Welte6ec64392019-08-14 12:37:07 +0200532
533 sub_data := {
534 ts_AVP_3GPP_SubscriberStatus(SERVICE_GRANTED),
535 ts_AVP_3GPP_SubscrRauTauTmr(30),
536 ts_AVP_3GPP_AMBR(1000, 2000),
537 ts_AVP_3GPP_ApnConfigProfile({
538 ts_AVP_3GPP_ContextId(1),
539 ts_AVP_3GPP_AllApnConfigsIncl,
540 ts_AVP_3GPP_ApnConfig(1, IPv4, "*")
541 })
542 };
543
Vadim Yanitskiy0e8f5162021-12-15 05:00:32 +0300544 DIAMETER.send(ts_DIA_ULA(sub_data, avp.avp_data.avp_BASE_NONE_Session_Id,
545 hbh_id := rx_dia.hop_by_hop_id,
546 ete_id := rx_dia.end_to_end_id));
Harald Welte6ec64392019-08-14 12:37:07 +0200547 }
548}
549
Harald Welte95333a12019-07-11 22:51:45 +0800550private function f_TC_attach(ConnHdlrPars pars) runs on ConnHdlr {
Harald Welte6ec64392019-08-14 12:37:07 +0200551
Harald Welte95333a12019-07-11 22:51:45 +0800552 f_init_handler(pars);
Harald Welte6ec64392019-08-14 12:37:07 +0200553 var template (value) EPS_MobileIdentityV mi := ts_NAS_MobileId_IMSI(pars.ue_pars.imsi);
Harald Welte95333a12019-07-11 22:51:45 +0800554 var template (value) PDU_NAS_EPS nas_esm, nas_emm;
555/*
556 nas_esm := ts_NAS_ActDefEpsBearCtxReq(bearer_id := '0000'B, proc_tid := int2bit(1,8),
557 qos := c_NAS_defaultQoS, apn := c_NAS_defaultAPN,
558 addr_type := '000'B, addr_info := ''O);
559*/
560 nas_esm := ts_NAS_PdnConnReq(bearer_id := '0000'B, proc_tid := int2bit(1,8),
561 pdn_type := NAS_PDN_T_IPv4, req_type := '001'B);
562 nas_emm := ts_NAS_AttachRequest(att_type := '000'B, kset_id := '000'B, mobile_id := mi,
563 ue_net_cap := c_NAS_defaultUeNetCap,
564 esm_enc := enc_PDU_NAS_EPS(valueof(nas_esm)));
565 var template (value) S1AP_PDU tx;
566 tx := ts_S1AP_InitialUE(p_eNB_value := 0, p_nasPdu := enc_PDU_NAS_EPS(valueof(nas_emm)),
567 p_tAI := ts_enb_S1AP_TAI(g_pars.enb_pars[g_pars.mme_idx]),
568 p_eUTRAN_CGI := ts_enb_S1AP_CGI(g_pars.enb_pars[g_pars.mme_idx]),
569 p_rrcCause := mo_Signalling);
570 S1AP.send(tx);
571
Harald Welte6ec64392019-08-14 12:37:07 +0200572 as_DIA_AuthInfo();
Harald Welte95333a12019-07-11 22:51:45 +0800573 as_s1ap_handle_auth();
Harald Welte6ec64392019-08-14 12:37:07 +0200574 alt {
575 [] as_DIA_UpdLoc() {
576 as_s1ap_handle_sec_mode();
577 }
578 [] as_s1ap_handle_sec_mode() {
579 as_DIA_UpdLoc();
580 }
581 }
Harald Welte95333a12019-07-11 22:51:45 +0800582
583 f_sleep(10.0);
584}
585testcase TC_s1ap_attach() runs on MTC_CT {
586 var charstring id := testcasename();
587
Harald Welte6ec64392019-08-14 12:37:07 +0200588 f_init_diameter(id);
589 f_sleep(10.0);
Harald Welte95333a12019-07-11 22:51:45 +0800590 f_init_s1ap(id, 4);
591 f_s1ap_setup(0);
592
593 var ConnHdlrPars pars := f_init_pars(ue_idx := 0);
594 var ConnHdlr vc_conn;
595 vc_conn := f_start_handler_with_pars(refers(f_TC_attach), pars);
596 vc_conn.done;
597}
598
Philipp Maier74d776a2023-07-12 14:04:14 +0200599private function f_TC_gn_echo_request(ConnHdlrPars pars) runs on ConnHdlr {
600 timer T := 5.0;
601 f_init_handler(pars);
602 f_gtp_register_teid('00000000'O);
603
604 GTP.send(ts_GTPC_PING(g_gn_iface_peer, 1));
605 T.start;
606 alt {
607 [] GTP.receive(tr_GTPC_PONG(?)) {
608 setverdict(pass);
609 }
610 [] GTP.receive {
611 setverdict(fail, "unexpected GTPC message from MME");
612 }
613 [] T.timeout {
614 setverdict(fail, "no GTPC ECHO RESPONSE from MME");
615 }
616 }
617}
618testcase TC_gn_echo_request() runs on MTC_CT {
619 var charstring id := testcasename();
620
621 f_init_diameter(id);
622 f_init_s1ap(id, 4);
623 f_s1ap_setup(0);
624 f_init_gtp(id);
625
626 var ConnHdlrPars pars := f_init_pars(ue_idx := 0);
627 var ConnHdlr vc_conn;
628 vc_conn := f_start_handler_with_pars(refers(f_TC_gn_echo_request), pars);
629 vc_conn.done;
630}
631
Harald Welte95333a12019-07-11 22:51:45 +0800632control {
633 execute( TC_s1ap_setup_wrong_plmn() );
634 execute( TC_s1ap_setup_wrong_tac() );
635 execute( TC_s1ap_setup() );
Harald Welte6ec64392019-08-14 12:37:07 +0200636 execute( TC_s1ap_attach() );
Philipp Maier74d776a2023-07-12 14:04:14 +0200637 execute( TC_gn_echo_request() );
Harald Welteb8a4ac82019-06-23 11:04:12 +0200638}
639
640
641}