blob: d3d3a36f677a27ea41a0a1f6d127a58b2044f422 [file] [log] [blame]
Daniel Willmann19b8d902022-01-05 09:12:34 +01001module HNBGW_Tests {
2
3/* Integration Tests for OsmoHNBGW
4 * (C) 2021 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
5 * All rights reserved.
6 *
7 * Released under the terms of GNU General Public License, Version 2 or
8 * (at your option) any later version.
9 *
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 *
12 * This test suite tests OsmoHNBGW while emulating the hNodeB as well as MSC, SGSN, MGW
13 * See README for more details.
14 */
15
16import from Misc_Helpers all;
17import from General_Types all;
18import from GSM_Types all;
19import from Osmocom_Types all;
20import from IPL4asp_Types all;
21
22import from Osmocom_CTRL_Functions all;
23import from Osmocom_CTRL_Types all;
24import from Osmocom_CTRL_Adapter all;
25
26import from StatsD_Types all;
27import from StatsD_CodecPort all;
28import from StatsD_CodecPort_CtrlFunct all;
29import from StatsD_Checker all;
30
31import from Osmocom_VTY_Functions all;
32import from TELNETasp_PortType all;
33
34import from HNBAP_Templates all;
35import from HNBAP_PDU_Descriptions all;
36
37import from RUA_IEs all;
38import from RUA_Templates all;
39import from RUA_Emulation all;
40
41import from Iuh_Emulation all;
42
43import from RANAP_Types all;
44import from RANAP_PDU_Descriptions all;
45import from RANAP_PDU_Contents all;
46import from RANAP_IEs all;
47import from RANAP_Templates all;
48
49import from RAN_Adapter all;
50
51import from RAN_Adapter all;
52import from RAN_Emulation all;
53
54import from MGCP_Emulation all;
55import from MGCP_Types all;
56import from MGCP_Templates all;
57import from MGCP_CodecPort all;
58import from SDP_Types all;
59
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +020060import from PFCP_Types all;
61import from PFCP_Emulation all;
62import from PFCP_Templates all;
63import from PFCP_CodecPort all;
64
Daniel Willmann19b8d902022-01-05 09:12:34 +010065modulepar {
66 /* IP address at which the HNodeB can be reached */
67 charstring mp_hnodeb_ip := "127.0.0.1";
68 integer mp_hnodeb_port := -1;
69
70 /* IP address at which the test binds */
71 charstring mp_hnbgw_ip := "127.0.0.1";
72 integer mp_hnbgw_iuh_port := 29169;
73
74 charstring mp_mgw_ip := "127.0.0.1";
75 integer mp_mgw_port := 2427;
76
77 RAN_Configuration mp_msc_cfg := {
78 transport := RANAP_TRANSPORT_IuCS,
79 sccp_service_type := "mtp3_itu",
80 sctp_addr := { 23905, "127.0.0.1", 2905, "127.0.0.1" },
81 own_pc := 188, /* 0.23.4 first MSC emulation */
82 own_ssn := 142,
83 peer_pc := 189, /* 0.23.5 osmo-hnbgw */
84 peer_ssn := 142,
85 sio := '83'O,
86 rctx := 1
87 };
88 RAN_Configuration mp_sgsn_cfg := {
89 transport := RANAP_TRANSPORT_IuCS,
90 sccp_service_type := "mtp3_itu",
91 sctp_addr := { 23906, "127.0.0.1", 2905, "127.0.0.1" },
92 own_pc := 185, /* 0.23.1 first SGSN emulation */
93 own_ssn := 142,
94 peer_pc := 189, /* 0.23.5 osmo-hnbgw */
95 peer_ssn := 142,
96 sio := '83'O,
97 rctx := 2
98 };
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +020099
100 /* IP address at which we listen for PFCP to emulate a UPF in ttcn3 */
101 charstring mp_pfcp_ip_local := "127.0.0.1";
102
103 /* IP address from which the SUT (osmo-hnbgw) sends PFCP requests, and to which the ttcn3 UPF emulation sends
104 * PFCP responses. */
105 charstring mp_pfcp_ip_remote := "127.0.0.2";
Daniel Willmann19b8d902022-01-05 09:12:34 +0100106}
107
108function MSC_UnitdataCallback(RANAP_PDU ranap) runs on RAN_Emulation_CT return template RANAP_PDU {
109 // TODO: Actually implement unitdata handling
110 return ts_RANAP_Reset(ts_RanapCause_om_intervention, cs_domain);
111}
112
113const RanOps MSC_RanOps := {
114 ranap_create_cb := refers(RAN_Emulation.RanapExpectedCreateCallback),
115 ranap_unitdata_cb := refers(MSC_UnitdataCallback),
116 ps_domain := false,
117 decode_dtap := false,
118 role_ms := false,
119 protocol := RAN_PROTOCOL_RANAP,
120 transport := RANAP_TRANSPORT_IuCS,
121 use_osmux := false,
Eric Wild6e511ce2022-04-02 21:35:56 +0200122 bssap_reset_retries := 1,
Daniel Willmann19b8d902022-01-05 09:12:34 +0100123 sccp_addr_local := omit,
124 sccp_addr_peer := omit
125}
126
127type record CrcxResponse {
128 integer resp,
129 HostName mgw_rtp_ip,
130 PortNumber mgw_rtp_port,
131 MgcpConnectionId mgcp_connection_id
132}
133type record MgcpParameters {
134 integer got_crcx_count,
135 integer got_dlcx_count,
136 MgcpCallId mgcp_call_id optional,
137 MgcpEndpoint mgcp_ep,
138 CrcxResponse mgw_conn_1,
139 CrcxResponse mgw_conn_2,
140 uint7_t rtp_payload_type,
141 charstring rtp_sdp_format,
142 HostName hnb_rtp_ip,
143 PortNumber hnb_rtp_port,
144 HostName cn_rtp_ip,
145 PortNumber cn_rtp_port,
146 boolean use_osmux,
147 integer got_osmux_count
148}
149
150template (value) MgcpParameters t_MgcpParams := {
151 got_crcx_count := 0,
152 got_dlcx_count := 0,
153 mgcp_call_id := omit,
154 mgcp_ep := "rtpbridge/1@mgw",
155 mgw_conn_1 := {
156 resp := 1,
157 mgw_rtp_ip := "127.1.2.1",
158 mgw_rtp_port := 10000,
159 mgcp_connection_id := '11111'H
160 },
161 mgw_conn_2 := {
162 resp := 1,
163 mgw_rtp_ip := "127.1.2.2",
164 mgw_rtp_port := 20000,
165 mgcp_connection_id := '22222'H
166 },
167 rtp_payload_type := 23,
168 rtp_sdp_format := "FOO",
169 hnb_rtp_ip := "127.1.1.1",
170 hnb_rtp_port := 10001,
171 cn_rtp_ip := "127.1.3.1",
172 cn_rtp_port := 20001,
173 use_osmux := false,
174 got_osmux_count := 0
175}
176
177type record TestHdlrParams {
178 integer hnb_idx,
179 hexstring imsi,
180 boolean ps_domain,
181 MgcpParameters mgcp_pars optional,
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200182 HnbConfig hnb optional,
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200183 boolean separate_sccp_cr,
184 charstring pfcp_local_addr
Daniel Willmann19b8d902022-01-05 09:12:34 +0100185}
186
187/* We extend:
188 * RUA_ConnHdlr (for the Iuh side, emulating the HNB)
189 * RAN_ConnHdlr (for the Iu side, emulating the MSC)
190 * MGCP_ConnHdlr (for the MGCP side, emulating the MGW)
191 */
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200192type component ConnHdlr extends RAN_ConnHdlr, MGCP_ConnHdlr, RUA_ConnHdlr, PFCP_ConnHdlr {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100193 var integer g_sccp_conn_id;
194 var TestHdlrParams g_pars;
195 timer g_Tguard;
196}
197
198
199const MGCPOps MSC_MGCPOps := {
200 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
201 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
202}
203
204function f_create_ranap_exp(octetstring l3_enc) runs on ConnHdlr {
205 BSSAP_PROC.call(RAN_register:{l3_enc, self}) {
206 [] BSSAP_PROC.getreply(RAN_register:{?, ?}) {};
207 }
208}
209
210
Daniel Willmannc79679a2022-08-23 17:48:39 +0200211const integer NUM_HNB := 2;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100212
Daniel Willmann19b8d902022-01-05 09:12:34 +0100213type record HnbConfig {
214 LocationAreaIdentification lai,
215 integer sac
216}
217
218type component test_CT extends CTRL_Adapter_CT {
219 var boolean g_initialized := false;
220
221 /********************* Iu side */
222 var RAN_Adapter g_msc;
223 var RAN_Adapter g_sgsn;
224 /* SGSN IuPS missing */
225
226 /********************* Iuh side */
227 var HnbConfig g_hnb_cfg[NUM_HNB];
228 var Iuh_Emulation_CT vc_Iuh[NUM_HNB];
229 var RUA_Emulation_CT vc_RUA[NUM_HNB];
230 port HNBAP_PT HNBAP[NUM_HNB];
231
232 var MGCP_Emulation_CT vc_MGCP;
233 port TELNETasp_PT HNBGWVTY;
234 /* global test case guard timer (actual timeout value is set in f_init()) */
235 timer T_guard := 30.0;
236}
237
238/* global altstep for global guard timer; */
239altstep as_Tguard() runs on test_CT {
240 [] T_guard.timeout {
241 setverdict(fail, "Timeout of T_guard");
242 mtc.stop;
243 }
244}
245
246friend function f_logp(TELNETasp_PT pt, charstring log_msg)
247{
248 // log on TTCN3 log output
249 log(log_msg);
250 // log in stderr log
251 f_vty_transceive(pt, "logp lglobal notice TTCN3 f_logp(): " & log_msg);
252}
253
254function f_init_vty(charstring id := "foo") runs on test_CT {
255 if (HNBGWVTY.checkstate("Mapped")) {
256 /* skip initialization if already executed once */
257 return;
258 }
259 map(self:HNBGWVTY, system:HNBGWVTY);
260 f_vty_set_prompts(HNBGWVTY);
261 f_vty_transceive(HNBGWVTY, "enable");
262}
263
264function f_init_mgcp(charstring id) runs on test_CT {
265 id := id & "-MGCP";
266 var MGCPOps ops := {
267 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
268 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
269 }
270 var MGCP_conn_parameters pars := {
271 callagent_ip := mp_hnbgw_ip,
272 callagent_udp_port := -1,
273 mgw_ip := mp_mgw_ip,
274 mgw_udp_port := mp_mgw_port,
275 multi_conn_mode := false
276 }
277
278 vc_MGCP := MGCP_Emulation_CT.create(id);
279 map(vc_MGCP:MGCP, system:MGCP_CODEC_PT);
280 vc_MGCP.start(MGCP_Emulation.main(ops, pars, id));
281}
282
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200283function f_init_pfcp(charstring id) runs on ConnHdlr {
284 id := id & "-PFCP";
285
286 var PFCP_Emulation_Cfg pfcp_cfg := {
287 pfcp_bind_ip := mp_pfcp_ip_local,
288 pfcp_bind_port := PFCP_PORT,
289 pfcp_remote_ip := mp_pfcp_ip_remote,
290 pfcp_remote_port := PFCP_PORT,
291 role := UPF
292 };
293
294 vc_PFCP := PFCP_Emulation_CT.create(id) alive;
295 connect(self:PFCP, vc_PFCP:CLIENT);
296 connect(self:PFCP_PROC, vc_PFCP:CLIENT_PROC);
297 vc_PFCP.start(PFCP_Emulation.main(pfcp_cfg));
298}
299
Daniel Willmann19b8d902022-01-05 09:12:34 +0100300function f_init_hnodeb(charstring id, integer hnb_idx, RuaOps rua_ops) runs on test_CT {
301 id := id & "-Iuh" & int2str(hnb_idx);
302
303 /* Iuh lower layer (RUA/HNBAP demux) */
304 var Iuh_conn_parameters iuh_pars;
305 iuh_pars.remote_ip := mp_hnbgw_ip;
306 iuh_pars.remote_sctp_port := mp_hnbgw_iuh_port;
307 iuh_pars.local_ip := mp_hnodeb_ip;
308 iuh_pars.local_sctp_port := mp_hnodeb_port + hnb_idx;
309 vc_Iuh[hnb_idx] := Iuh_Emulation_CT.create(id);
310 connect(self:HNBAP[hnb_idx], vc_Iuh[hnb_idx]:HNBAP);
311
312 vc_RUA[hnb_idx] := RUA_Emulation_CT.create(id & "-RUA");
313 connect(vc_RUA[hnb_idx]:RUA, vc_Iuh[hnb_idx]:RUA);
314
315 /* Start Iuh side components */
316 vc_Iuh[hnb_idx].start(Iuh_Emulation.main(iuh_pars, id));
317 vc_RUA[hnb_idx].start(RUA_Emulation.main(rua_ops, id & "-RUA"));
318}
319
320/* global initialization function */
Neels Hofmeyr82e79b02022-06-08 00:08:09 +0200321function f_init(charstring id := "HNBGW", float guard_timeout := 30.0) runs on test_CT {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100322
Daniel Willmann19b8d902022-01-05 09:12:34 +0100323 T_guard.start(guard_timeout);
324 activate(as_Tguard());
325
326 /* RUA/RANAP emulation on top of lower-layer Iuh */
327 var RuaOps rua_ops := {
328 create_cb := refers(IuhRanapCreateCallback),
329 unitdata_cb := refers(IuhRanapUnitdataCallback)
330 };
331 for (var integer i := 0; i < NUM_HNB; i := i+1) {
Daniel Willmannc79679a2022-08-23 17:48:39 +0200332 g_hnb_cfg[i] := {
333 lai := {
334 mcc_mnc := '00101'H,
335 lac := 2342 + i
336 },
337 sac := 55
338 };
Daniel Willmann19b8d902022-01-05 09:12:34 +0100339 f_init_hnodeb(testcasename(), i, rua_ops);
340 }
341
342 /* MSC emulation */
343 var RanOps ranops := {
344 ranap_create_cb := refers(RAN_Emulation.RanapExpectedCreateCallback),
345 ranap_unitdata_cb := omit,
346 ps_domain := false,
347 decode_dtap := false,
348 role_ms := false,
349 protocol := RAN_PROTOCOL_RANAP,
350 transport := RANAP_TRANSPORT_IuCS,
351 use_osmux := false,
Eric Wild6e511ce2022-04-02 21:35:56 +0200352 bssap_reset_retries := 1,
Daniel Willmann19b8d902022-01-05 09:12:34 +0100353 sccp_addr_local := omit,
354 sccp_addr_peer := omit
355 };
356 f_ran_adapter_init(g_msc, mp_msc_cfg, "HNBGW_Test", ranops);
357 f_ran_adapter_start(g_msc);
358
359 /* SGSN emulation */
360 ranops.ps_domain := true;
361 f_ran_adapter_init(g_sgsn, mp_sgsn_cfg, "HNBGW_Test", ranops);
362 f_ran_adapter_start(g_sgsn);
363
364 f_init_mgcp(id);
365 f_init_vty("VirtHNBGW");
366}
367
368friend function f_shutdown_helper() runs on test_CT {
369 all component.stop;
370 setverdict(pass);
371 mtc.stop;
372}
373
374/* helper function to start all of the simulated hNodeBs */
375function f_start_hnbs() runs on test_CT {
376 for (var integer i:= 0; i < NUM_HNB; i := i+1) {
Daniel Willmannc79679a2022-08-23 17:48:39 +0200377 f_hnbap_register(i, i);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100378 }
379}
380
381/***********************************************************************
382 * code running in test_CT, preparing start of per-UE ConnHdlr
383 ***********************************************************************/
384
385/* inbound RUA connection establishment on Iuh side */
386function IuhRanapCreateCallback(ContextId context_id, RUA_IEs.CN_DomainIndicator domain, charstring id)
387runs on RUA_Emulation_CT return RUA_ConnHdlr {
388 log("CreateCallback");
389 return null;
390}
391
392/* inbound RUA connectionless data on Iuh side */
393function IuhRanapUnitdataCallback(RANAP_PDU ranap)
394runs on RUA_Emulation_CT return template RANAP_PDU {
395 log("UnitdataCallback");
396 return omit;
397}
398
399private function f_start_handler_create(TestHdlrParams pars) runs on test_CT return ConnHdlr {
400 var ConnHdlr vc_conn;
401 var charstring id := testcasename() & int2str(pars.hnb_idx);
402
403 vc_conn := ConnHdlr.create(id);
404
405 /* Iuh RUA part */
406 connect(vc_conn:RUA, vc_RUA[pars.hnb_idx]:CLIENT);
407
408 if (pars.ps_domain) {
409 /* SGSN side */
410 connect(vc_conn:BSSAP, g_sgsn.vc_RAN:CLIENT);
411 connect(vc_conn:BSSAP_PROC, g_sgsn.vc_RAN:PROC);
412 } else {
413 /* MSC side */
414 connect(vc_conn:BSSAP, g_msc.vc_RAN:CLIENT);
415 connect(vc_conn:BSSAP_PROC, g_msc.vc_RAN:PROC);
416 }
417 /* MGCP part */
418 connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT);
419 connect(vc_conn:MGCP_PROC, vc_MGCP:MGCP_PROC);
420
421 return vc_conn;
422}
423
424private function f_start_handler_run(ConnHdlr vc_conn, void_fn fn, TestHdlrParams pars) runs on test_CT {
425 var charstring id := testcasename(); // & int2str(pars.ran_idx);
426 /* We cannot use vc_conn.start(f_init_handler(fn, id, pars)); as we cannot have
427 * a stand-alone 'derefers()' call, see https://www.eclipse.org/forums/index.php/t/1091364/ */
428 pars.hnb := g_hnb_cfg[pars.hnb_idx];
429 pars.mgcp_pars := valueof(t_MgcpParams);
430 vc_conn.start(derefers(fn)(id, pars));
431}
432
433function f_start_handler_with_pars(void_fn fn, template (value) TestHdlrParams pars)
434runs on test_CT return ConnHdlr {
435 var ConnHdlr vc_conn;
436 vc_conn := f_start_handler_create(valueof(pars));
437 f_start_handler_run(vc_conn, fn, valueof(pars));
438 return vc_conn;
439}
440
441/***********************************************************************
442 * code running inside per-UE ConnHdlr
443 ***********************************************************************/
444
445type function void_fn(charstring id, TestHdlrParams pars) runs on ConnHdlr;
446
447function f_init_handler(TestHdlrParams pars, float t_guard := 20.0) runs on ConnHdlr {
448 /* make parameters available via component variable */
449 g_pars := pars;
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200450
451 f_init_pfcp(testcasename());
452
Daniel Willmann19b8d902022-01-05 09:12:34 +0100453 /* start guard timer and activate it as default */
454 g_Tguard.start(t_guard);
455 activate(as_Tguard_ConnHdlr());
456
457 /* TODO: CTRL? */
458 /* TODO: VTY? */
459}
460
461/* global altstep for global guard timer; */
462private altstep as_Tguard_ConnHdlr() runs on ConnHdlr {
463 [] g_Tguard.timeout {
464 setverdict(fail, "Timeout of T_guard");
465 mtc.stop;
466 }
467}
468
469/* send RANAP on Iuh and expect it to show up on Iu */
470function f_iuh2iu(template (present) RANAP_PDU tx, template RANAP_PDU exp_rx := omit)
471runs on ConnHdlr return RANAP_PDU {
472 var RANAP_PDU rx;
473 timer T := 5.0;
474
475 if (istemplatekind(exp_rx, "omit")) {
476 exp_rx := tx;
477 }
478
479 RUA.send(tx);
480 T.start;
481
482 alt {
483 [] BSSAP.receive(exp_rx) -> value rx {
484 setverdict(pass);
485 }
486 [] T.timeout {
487 setverdict(fail, "Timeout waiting for Iu ", exp_rx);
488 }
489 }
490 return rx;
491}
492
493/* send RANAP on Iu and expect it to show up on Iuh */
494function f_iu2iuh(template (present) RANAP_PDU tx, template RANAP_PDU exp_rx := omit)
495runs on ConnHdlr return RANAP_PDU {
496 var RANAP_PDU rx;
497 timer T := 5.0;
498
499 if (istemplatekind(exp_rx, "omit")) {
500 exp_rx := tx;
501 }
502
503 BSSAP.send(tx);
504 T.start;
505
506 alt {
507 [] RUA.receive(exp_rx) -> value rx {
508 setverdict(pass);
509 }
510 [] T.timeout {
511 setverdict(fail, "Timeout waiting for Iuh ", exp_rx);
512 }
513 }
514 return rx;
515}
516
517/* send RANAP on Iuh and expect it to show up on Iu */
518function f_iuh2iu_connect(template (present) RANAP_PDU tx, template RANAP_PDU exp_rx := omit)
519runs on ConnHdlr return RANAP_PDU {
520 var RANAP_PDU rx;
521 timer T := 5.0;
522
523 if (istemplatekind(exp_rx, "omit")) {
524 exp_rx := tx;
525 }
526
527 /* create an expect on the Iu side for the random NAS portion */
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200528 if (g_pars.separate_sccp_cr) {
529 f_ran_register_sccp_cr_without_payload();
530 } else {
531 var template (omit) octetstring nas := f_ranap_extract_l3(valueof(tx));
532 f_ran_register_exp(valueof(nas));
533 }
Daniel Willmann19b8d902022-01-05 09:12:34 +0100534
535 /* send it via Iuh (creating a RUA connection) */
536 RUA.send(RUA_Conn_Req:{g_pars.ps_domain, tx});
537
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200538 if (g_pars.separate_sccp_cr) {
539 /* Acknowledge the empty SCCP CR. RAN_Emulation does the confirmation, no need to respond. */
540 BSSAP.receive(tr_RANAP_Conn_Req());
541 }
542
Daniel Willmann19b8d902022-01-05 09:12:34 +0100543 /* expect to receive it on the Iu side */
544 T.start;
545 alt {
546 [] BSSAP.receive(exp_rx) -> value rx {
547 setverdict(pass);
548 }
549 [] T.timeout {
550 setverdict(fail, "Timeout waiting for Iu ", exp_rx);
551 }
552 }
553 return rx;
554}
555
556function f_iuh2iu_disconnect(template (present) RANAP_PDU tx, RUA_IEs.Cause cause,
557 template RANAP_PDU exp_rx := omit)
558runs on ConnHdlr return RANAP_PDU {
559 var RANAP_PDU rx
560 timer T := 5.0;
561
562 if (istemplatekind(exp_rx, "omit")) {
563 exp_rx := tx;
564 }
565
566 /* send it via Iuh (creating a RUA connection) */
567 RUA.send(RUA_Disc_Req:{tx, cause});
568
569 /* expect to receive it on the Iu side */
570 T.start;
571 alt {
572 [] BSSAP.receive(exp_rx) -> value rx {
573 }
574 [] T.timeout {
575 setverdict(fail, "Timeout waiting for Iu ", exp_rx);
576 return rx;
577 }
578 }
579
580 /* expect disconnect on the Iu side */
581 alt {
582 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {
583 setverdict(pass);
584 }
585 [] T.timeout {
586 setverdict(fail, "Timeout waiting for Iu disconnect");
587 return rx;
588 }
589
590 }
591 return rx;
592}
593
594/* build a RANAP InitialUE based on the TestHdlrParams */
595friend function f_build_initial_ue(TestHdlrParams pars) return RANAP_PDU {
596 var LAI lai := {
597 pLMNidentity := hex2oct(pars.hnb.lai.mcc_mnc),
598 lAC := int2oct(pars.hnb.lai.lac, 2),
599 iE_Extensions := omit
600 };
601 var SAI sai := {
602 pLMNidentity := lai.pLMNidentity,
603 lAC := lai.lAC,
604 sAC := int2oct(pars.hnb.sac, 2),
605 iE_Extensions := omit
606 }
607 var octetstring nas := f_rnd_octstring(10);
608 var IuSignallingConnectionIdentifier sigc_id := int2bit(f_rnd_int(1000), 24);
609 var GlobalRNC_ID grnc_id := {
610 pLMNidentity := lai.pLMNidentity,
611 rNC_ID := 2342
612 }
613
614 if (pars.ps_domain) {
615 var RAC rac := '00'O;
616 return valueof(ts_RANAP_initialUE_PS(lai, rac, sai, nas, sigc_id, grnc_id));
617 } else {
618 return valueof(ts_RANAP_initialUE_CS(lai, sai, nas, sigc_id, grnc_id));
619 }
620}
621
622/* build a RANAP RAB AssignmentResponse based on the TestHdlrParams */
623friend function f_build_rab_ass_resp(TestHdlrParams pars) return RANAP_PDU {
624 var template RAB_SetupOrModifiedList rab_sml;
625
626 rab_sml := ts_RAB_SMdL(t_RAB_id(23), f_ts_RAB_TLA("192.168.1.23"), t_RAB_binding_port(1234));
627
628 return valueof(ts_RANAP_RabAssResp(rab_sml));
629}
630
631
632/***********************************************************************
633 * HNBAP Testing
634 ***********************************************************************/
635
636
Daniel Willmannc79679a2022-08-23 17:48:39 +0200637function f_hnbap_register(integer hnb_idx := 0, integer cell_id := 0, boolean expect_reject := false) runs on test_CT
Daniel Willmann19b8d902022-01-05 09:12:34 +0100638{
639 timer T := 2.0;
640
641 HNBAP[hnb_idx].send(tr_HNBAP_HNBRegisterRequest(char2oct("TTCN3 HNodeB"),
642 '00F110'O,
Daniel Willmannc79679a2022-08-23 17:48:39 +0200643 int2bit(1 + cell_id, 28),
Daniel Willmann19b8d902022-01-05 09:12:34 +0100644 int2oct(2, 2),
645 int2oct(3, 1),
646 int2oct(4, 2)));
647
648 T.start;
649 alt {
650 [] HNBAP[hnb_idx].receive(tr_HNBAP_HNBRegisterAccept(?)) {
Daniel Willmannc79679a2022-08-23 17:48:39 +0200651 if (expect_reject) {
652 setverdict(fail, "Rx HNB Register Accept while expecting reject");
653 } else {
654 setverdict(pass);
655 }
656 }
657 [] HNBAP[hnb_idx].receive(tr_HNBAP_HNBRegisterReject(?)) {
658 if (expect_reject) {
659 setverdict(pass);
660 } else {
661 setverdict(fail, "Rx HNB Register Reject while expecting accept");
662 }
Daniel Willmann19b8d902022-01-05 09:12:34 +0100663 }
664 [] HNBAP[hnb_idx].receive(IUHEM_Event:?) {
665 repeat;
666 }
667 [] T.timeout {
Daniel Willmannc79679a2022-08-23 17:48:39 +0200668 setverdict(fail, "Timeout waiting for HNB Register response");
Daniel Willmann19b8d902022-01-05 09:12:34 +0100669 }
670 }
671}
672
673testcase TC_hnb_register() runs on test_CT {
674 f_init();
675 f_hnbap_register(0);
676 f_shutdown_helper();
677}
678
Daniel Willmannc79679a2022-08-23 17:48:39 +0200679testcase TC_hnb_register_duplicate() runs on test_CT {
680 f_init();
681 f_hnbap_register(0);
682 f_hnbap_register(1, 0, expect_reject := true);
683 f_verify_talloc_count(HNBGWVTY, {"struct hnb_context"}, expect_count := 1);
684 f_shutdown_helper();
685}
686
Daniel Willmann19b8d902022-01-05 09:12:34 +0100687/***********************************************************************
688 * RUA / RANAP Testing
689 ***********************************************************************/
690
691private template (value) TestHdlrParams
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200692t_pars(integer imsi_suffix, boolean ps_domain := false, integer hnb_idx := 0,
693 boolean separate_sccp_cr := false) := {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100694 hnb_idx := hnb_idx,
695 imsi := f_gen_imsi(imsi_suffix),
696 ps_domain := ps_domain,
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200697 hnb := omit, /* filled in later */
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200698 separate_sccp_cr := separate_sccp_cr,
699 pfcp_local_addr := mp_pfcp_ip_local
Daniel Willmann19b8d902022-01-05 09:12:34 +0100700}
701
702/* Create an Iuh connection; send InitialUE; expect it to appear on new SCCP conenction */
703friend function f_tc_initial_ue(charstring id, TestHdlrParams pars) runs on ConnHdlr {
704 f_init_handler(pars);
705 var RANAP_PDU tx := f_build_initial_ue(g_pars);
706 f_iuh2iu_connect(tx);
707}
708testcase TC_ranap_cs_initial_ue() runs on test_CT {
709 var ConnHdlr vc_conn;
710
711 f_init();
712 f_start_hnbs();
713
714 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(1));
715 vc_conn.done;
716}
717testcase TC_ranap_ps_initial_ue() runs on test_CT {
718 var ConnHdlr vc_conn;
719
720 f_init();
721 f_start_hnbs();
722
723 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(2, true));
724 vc_conn.done;
725}
726
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200727private function f_vty_set_sccp_cr_max_payload_len(TELNETasp_PT pt, integer val := 999999)
728{
729 f_vty_enter_config(pt);
730 f_vty_transceive(pt, "hnbgw");
731 f_vty_transceive(pt, "sccp cr max-payload-len " & int2str(val));
732 f_vty_transceive(pt, "end");
733}
734
735testcase TC_ranap_cs_initial_ue_empty_cr() runs on test_CT {
736 var ConnHdlr vc_conn;
737
738 f_init();
739 f_start_hnbs();
740
741 f_vty_set_sccp_cr_max_payload_len(HNBGWVTY, 0);
742
743 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(1, separate_sccp_cr := true));
744 vc_conn.done;
745
746 /* reset */
747 f_vty_set_sccp_cr_max_payload_len(HNBGWVTY);
748}
749testcase TC_ranap_ps_initial_ue_empty_cr() runs on test_CT {
750 var ConnHdlr vc_conn;
751
752 f_init();
753 f_start_hnbs();
754
755 f_vty_set_sccp_cr_max_payload_len(HNBGWVTY, 0);
756
757 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(2, true, separate_sccp_cr := true));
758 vc_conn.done;
759
760 /* reset */
761 f_vty_set_sccp_cr_max_payload_len(HNBGWVTY);
762}
763
Daniel Willmann19b8d902022-01-05 09:12:34 +0100764/* Reply to a received CRCX with an OK (or the reply configured in cpars), using the given parameters.
765 * Return true when an OK reply was sent, false otherwise.
766 * Count occurrence of Osmux, include Osmux parameters in the reply if necessary. */
767function f_handle_crcx(inout MgcpParameters pars, MgcpCommand mgcp_cmd) return template MgcpResponse {
768 var CrcxResponse conn := pars.mgw_conn_1;
769 if (pars.got_crcx_count > 0) {
770 conn := pars.mgw_conn_2;
771 }
772 pars.got_crcx_count := pars.got_crcx_count + 1;
773
774 var MgcpMessage mgcp_msg := {
775 command := mgcp_cmd
776 }
777 var template MgcpResponse mgcp_resp;
778 var MgcpOsmuxCID osmux_cid;
779 var MgcpCallId call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
780 if (ispresent(pars.mgcp_call_id)) {
781 if (pars.mgcp_call_id != call_id) {
782 setverdict(fail, "CRCX contained unexpected call id. Expected:", pars.mgcp_call_id, " got:", call_id);
783 mtc.stop;
784 }
785 } else {
786 pars.mgcp_call_id := call_id;
787 }
788
789 /* When the endpoint contains a wildcard we keep the endpoint
790 * identifier we have set up in pars. Otherwise we use the
791 * endpoint name that the call agent has supplied */
792 if (match(mgcp_cmd.line.ep, t_MGCP_EP_wildcard) == false) {
793 pars.mgcp_ep := mgcp_cmd.line.ep;
794 }
795
796 if (conn.resp == -1) {
797 /* Reply with rror */
798 var MgcpResponse mgcp_rsp := {
799 line := {
800 code := "542",
801 trans_id := mgcp_cmd.line.trans_id,
802 string := "FORCED_FAIL"
803 },
804 sdp := omit
805
806 }
807 var MgcpParameter mgcp_rsp_param := {
808 code := "Z",
809 val := pars.mgcp_ep
810 };
811 mgcp_rsp.params[0] := mgcp_rsp_param;
812 return mgcp_rsp;
813 }
814
815 if (conn.resp == 0) {
816 /* Do not reply at all */
817 return omit;
818 }
819
820 if (conn.resp != 1) {
821 setverdict(fail, "Unexpected value for pars.mgw_conn_*.resp, expect -1, 0 or 1");
822 mtc.stop;
823 }
824
825 var SDP_Message sdp := valueof(ts_SDP(conn.mgw_rtp_ip, conn.mgw_rtp_ip,
826 hex2str(pars.mgcp_call_id), "42",
827 conn.mgw_rtp_port,
828 { int2str(pars.rtp_payload_type) },
829 { valueof(ts_SDP_rtpmap(pars.rtp_payload_type,
830 pars.rtp_sdp_format)),
831 valueof(ts_SDP_ptime(20)) }));
832
833 if (f_mgcp_contains_par(mgcp_msg, "X-OSMUX")) {
834 if (not pars.use_osmux) {
835 setverdict(fail, "MSC sent X-Osmux parameter in MGCP, but not expecting any Osmux");
836 mtc.stop;
837 }
838 pars.got_osmux_count := pars.got_osmux_count + 1;
839 /* we expect MSC to use wildcard here, i.e. osmux_cid == -1 */
840 osmux_cid := f_MgcpCmd_extract_osmux_cid(mgcp_cmd);
841 log("f_handle_crcx(): got Osmux CID: ", osmux_cid);
842 if (osmux_cid != -1) {
843 setverdict(fail, "MSC using unexpected CID " & int2str(osmux_cid) & " != -1");
844 mtc.stop;
845 }
846
847 osmux_cid := 0;
848 mgcp_resp := ts_CRCX_ACK_osmux(mgcp_cmd.line.trans_id, conn.mgcp_connection_id, osmux_cid, sdp);
849 } else {
850 mgcp_resp := ts_CRCX_ACK(mgcp_cmd.line.trans_id, conn.mgcp_connection_id, sdp);
851 }
852
853 f_mgcp_par_append(mgcp_resp.params, ts_MgcpParSpecEP(pars.mgcp_ep));
854
855 return mgcp_resp;
856}
857
Daniel Willmann3e15b7b2022-02-21 17:07:02 +0100858friend function f_create_rab(inout MgcpParameters pars) runs on ConnHdlr {
859 f_rab_ass_req(pars);
860 f_rab_ass_resp(pars);
861}
862
863friend function f_rab_ass_req(inout MgcpParameters pars) runs on ConnHdlr {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100864 var MgcpCommand mgcp_cmd;
865 var RANAP_PDU tx;
866 var template RAB_SetupOrModifyList rab_sml;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100867 timer T := 5.0;
868
869 /* Send RAB Assignment Request */
870 rab_sml := ts_RAB_SML(t_RAB_id(23), f_ts_RAB_TLA(pars.cn_rtp_ip), t_RAB_binding_port(pars.cn_rtp_port));
871 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
872 BSSAP.send(tx);
873 T.start;
874
875 /* Handle MGCP CRCX */
876 alt {
877 [] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
878 log("CRCX1", mgcp_cmd);
879 var template MgcpResponse mgcp_rsp := f_handle_crcx(pars, mgcp_cmd);
880 MGCP.send(valueof(mgcp_rsp));
881 }
882 [] T.timeout {
883 setverdict(fail, "Timeout waiting for MGCP");
884 }
885 }
886
887 /* Expect RAB Assignment Request with IP/port from CRCX ACK via Iuh */
888 rab_sml := ts_RAB_SML(t_RAB_id(23), f_ts_RAB_TLA(pars.mgw_conn_1.mgw_rtp_ip), t_RAB_binding_port(pars.mgw_conn_1.mgw_rtp_port));
889 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
890
891 alt {
892 [] RUA.receive(tx) {
893 setverdict(pass);
894 }
895 [] T.timeout {
896 setverdict(fail, "Timeout waiting for Iuh ", tx);
897 }
898 }
Daniel Willmann3e15b7b2022-02-21 17:07:02 +0100899}
900
901friend function f_rab_ass_resp(inout MgcpParameters pars) runs on ConnHdlr {
902 var MgcpCommand mgcp_cmd;
903 var RANAP_PDU tx;
904 var template RAB_SetupOrModifiedList rab_smdl;
905 timer T := 5.0;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100906
907 /* Send back RAB Assignment Response via Iuh */
908 rab_smdl := ts_RAB_SMdL(t_RAB_id(23), f_ts_RAB_TLA(pars.hnb_rtp_ip), t_RAB_binding_port(pars.hnb_rtp_port));
909 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
910 RUA.send(tx);
911 T.start;
912
913 interleave {
914 /* Expect MDCX with IP/port from RAB Assignment Response */
915 [] MGCP.receive(tr_MDCX(tr_SDP(pars.hnb_rtp_ip, pars.hnb_rtp_port))) -> value mgcp_cmd {
916 log("MDCX1", mgcp_cmd);
917 /* Verify SDP of MDCX */
918 var SDP_Message sdp := valueof(ts_SDP(pars.mgw_conn_1.mgw_rtp_ip, pars.mgw_conn_1.mgw_rtp_ip, hex2str(pars.mgcp_call_id), "42", pars.mgw_conn_1.mgw_rtp_port,
919 { int2str(pars.rtp_payload_type) }, { valueof(ts_SDP_rtpmap(pars.rtp_payload_type, pars.rtp_sdp_format)), valueof(ts_SDP_ptime(20)) } ));
920 var template MgcpResponse mgcp_rsp := ts_MDCX_ACK(mgcp_cmd.line.trans_id, pars.mgw_conn_1.mgcp_connection_id, sdp);
921 MGCP.send(valueof(mgcp_rsp));
922 }
923 /* Handle CRCX for second leg of endpoint, answer with IP/port */
924 [] MGCP.receive(tr_CRCX(pars.mgcp_ep, tr_SDP(pars.cn_rtp_ip, pars.cn_rtp_port))) -> value mgcp_cmd {
925 log("CRCX2", mgcp_cmd);
926 /* Verify SDP of CRCX */
927 var template MgcpResponse mgcp_rsp := f_handle_crcx(pars, mgcp_cmd);
928 MGCP.send(valueof(mgcp_rsp));
929 }
930 }
931
932 /* Expect RAB Assignment Response with IP/port from second CRCX ACK */
933 rab_smdl := ts_RAB_SMdL(t_RAB_id(23), f_ts_RAB_TLA(pars.mgw_conn_2.mgw_rtp_ip), t_RAB_binding_port(pars.mgw_conn_2.mgw_rtp_port));
934 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
935
936 alt {
937 [] BSSAP.receive(tx) {
938 setverdict(pass);
939 }
940 [] T.timeout {
941 setverdict(fail, "Timeout waiting for Iuh ", tx);
942 }
943 }
944}
945
946private altstep as_mgcp_dlcx(inout TestHdlrParams pars) runs on ConnHdlr {
947 var MgcpCommand mgcp_cmd;
948
949 [] MGCP.receive(tr_DLCX(pars.mgcp_pars.mgcp_ep)) -> value mgcp_cmd {
950 log("DLCX", mgcp_cmd);
951 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
952 pars.mgcp_pars.got_dlcx_count := pars.mgcp_pars.got_dlcx_count + 1;
Daniel Willmann3e15b7b2022-02-21 17:07:02 +0100953 if (pars.mgcp_pars.got_dlcx_count != pars.mgcp_pars.got_crcx_count) {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100954 repeat;
955 }
956 setverdict(pass);
957 }
958}
959
960friend function f_tc_rab_assignment(charstring id, TestHdlrParams pars) runs on ConnHdlr {
961 var MgcpCommand mgcp_cmd;
962 var RANAP_PDU tx;
963 timer T := 5.0;
964
965 f_init_handler(pars);
966 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
967
968 tx := f_build_initial_ue(g_pars);
969 f_iuh2iu_connect(tx);
970
971 f_create_rab(pars.mgcp_pars);
972
973 /* Send Iu Release */
974 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
975 f_iu2iuh(tx);
976
977 T.start;
978 alt {
979 [] as_mgcp_dlcx(pars) {}
980 [] T.timeout {
981 setverdict(fail, "Timeout waiting for DLCX");
982 }
983 }
984
985 tx := valueof(ts_RANAP_IuReleaseComplete());
986 f_iuh2iu(tx);
987}
988
989testcase TC_rab_assignment() runs on test_CT {
990 var ConnHdlr vc_conn;
991 f_init();
992 f_start_hnbs();
993
994 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assignment), t_pars(3));
995 vc_conn.done;
996}
997
Daniel Willmann3e15b7b2022-02-21 17:07:02 +0100998friend function f_tc_rab_assign_fail(charstring id, TestHdlrParams pars) runs on ConnHdlr {
999 var MgcpCommand mgcp_cmd;
1000 var RANAP_PDU tx;
1001 timer T := 5.0;
1002
1003 f_init_handler(pars);
1004 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1005
1006 tx := f_build_initial_ue(g_pars);
1007 f_iuh2iu_connect(tx);
1008
1009 f_rab_ass_req(pars.mgcp_pars);
1010
1011 /* Send RAB failed list in response */
1012 tx := valueof(ts_RANAP_RabAssResp(rab_fl := ts_RAB_FL(t_RAB_id(23), ts_RanapCause_om_intervention)));
1013 f_iuh2iu(tx);
1014
1015 T.start;
1016 alt {
1017 [] as_mgcp_dlcx(pars) {}
1018 [] T.timeout {
1019 setverdict(fail, "Timeout waiting for DLCX");
1020 }
1021 }
1022}
1023
1024testcase TC_rab_assign_fail() runs on test_CT {
1025 var ConnHdlr vc_conn;
1026 f_init();
1027 f_start_hnbs();
1028
1029 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assign_fail), t_pars(4));
1030 vc_conn.done;
1031}
1032
Daniel Willmann19b8d902022-01-05 09:12:34 +01001033friend function f_tc_rab_release(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1034 var MgcpCommand mgcp_cmd;
1035 var RANAP_PDU tx;
1036 timer T := 15.0;
1037
1038 f_init_handler(pars);
1039 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1040
1041 tx := f_build_initial_ue(g_pars);
1042 f_iuh2iu_connect(tx);
1043
1044 f_create_rab(pars.mgcp_pars);
1045
1046 /* Send RAB Release */
Daniel Willmann9e789be2022-02-22 13:30:51 +01001047 tx := valueof(ts_RANAP_RabAssReq(rab_rl := ts_RAB_RL(t_RAB_id(23), ts_RanapCause_om_intervention)));
Daniel Willmann19b8d902022-01-05 09:12:34 +01001048 BSSAP.send(tx);
1049
1050 T.start;
1051
1052 alt {
1053 [] as_mgcp_dlcx(pars) {}
1054 [] T.timeout {
1055 setverdict(fail, "Timeout waiting for DLCX");
1056 }
1057 }
1058
1059 alt {
1060 [] RUA.receive(tx) {
1061 setverdict(pass);
1062 }
1063 [] T.timeout {
1064 setverdict(fail, "Timeout waiting for Iuh ", tx);
1065 }
1066 }
1067
1068}
1069
1070testcase TC_rab_release() runs on test_CT {
1071 var ConnHdlr vc_conn;
1072 f_init();
1073 f_start_hnbs();
1074
1075 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_release), t_pars(5));
1076 vc_conn.done;
1077}
1078
Daniel Willmann37c877f2022-02-22 16:47:06 +01001079friend function f_tc_rab_assign_mgcp_to(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1080 var MgcpCommand mgcp_cmd;
1081 var RANAP_PDU tx;
1082 var template RAB_SetupOrModifyList rab_sml;
1083 timer T := 15.0;
1084
1085 T.start;
1086 f_init_handler(pars);
1087 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1088
1089 tx := f_build_initial_ue(g_pars);
1090 f_iuh2iu_connect(tx);
1091
1092
1093 /* Send RAB Assignment Request */
1094 rab_sml := ts_RAB_SML(t_RAB_id(23), f_ts_RAB_TLA(pars.mgcp_pars.cn_rtp_ip), t_RAB_binding_port(pars.mgcp_pars.cn_rtp_port));
1095 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1096 BSSAP.send(tx);
1097
1098 /* Ignore MGCP CRCX */
1099 alt {
1100 [] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
1101 log("Ignoreing CRCX1", mgcp_cmd);
1102 repeat;
1103 }
1104 [] BSSAP.receive(tr_RANAP_IuReleaseRequest(?)) { }
1105 [] T.timeout {
1106 setverdict(fail, "Timeout waiting for IuRelease");
1107 }
1108 }
1109
1110 /* Send Iu Release */
1111 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1112 f_iu2iuh(tx);
1113
1114 tx := valueof(ts_RANAP_IuReleaseComplete());
1115 f_iuh2iu(tx);
1116}
1117
1118testcase TC_rab_assign_mgcp_to() runs on test_CT {
1119 var ConnHdlr vc_conn;
1120 f_init();
1121 f_start_hnbs();
1122
1123 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assign_mgcp_to), t_pars(6));
1124 vc_conn.done;
1125}
1126
Daniel Willmann19b8d902022-01-05 09:12:34 +01001127/* Create an Iuh connection; send InitialUE; transceive data both directions */
1128friend function f_tc_ranap_bidir(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1129 f_init_handler(pars);
1130
1131 /* HNB -> MSC: InitialUE */
1132 f_iuh2iu_connect(f_build_initial_ue(g_pars));
1133
1134 /* MSC <- HNB: DirectTransfer */
1135 f_iu2iuh(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1136 /* MSC -> HNB: DirectTransfer */
1137 f_iuh2iu(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1138
1139 /* HNB <- MSC: CommonID */
1140 f_iu2iuh(ts_RANAP_CommonId(hex2oct(pars.imsi)));
1141}
1142testcase TC_ranap_cs_bidir() runs on test_CT {
1143 var ConnHdlr vc_conn;
1144
1145 f_init();
1146 f_start_hnbs();
1147
1148 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_bidir), t_pars(3));
1149 vc_conn.done;
1150}
1151testcase TC_ranap_ps_bidir() runs on test_CT {
1152 var ConnHdlr vc_conn;
1153
1154 f_init();
1155 f_start_hnbs();
1156
1157 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_bidir), t_pars(4, true));
1158 vc_conn.done;
1159}
1160
1161
1162private function f_tc_ranap_mo_disconnect(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1163 f_init_handler(pars);
1164
1165 /* HNB -> MSC: InitialUE */
1166 f_iuh2iu_connect(f_build_initial_ue(g_pars));
1167
1168 /* MSC <- HNB: DirectTransfer */
1169 f_iu2iuh(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1170 /* MSC -> HNB: DirectTransfer */
1171 f_iuh2iu(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1172
1173 /* MSC <- HNB: RUA disconnect */
1174 f_iuh2iu_disconnect(ts_RANAP_IuReleaseComplete, RUA_IEs.Cause:{misc:=processing_overload});
1175}
1176testcase TC_ranap_cs_mo_disconnect() runs on test_CT {
1177 var ConnHdlr vc_conn;
1178
1179 f_init();
1180 f_start_hnbs();
1181
1182 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_mo_disconnect), t_pars(5));
1183 vc_conn.done;
1184}
1185testcase TC_ranap_ps_mo_disconnect() runs on test_CT {
1186 var ConnHdlr vc_conn;
1187
1188 f_init();
1189 f_start_hnbs();
1190
1191 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_mo_disconnect), t_pars(6));
1192 vc_conn.done;
1193}
1194
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001195type record FTeid {
1196 HostName addr,
1197 OCT4 teid
1198}
1199
1200type record FTeids {
1201 FTeid local,
1202 FTeid remote
1203}
Daniel Willmann19b8d902022-01-05 09:12:34 +01001204
1205
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001206/* 'local' and 'remote' refer to the GTP information from the UPF's point of view:
1207 * HNB UPF CN
1208 * access.remote <---> access.local | core.local <---> core.remote
1209 */
1210type record GtpParameters {
1211 FTeids core,
1212 FTeids access
1213}
1214
1215/* HNB UPF CN
1216 * access.remote <---> access.local | core.local <---> core.remote
1217 * 127.0.0.4 127.0.0.3 127.0.0.2 127.0.0.1
1218 * 0x44004400 0x30303030 0x22002200 0x10101010
1219 */
1220template GtpParameters t_GtpParameters := {
1221 core := {
1222 local := {
1223 addr := "127.0.0.2",
1224 teid := '22002200'O
1225 },
1226 remote := {
1227 addr := "127.0.0.1",
1228 teid := '10101010'O
1229 }
1230 },
1231 access := {
1232 local := {
1233 addr := "127.0.0.3",
1234 teid := '30303030'O
1235 },
1236 remote := {
1237 addr := "127.0.0.4",
1238 teid := '44004400'O
1239 }
1240 }
1241}
1242
1243friend function f_tc_ps_rab_assignment(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1244 var RANAP_PDU tx;
1245 var RANAP_PDU rx;
1246 timer T := 5.0;
1247
1248 f_init_handler(pars);
1249
1250 f_pfcp_register();
1251
1252 var PDU_PFCP m;
1253 var Node_ID upf_node_id := valueof(ts_PFCP_Node_ID_fqdn("\07osmocom\03org"));
1254
1255 PFCP.receive(tr_PFCP_Assoc_Setup_Req()) -> value m;
1256 PFCP.send(ts_PFCP_Assoc_Setup_Resp(m.sequence_number, upf_node_id,
1257 ts_PFCP_Cause(REQUEST_ACCEPTED), 1234));
1258
1259 tx := f_build_initial_ue(g_pars);
1260 f_iuh2iu_connect(tx);
1261
1262 var GtpParameters gtp_pars := valueof(t_GtpParameters);
1263 var template RAB_SetupOrModifyList rab_sml;
1264
1265 /* Send RAB Assignment Request */
1266 rab_sml := ts_RAB_SML_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.core.remote.addr), gtp_pars.core.remote.teid);
1267 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1268 BSSAP.send(tx);
1269
1270 /* Expect PFCP Session Establishment Request. */
1271 PFCP.receive(tr_PFCP_Session_Est_Req()) -> value m;
1272 var F_SEID hnbgw_f_seid := m.message_body.pfcp_session_establishment_request.CP_F_SEID;
1273 var PFCP_Session_Establishment_Request serq := m.message_body.pfcp_session_establishment_request;
1274
1275 /* Acting as UPF, invent a new PFCP SEID to send to HNBGW. Respond to the Session Establishment.
1276 * The PFCP response must have the same sequence_number as the request. */
1277 var F_SEID up_f_seid := valueof(ts_PFCP_F_SEID_ipv4("127.0.0.1", '1111111111111111'O));
1278 var template PDU_PFCP r := ts_PFCP_Session_Est_Resp(m.sequence_number, upf_node_id, hnbgw_f_seid.seid);
1279 r.message_body.pfcp_session_establishment_response := {
1280 offending_ie := omit,
1281 UP_F_SEID := up_f_seid,
1282 created_PDR_list := {
1283 ts_PFCP_Created_PDR(pdr_id := serq.create_PDR_list[0].grouped_ie.pdr_id,
1284 local_F_TEID := ts_PFCP_F_TEID_ipv4(gtp_pars.core.local.teid,
1285 gtp_pars.core.local.addr)),
1286 ts_PFCP_Created_PDR(pdr_id := serq.create_PDR_list[1].grouped_ie.pdr_id,
1287 local_F_TEID := ts_PFCP_F_TEID_ipv4(gtp_pars.access.local.teid,
1288 gtp_pars.access.local.addr))
1289 },
1290 load_control_information := omit,
1291 overload_control_information := omit,
1292 node_list := omit,
1293 failed_rule_id := omit,
1294 created_traffic_endpoint_list := omit
1295 };
1296 PFCP.send(r);
1297
1298 /* Expect on Iuh: RAB Assignment Request with IP/port from PFCP Session Est Resp */
1299 rab_sml := ts_RAB_SML_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.access.local.addr),
1300 gtp_pars.access.local.teid);
1301 rx := valueof(ts_RANAP_RabAssReq(rab_sml));
1302 RUA.receive(rx);
1303
1304 /* Send back RAB Assignment Response via Iuh */
1305 var template RAB_SetupOrModifiedList rab_smdl;
1306 rab_smdl := ts_RAB_SMdL_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.access.remote.addr),
1307 gtp_pars.access.remote.teid);
1308 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
1309 RUA.send(tx);
1310 T.start;
1311
1312 PFCP.receive(tr_PFCP_Session_Mod_Req(up_f_seid.seid)) -> value m;
1313 r := ts_PFCP_Session_Mod_Resp(m.sequence_number, hnbgw_f_seid.seid);
1314 PFCP.send(r);
1315
1316 rab_smdl := ts_RAB_SMdL_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.core.local.addr), gtp_pars.core.local.teid);
1317 BSSAP.receive(tr_RANAP_RabAssResp(rab_smdl));
1318
1319 f_sleep(2.0);
1320 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1321 f_iu2iuh(tx);
1322
1323 tx := valueof(ts_RANAP_IuReleaseComplete());
1324 f_iuh2iu(tx);
1325
1326 PFCP.receive(tr_PFCP_Session_Del_Req(up_f_seid.seid)) -> value m;
1327 PFCP.send(ts_PFCP_Session_Del_Resp(m.sequence_number, hnbgw_f_seid.seid));
1328
1329 f_sleep(2.0);
1330}
1331
1332testcase TC_ps_rab_assignment() runs on test_CT {
1333 var ConnHdlr vc_conn;
1334 f_init();
1335 f_start_hnbs();
1336 f_sleep(1.0);
1337
1338 vc_conn := f_start_handler_with_pars(refers(f_tc_ps_rab_assignment), t_pars(7, ps_domain := true));
1339 vc_conn.done;
1340}
Daniel Willmann19b8d902022-01-05 09:12:34 +01001341
1342control {
1343 execute(TC_hnb_register());
Daniel Willmannc79679a2022-08-23 17:48:39 +02001344 execute(TC_hnb_register_duplicate());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001345 execute(TC_ranap_cs_initial_ue());
1346 execute(TC_ranap_ps_initial_ue());
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +02001347 execute(TC_ranap_cs_initial_ue_empty_cr());
1348 execute(TC_ranap_ps_initial_ue_empty_cr());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001349 execute(TC_ranap_cs_bidir());
1350 execute(TC_ranap_ps_bidir());
1351 execute(TC_rab_assignment());
1352 execute(TC_rab_release());
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001353 execute(TC_rab_assign_fail());
Daniel Willmann37c877f2022-02-22 16:47:06 +01001354 execute(TC_rab_assign_mgcp_to());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001355 execute(TC_ranap_cs_mo_disconnect());
1356 execute(TC_ranap_ps_mo_disconnect());
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001357 execute(TC_ps_rab_assignment());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001358}
1359
1360}