blob: 585059e1b2a1077ecfc6bf34b671f9e22bd7b949 [file] [log] [blame]
Harald Weltecc0b0142018-05-29 15:19:33 +02001module BSC_Tests_LCLS {
2
3/* Integration Tests for OsmoBSC
4 * (C) 2018 by Harald Welte <laforge@gnumonks.org>
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 * This test suite tests OsmoBSC while emulating both multiple BTS + MS as
11 * well as the MSC. See README for more details.
12 *
13 * There are test cases that run in so-called 'handler mode' and test cases
14 * that run directly on top of the BSSAP and RSL CodecPorts. The "handler mode"
15 * tests abstract the multiplexing/demultiplexing of multiple SCCP connections
16 * and/or RSL channels and are hence suitable for higher-level test cases, while
17 * the "raw" tests directly on top of the CodecPorts are more suitable for lower-
18 * level testing.
19 */
20
21import from General_Types all;
22import from Osmocom_Types all;
23import from GSM_Types all;
24import from IPL4asp_Types all;
25
26import from BSSAP_Types all;
27import from BSSAP_Adapter all;
28import from BSSAP_CodecPort all;
29import from BSSMAP_Templates all;
30import from IPA_Emulation all;
31import from IPA_CodecPort all;
32import from IPA_Types all;
33import from RSL_Types all;
34import from RSL_Emulation all;
35import from MGCP_Types all;
36import from MGCP_Emulation all;
37import from MGCP_Templates all;
38import from SDP_Types all;
39
40import from Osmocom_CTRL_Functions all;
41import from Osmocom_CTRL_Types all;
42import from Osmocom_CTRL_Adapter all;
43
44import from Osmocom_VTY_Functions all;
45import from TELNETasp_PortType all;
46
47import from MobileL3_CommonIE_Types all;
48import from MobileL3_Types all;
49import from L3_Templates all;
50import from GSM_RR_Types all;
51
52import from BSSMAP_Templates all;
53import from BSSMAP_Emulation all;
54
55import from MSC_ConnectionHandler all;
56import from BSC_Tests all;
57
58/* The philosophy of this testsuite is to re-use as much as possible the existing components
59 * and functions that we have in BSC_Tests and its dependencies. However, as opposed to those
60 * normal BSC tests, we here have to run *two* ConnHdlr and synchronize activity between them.
61 *
62 * We do this by adding some special-purpose ports between the main test component running the
63 * test case [lcls_]test_CT and the per-connection [LCLS_]MSC_ConnHdlr.
64 */
65
66
67/* take test_CT from BSC_Tests and extend it with LCLS specific bits */
68type component lcls_test_CT extends test_CT {
69 /* Component references */
70 var LCLS_MSC_ConnHdlr vc_CONN_A;
71 var LCLS_MSC_ConnHdlr vc_CONN_B;
72 /* Ports to the two call legs */
73 port LCLS_InterComp_PT CONN_A;
74 port LCLS_InterComp_PT CONN_B;
75}
76
77/* take MSC_ConnHdlr and extend it with LCLS specific bits */
78type component LCLS_MSC_ConnHdlr extends MSC_ConnHdlr {
79 /* Port back to the controlling lcls_test_CT */
80 port LCLS_InterComp_PT MASTER;
81}
82
83/* port type between lcls_test_CT and LCLS_MSC_ConnHdlr */
84type port LCLS_InterComp_PT message {
85 /* BSSAP from BSSA_ConnHdlr */
86 inout PDU_BSSAP, BSSAP_Conn_Prim, PDU_DTAP_MO, PDU_DTAP_MT,
87 /* RSL from RSL_DchanHdlr */
88 RSLDC_ChanRqd, RSL_Message,
89 /* MGCP from MGCP_ConnHdlr */
90 MgcpCommand, MgcpResponse,
91 LclsCompSync;
92} with { extension "internal" };
93
94type enumerated LclsCompSync {
95 /* ConnHdlr signals to master component that assignment has completed */
96 LCLS_COMP_SYNC_ASS_COMPL
97}
98
99
100/* forward messages between the RSL/MGCP/BSSAP Emulation and the master component */
101private altstep as_lcls_conn_hdlr_proxy() runs on LCLS_MSC_ConnHdlr {
102 var PDU_BSSAP bssap;
103 var BSSAP_Conn_Prim bssap_p;
104 var PDU_DTAP_MO dtap_mo;
105 var PDU_DTAP_MT dtap_mt;
106 var MgcpCommand mgcp_cmd;
107 var MgcpResponse mgcp_rsp;
108 var RSL_Message rsl_msg;
109 /* from ConnHdlr to master process */
110 [] BSSAP.receive(PDU_BSSAP:?) -> value bssap { MASTER.send(bssap); }
111 [] BSSAP.receive(BSSAP_Conn_Prim:?) -> value bssap_p { MASTER.send(bssap_p); }
112 [] BSSAP.receive(PDU_DTAP_MO:?) -> value dtap_mo { MASTER.send(dtap_mo); }
113 [] BSSAP.receive(PDU_DTAP_MT:?) -> value dtap_mt { MASTER.send(dtap_mt); }
114 [] MGCP.receive(MgcpCommand:?) -> value mgcp_cmd { MASTER.send(mgcp_cmd); }
115 [] MGCP.receive(MgcpResponse:?) -> value mgcp_rsp { MASTER.send(mgcp_rsp); }
116 [] RSL.receive(RSL_Message:?) -> value rsl_msg { MASTER.send(rsl_msg); }
117 /* from master process to ConnHdlr */
118 [] MASTER.receive(PDU_BSSAP:?) -> value bssap { BSSAP.send(bssap); }
Harald Welte935fbe32018-06-11 15:20:39 +0200119 [] MASTER.receive(BSSAP_Conn_Prim:?) -> value bssap_p { BSSAP.send(bssap_p); }
Harald Weltecc0b0142018-05-29 15:19:33 +0200120 [] MASTER.receive(PDU_DTAP_MO:?) -> value dtap_mo { BSSAP.send(dtap_mo); }
121 [] MASTER.receive(PDU_DTAP_MT:?) -> value dtap_mt { BSSAP.send(dtap_mt); }
122 [] MASTER.receive(MgcpCommand:?) -> value mgcp_cmd { MGCP.send(mgcp_cmd); }
123 [] MASTER.receive(MgcpResponse:?) -> value mgcp_rsp { MGCP.send(mgcp_rsp); }
124 [] MASTER.receive(RSL_Message:?) -> value rsl_msg { RSL.send(rsl_msg); }
125}
126
127
128private function f_lcls_connhdlr_main(charstring id) runs on LCLS_MSC_ConnHdlr {
129 /* 1) establish the connection between RSL and BSSAP side */
130 var PDU_BSSAP ass_req := f_gen_ass_req();
Philipp Maier61f6b572018-07-06 14:03:38 +0200131
Harald Weltecc0b0142018-05-29 15:19:33 +0200132 var template PDU_BSSAP ass_compl := f_gen_exp_compl();
133 ass_req.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
Philipp Maier61f6b572018-07-06 14:03:38 +0200134 ass_req.pdu.bssmap.assignmentRequest.channelType :=
135 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
136
Harald Weltecc0b0142018-05-29 15:19:33 +0200137 f_establish_fully(ass_req, ass_compl);
138
139 /* 2) notify master that assignment has completed */
140 MASTER.send(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
141
142 /* 3) proxy packets between master component and various ports */
143 while (true) {
144 as_lcls_conn_hdlr_proxy();
145 }
146}
147
148type function lcls_void_fn(charstring id) runs on LCLS_MSC_ConnHdlr;
149
150/* first function inside ConnHdlr component; sets g_pars + starts function */
151private function f_handler_init(lcls_void_fn fn, charstring id, template (omit) TestHdlrParams pars := omit)
152runs on LCLS_MSC_ConnHdlr {
153 if (isvalue(pars)) {
154 g_pars := valueof(pars);
155 }
156 fn.apply(id);
157}
158
Harald Welteff579f92018-05-31 22:19:39 +0200159/* helper function to create and connect a MSC_ConnHdlr component */
160/* FIXME: Why can't we use BSC_Tests.f_connect_andler() ?!? */
161private function f_connect_handler(inout LCLS_MSC_ConnHdlr vc_conn) runs on lcls_test_CT {
162 connect(vc_conn:BSSMAPEM, g_bssap.vc_BSSMAP:PROC);
163 connect(vc_conn:MGCP_PROC, vc_MGCP:MGCP_PROC);
164 connect(vc_conn:RSL, bts[0].rsl.vc_RSL:CLIENT_PT);
165 connect(vc_conn:RSL_PROC, bts[0].rsl.vc_RSL:RSL_PROC);
166 if (isvalue(bts[1])) {
167 connect(vc_conn:RSL1, bts[1].rsl.vc_RSL:CLIENT_PT);
168 connect(vc_conn:RSL1_PROC, bts[1].rsl.vc_RSL:RSL_PROC);
169 }
170 connect(vc_conn:BSSAP, g_bssap.vc_BSSMAP:CLIENT);
171 connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT);
172}
173
Harald Weltecc0b0142018-05-29 15:19:33 +0200174/* function creating the two ConnHdlrs, connecting them + starting them */
175private function f_lcls_test_init(TestHdlrParams pars_a, TestHdlrParams pars_b) runs on lcls_test_CT {
176 var charstring id_a := testcasename() & "-A";
177 var charstring id_b := testcasename() & "-B";
178
179 pars_b.imsi := '002029876543210'H;
180 pars_b.media_nr := 2;
181
182 /* create and connect the two ConnHandlers */
183 vc_CONN_A := LCLS_MSC_ConnHdlr.create(id_a);
184 f_connect_handler(vc_CONN_A);
185 connect(vc_CONN_A:MASTER, self:CONN_A);
186
187 vc_CONN_B := LCLS_MSC_ConnHdlr.create(id_b);
188 f_connect_handler(vc_CONN_B);
189 connect(vc_CONN_B:MASTER, self:CONN_B);
190
191 /* start the two components */
192 vc_CONN_A.start(f_handler_init(refers(f_lcls_connhdlr_main), id_a, pars_a));
193 f_sleep(3.0);
194 vc_CONN_B.start(f_handler_init(refers(f_lcls_connhdlr_main), id_b, pars_b));
195}
196
197private function f_lcls_test_fini() runs on lcls_test_CT {
198 vc_CONN_A.stop;
199 vc_CONN_B.stop;
200}
201
202/* ignore some messages which we're not interested in evaluating (yet) */
203private altstep as_ignore() runs on lcls_test_CT {
204 [] CONN_A.receive(tr_DLCX) { repeat; }
205 [] CONN_B.receive(tr_DLCX) { repeat; }
206}
207
208/* fail if any notify is being received */
209private altstep as_fail_on_lcls_notify() runs on lcls_test_CT
210{
211 [] CONN_A.receive(tr_BSSMAP_LclsNotification(?, *)) {
212 setverdict(fail, "Unexpected BSSMAP LCLS Notification");
213 }
214 [] CONN_B.receive(tr_BSSMAP_LclsNotification(?, *)) {
215 setverdict(fail, "Unexpected BSSMAP LCLS Notification");
216 }
217}
218
219private function f_wait_fail_notify() runs on lcls_test_CT
220{
221 timer T := 3.0;
222 T.start;
223 alt {
224 [] as_fail_on_lcls_notify();
225 [] T.timeout { }
226 }
227}
228
229private function f_lcls_init(integer nr_bts := 1) runs on lcls_test_CT
230{
231 var default d;
232
233 d := activate(as_ignore());
234 f_init(nr_bts, true);
235 f_sleep(1.0);
236}
237
238
239/* Send an ASSIGNMENT REQ with LCLS GCR only, without LCLS CFG or CSC */
240testcase TC_lcls_gcr_only() runs on lcls_test_CT {
241 var TestHdlrParams pars := valueof(t_def_TestHdlrPars);
242 var MSC_ConnHdlr vc_conn;
243
244 f_lcls_init();
245
246 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
247 pars.lcls.gcr := valueof(ts_GCR('010203'O, '0405'O, '060708090a'O));
248 /* Expect LCLS status to be not reported, as no LCLS config was signalled */
249 pars.lcls.exp_sts := omit;
250
251 f_lcls_test_init(pars, pars);
252 CONN_A.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
253 CONN_B.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
254 f_wait_fail_notify();
255 f_lcls_test_fini();
256}
257
Maxb1599b12018-10-31 19:38:38 +0100258private function f_tc_lcls_recv_ls_exp_mgcp() runs on lcls_test_CT {
259 var MgcpCommand mgcp_cmd;
260
261 interleave {
262 [] CONN_A.receive(tr_BSSMAP_LclsNotificationSts(LCLS_STS_not_yet_ls));
263 [] CONN_A.receive(tr_BSSMAP_LclsNotificationSts(LCLS_STS_locally_switched));
264 [] CONN_B.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
265 [] CONN_A.receive(tr_MDCX) -> value mgcp_cmd {
266 CONN_A.send(f_build_mdcx_rsp(mgcp_cmd));
267 }
268 /* not needed, as this MDCX is still handled within MSC_ConnectionHandler
269 [] CONN_B.receive(tr_MDCX) -> value mgcp_cmd {
270 CONN_B.send(f_build_mdcx_rsp(mgcp_cmd));
271 }
272 */
273 }
274}
275
Philipp Maier61f6b572018-07-06 14:03:38 +0200276private function f_tc_lcls_gcr_bway_connect(boolean hr) runs on lcls_test_CT {
Harald Weltecc0b0142018-05-29 15:19:33 +0200277 var TestHdlrParams pars_a := valueof(t_def_TestHdlrPars);
278 var TestHdlrParams pars_b;
279 var MSC_ConnHdlr vc_conn;
Harald Weltecc0b0142018-05-29 15:19:33 +0200280
281 f_lcls_init();
282
Philipp Maier61f6b572018-07-06 14:03:38 +0200283 if (hr == true) {
284 pars_a.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
285 } else {
286 pars_a.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
287 }
Harald Weltecc0b0142018-05-29 15:19:33 +0200288 pars_a.lcls.gcr := valueof(ts_GCR('010203'O, '0405'O, '060708090a'O));
289 pars_a.lcls.cfg := LCLS_CFG_both_way;
290 pars_a.lcls.csc := LCLS_CSC_connect;
291 pars_b := pars_a;
292
293 /* first call is not possible to be LS (no second leg yet) */
294 pars_a.lcls.exp_sts := LCLS_STS_not_possible_ls;
295 /* second call should then reuslt in LS */
296 pars_b.lcls.exp_sts := LCLS_STS_locally_switched;
297
298 f_lcls_test_init(pars_a, pars_b);
Philipp Maier61f6b572018-07-06 14:03:38 +0200299
Harald Weltecc0b0142018-05-29 15:19:33 +0200300 CONN_A.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
Maxb1599b12018-10-31 19:38:38 +0100301
302 f_tc_lcls_recv_ls_exp_mgcp();
Harald Weltecc0b0142018-05-29 15:19:33 +0200303
304 f_lcls_test_fini();
305}
306
Philipp Maier61f6b572018-07-06 14:03:38 +0200307/* Send an ASSIGNMENT REQ with LCLS GCR+CFG+CSC; expect connect both-way (full rate)*/
308testcase TC_lcls_gcr_bway_connect() runs on lcls_test_CT {
309 f_tc_lcls_gcr_bway_connect(false)
310}
311
312/* Send an ASSIGNMENT REQ with LCLS GCR+CFG+CSC; expect connect both-way (half rate) */
313testcase TC_lcls_gcr_bway_connect_hr() runs on lcls_test_CT {
314 f_tc_lcls_gcr_bway_connect(true)
315}
316
Philipp Maier55f27f52018-07-10 09:15:09 +0200317/* Unless explicitly enabled, osmo-bsc will avoid LCLSs when the codecs or rates
318 * of both legs are different */
319testcase TC_lcls_gcr_bway_codec_mismatch() runs on lcls_test_CT {
320 var TestHdlrParams pars_a := valueof(t_def_TestHdlrPars);
321 var TestHdlrParams pars_b;
322 var MSC_ConnHdlr vc_conn;
323 var MgcpCommand mgcp_cmd;
324
325 f_lcls_init();
326
327 /* First call leg uses full rate */
328 pars_a.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
329 pars_a.lcls.gcr := valueof(ts_GCR('010203'O, '0405'O, '060708090a'O));
330 pars_a.lcls.cfg := LCLS_CFG_both_way;
331 pars_a.lcls.csc := LCLS_CSC_connect;
332
333 /* The second call leg uses half-rate */
334 pars_b := pars_a;
335 pars_a.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
336
337 /* first call is not possible to be LS (no second leg yet) */
338 pars_a.lcls.exp_sts := LCLS_STS_not_possible_ls;
339
340 /* second call is also not possible to be LS (codec/rate does not match) */
341 pars_b.lcls.exp_sts := LCLS_STS_not_yet_ls;
342 f_lcls_test_init(pars_a, pars_b);
343
344 interleave {
345 [] CONN_A.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
346 [] CONN_B.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
347 [] CONN_A.receive(tr_BSSMAP_LclsNotificationSts(LCLS_STS_not_yet_ls));
348 }
349
350 f_lcls_test_fini();
351}
352
Harald Weltecc0b0142018-05-29 15:19:33 +0200353/* Send an ASSIGNMENT REQ with LCLS CFG+CSC enabling LCLS but GCR doesn't match! */
354testcase TC_lcls_gcr_nomatch_bway_connect() runs on lcls_test_CT {
355 var TestHdlrParams pars_a := valueof(t_def_TestHdlrPars);
356 var TestHdlrParams pars_b;
357 var MSC_ConnHdlr vc_conn;
358 var MgcpCommand mgcp_cmd;
359
360 f_lcls_init();
361
362 pars_a.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
363 pars_a.lcls.cfg := LCLS_CFG_both_way;
364 pars_a.lcls.csc := LCLS_CSC_connect;
365 pars_a.lcls.exp_sts := LCLS_STS_not_possible_ls;
366
367 pars_b := pars_a;
368
369 /* first call is not possible to be LS (no second leg yet) */
370 pars_a.lcls.gcr := valueof(ts_GCR('010203'O, '0405'O, '060708090a'O));
371 pars_b.lcls.gcr := valueof(ts_GCR('010203'O, '0405'O, '060708090b'O));
372
373 f_lcls_test_init(pars_a, pars_b);
374 CONN_A.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
375 CONN_B.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
376 f_wait_fail_notify();
377 f_lcls_test_fini();
378}
379
Maxb1599b12018-10-31 19:38:38 +0100380/* check for the cases where LCLS is not possible due to some reason */
381private function f_lcls_not_yet_ls() runs on lcls_test_CT {
382 CONN_A.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
383 CONN_B.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
384 CONN_A.receive(tr_BSSMAP_LclsNotificationSts(LCLS_STS_not_yet_ls));
385}
Harald Weltecc0b0142018-05-29 15:19:33 +0200386
387/* Send an ASSIGNMENT REQ with LCLS GCR+CFG+CSC; expect no connect */
388testcase TC_lcls_gcr_bway_dont_connect() runs on lcls_test_CT {
389 var TestHdlrParams pars_a := valueof(t_def_TestHdlrPars);
390 var TestHdlrParams pars_b;
391 var MSC_ConnHdlr vc_conn;
392
393 f_lcls_init();
394
395 pars_a.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
396 pars_a.lcls.gcr := valueof(ts_GCR('010203'O, '0405'O, '060708090a'O));
397 pars_a.lcls.cfg := LCLS_CFG_both_way;
398 pars_a.lcls.csc := LCLS_CSC_do_not_connect;
399 pars_b := pars_a;
400
401 /* first call is not possible to be LS (no second leg yet) */
402 pars_a.lcls.exp_sts := LCLS_STS_not_possible_ls;
403 /* Expect LCLS is *NOT* established */
404 pars_b.lcls.exp_sts := LCLS_STS_not_yet_ls;
405
406 f_lcls_test_init(pars_a, pars_b);
Maxb1599b12018-10-31 19:38:38 +0100407 f_lcls_not_yet_ls();
Harald Weltecc0b0142018-05-29 15:19:33 +0200408 f_wait_fail_notify();
409 f_lcls_test_fini();
410}
411
412/* Send an ASSIGNMENT REQ with LCLS GCR+CFG+CSC; expect no connect */
413testcase TC_lcls_gcr_unsuppported_cfg() runs on lcls_test_CT {
414 var TestHdlrParams pars := valueof(t_def_TestHdlrPars);
415 var MSC_ConnHdlr vc_conn;
416
417 f_lcls_init();
418
419 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
420 pars.lcls.gcr := valueof(ts_GCR('010203'O, '0405'O, '060708090a'O));
421 pars.lcls.cfg := LCLS_CFG_both_way_and_send_DL;
422 pars.lcls.csc := LCLS_CSC_connect;
423 /* Expect LCLS is *NOT* established with "LCLS_STS_req_lcls_not_supp" */
424 pars.lcls.exp_sts := LCLS_STS_req_lcls_not_supp;
425
426 f_lcls_test_init(pars, pars);
427 CONN_A.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
428 CONN_B.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
429 f_wait_fail_notify();
430 f_lcls_test_fini();
431}
432
433/* Send an ASSIGNMENT REQ with LCLS GCR+CFG+CSC; expect no connect */
434testcase TC_lcls_gcr_unsuppported_csc() runs on lcls_test_CT {
435 var TestHdlrParams pars_a := valueof(t_def_TestHdlrPars);
436 var TestHdlrParams pars_b;
437 var MSC_ConnHdlr vc_conn;
438
439 f_lcls_init();
440
441 pars_a.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
442 pars_a.lcls.gcr := valueof(ts_GCR('010203'O, '0405'O, '060708090a'O));
443 pars_a.lcls.cfg := LCLS_CFG_both_way;
444 pars_a.lcls.csc := LCLS_CSC_bicast_UL_and_recv_DL_at_handover;
445 pars_b := pars_a;
446
447 /* first call is not possible to be LS (no second leg yet) */
448 pars_a.lcls.exp_sts := LCLS_STS_not_possible_ls;
449 /* Expect LCLS is *NOT* established */
450 pars_b.lcls.exp_sts := LCLS_STS_not_yet_ls;
451
452 f_lcls_test_init(pars_a, pars_b);
Maxb1599b12018-10-31 19:38:38 +0100453 f_lcls_not_yet_ls();
Harald Weltecc0b0142018-05-29 15:19:33 +0200454 f_lcls_test_fini();
455}
456
Maxb1599b12018-10-31 19:38:38 +0100457/* Expect given LCLS status alongside with corresponding MDCX commands */
458private function f_lcls_sts_mgcp(BIT4 expected_status) runs on lcls_test_CT {
459 var MgcpCommand mgcp_cmd;
460
461 interleave {
462 [] CONN_B.receive(tr_BSSMAP_LclsConnCtrlAck(tr_BSSMAP_IE_LclsSts(expected_status)));
463 [] CONN_A.receive(tr_BSSMAP_LclsNotificationSts(expected_status));
464 [] CONN_A.receive(tr_MDCX) -> value mgcp_cmd {
465 CONN_A.send(f_build_mdcx_rsp(mgcp_cmd));
466 }
467 [] CONN_B.receive(tr_MDCX) -> value mgcp_cmd {
468 CONN_B.send(f_build_mdcx_rsp(mgcp_cmd));
469 }
470 }
471}
472
Harald Weltecc0b0142018-05-29 15:19:33 +0200473/* Send an ASSIGNMENT REQ with "do not connect" and enable later using LCLS CTRL */
474testcase TC_lcls_gcr_bway_dont_connect_csc() runs on lcls_test_CT {
475 var TestHdlrParams pars_a := valueof(t_def_TestHdlrPars);
476 var TestHdlrParams pars_b;
477 var MSC_ConnHdlr vc_conn;
478 var MgcpCommand mgcp_cmd;
479
480 f_lcls_init();
481
482 pars_a.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
483 pars_a.lcls.gcr := valueof(ts_GCR('010203'O, '0405'O, '060708090a'O));
484 pars_a.lcls.cfg := LCLS_CFG_both_way;
485 pars_a.lcls.csc := LCLS_CSC_do_not_connect;
486 pars_b := pars_a;
487
488 /* first call is not possible to be LS (no second leg yet) */
489 pars_a.lcls.exp_sts := LCLS_STS_not_possible_ls;
490 /* Expect LCLS is *NOT* established */
491 pars_b.lcls.exp_sts := LCLS_STS_not_yet_ls;
492
493 /* start call and expect it to be "not yet" LS */
494 f_lcls_test_init(pars_a, pars_b);
Maxb1599b12018-10-31 19:38:38 +0100495 f_lcls_not_yet_ls();
Harald Weltecc0b0142018-05-29 15:19:33 +0200496 f_sleep(2.0);
497
498 /* send "connect" on A side, expect call to remain in "not yet" */
499 CONN_A.send(ts_BSSMAP_LclsConnCtrl(omit, ts_BSSMAP_IE_LclsCsc(LCLS_CSC_connect)));
500 CONN_A.receive(tr_BSSMAP_LclsConnCtrlAck(tr_BSSMAP_IE_LclsSts(LCLS_STS_not_yet_ls)));
501 f_sleep(2.0);
502
503 /* send "connect" on B side, expect call to go LS, with notify to A side */
504 CONN_B.send(ts_BSSMAP_LclsConnCtrl(omit, ts_BSSMAP_IE_LclsCsc(LCLS_CSC_connect)));
Maxb1599b12018-10-31 19:38:38 +0100505 f_lcls_sts_mgcp(LCLS_STS_locally_switched);
Harald Weltecc0b0142018-05-29 15:19:33 +0200506 f_wait_fail_notify();
507 f_lcls_test_fini();
508}
509
510private function f_build_mdcx_rsp(MgcpCommand mdcx) return MgcpResponse
511{
512 var MgcpConnectionId conn_id := f_MgcpCmd_extract_conn_id(mdcx);
513 var SDP_Message sdp_in := mdcx.sdp;
514 var MgcpResponse resp;
515 var SDP_Message sdp_out;
516 var integer rtp_pt := str2int(sdp_in.media_list[0].media_field.fmts[0]);
517
518 sdp_out := valueof(ts_SDP(sdp_in.connection.conn_addr.addr, sdp_in.connection.conn_addr.addr,
519 "foo", "21", sdp_in.media_list[0].media_field.ports.port_number,
520 { int2str(rtp_pt) },
521 { valueof(ts_SDP_rtpmap(rtp_pt, "AMR/8000")),
522 valueof(ts_SDP_ptime(20)) } ));
523 return valueof(ts_MDCX_ACK(mdcx.line.trans_id, conn_id, sdp_out));
524}
525
526/* Establish LCLS "connect" followed by a MSC-initiated break */
527testcase TC_lcls_connect_break() runs on lcls_test_CT {
528 var TestHdlrParams pars_a := valueof(t_def_TestHdlrPars);
529 var TestHdlrParams pars_b;
530 var MSC_ConnHdlr vc_conn;
Harald Weltecc0b0142018-05-29 15:19:33 +0200531
532 f_lcls_init();
533
534 pars_a.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
535 pars_a.lcls.gcr := valueof(ts_GCR('010203'O, '0405'O, '060708090a'O));
536 pars_a.lcls.cfg := LCLS_CFG_both_way;
537 pars_a.lcls.csc := LCLS_CSC_connect;
538 pars_b := pars_a;
539
540 /* first call is not possible to be LS (no second leg yet) */
541 pars_a.lcls.exp_sts := LCLS_STS_not_possible_ls;
Maxd4e56962018-10-31 19:08:25 +0100542 /* second call should then result in LS */
Harald Weltecc0b0142018-05-29 15:19:33 +0200543 pars_b.lcls.exp_sts := LCLS_STS_locally_switched;
544
545 /* Expect LS to be established successfully */
546 f_lcls_test_init(pars_a, pars_b);
547 CONN_A.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
Maxb1599b12018-10-31 19:38:38 +0100548
549 f_tc_lcls_recv_ls_exp_mgcp()
Harald Weltecc0b0142018-05-29 15:19:33 +0200550
551 /* request LS release on "A" side; call continues to be locally switched */
552 CONN_A.send(ts_BSSMAP_LclsConnCtrl(omit, ts_BSSMAP_IE_LclsCsc(LCLS_CSC_release_lcls)));
553 CONN_A.receive(tr_BSSMAP_LclsConnCtrlAck(tr_BSSMAP_IE_LclsSts(LCLS_STS_locally_switched)));
554 f_sleep(2.0);
555
556 /* request LS release on "B" side; call LS is released */
557 CONN_B.send(ts_BSSMAP_LclsConnCtrl(omit, ts_BSSMAP_IE_LclsCsc(LCLS_CSC_release_lcls)));
Maxb1599b12018-10-31 19:38:38 +0100558
559 f_lcls_sts_mgcp(LCLS_STS_no_longer_ls)
Harald Weltecc0b0142018-05-29 15:19:33 +0200560
561 f_lcls_test_fini();
562}
563
564/* Establish LCLS "connect" followed by a SCCP-level release of one leg */
565testcase TC_lcls_connect_clear() runs on lcls_test_CT {
566 var TestHdlrParams pars_a := valueof(t_def_TestHdlrPars);
567 var TestHdlrParams pars_b;
568 var MSC_ConnHdlr vc_conn;
569 var MgcpCommand mgcp_cmd;
570 var RSL_Message rsl;
571
572 f_lcls_init();
573
574 pars_a.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
575 pars_a.lcls.gcr := valueof(ts_GCR('010203'O, '0405'O, '060708090a'O));
576 pars_a.lcls.cfg := LCLS_CFG_both_way;
577 pars_a.lcls.csc := LCLS_CSC_connect;
578 pars_b := pars_a;
579
580 /* first call is not possible to be LS (no second leg yet) */
581 pars_a.lcls.exp_sts := LCLS_STS_not_possible_ls;
582 /* second call should then reuslt in LS */
583 pars_b.lcls.exp_sts := LCLS_STS_locally_switched;
584
585 /* Expect LS to be established successfully */
586 f_lcls_test_init(pars_a, pars_b);
587 CONN_A.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
Maxb1599b12018-10-31 19:38:38 +0100588
589 f_tc_lcls_recv_ls_exp_mgcp();
Harald Weltecc0b0142018-05-29 15:19:33 +0200590
591 /* Perform hard BSSMAP Clear on "A" side, expect no LS on "B" side */
592 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_CALL_CONTROL;
593 var octetstring l3_rr_chan_rel := '060D00'O;
594 CONN_A.send(ts_BSSMAP_ClearCommand(enum2int(cause_val)));
595 interleave {
596 [] CONN_A.receive(tr_RSL_DATA_REQ(?, tr_RslLinkID_DCCH(0), l3_rr_chan_rel));
597 [] CONN_A.receive(tr_RSL_DEACT_SACCH(?));
598 [] CONN_A.receive(tr_RSL_RF_CHAN_REL(?)) -> value rsl {
599 var RSL_IE_Body ieb;
Maxfc337ca2018-10-31 19:42:08 +0100600 if (f_rsl_find_ie(rsl, RSL_IE_CHAN_NR, ieb) == true) {
601 CONN_A.send(ts_RSL_RF_CHAN_REL_ACK(ieb.chan_nr));
602 } else {
603 log("Unable to find chan# in RSL_RF_CHAN_REL")
604 }
Harald Weltecc0b0142018-05-29 15:19:33 +0200605 }
Harald Welte935fbe32018-06-11 15:20:39 +0200606 [] CONN_A.receive(tr_BSSMAP_ClearComplete) {
607 CONN_A.send(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
608 }
Harald Weltecc0b0142018-05-29 15:19:33 +0200609 [] CONN_B.receive(tr_BSSMAP_LclsNotificationSts(LCLS_STS_not_possible_ls));
610 }
611 f_sleep(2.0);
612
613 f_lcls_test_fini();
614}
615
616
617
618
619/* TODO:
620 * verify IP/Port information in LCLS-triggered MDCX
621 * establish with one side connect, then enable using LCLS CTRL
622 * LCLS CTRL for call that doesn't have LCLS enabled
623 * LCLS IEs without GCR in ASS CMD
624 * GCR updates?
625 * Handover related LCLS bits (after we have inter-BSC HO in OsmoBSC)
626*/
627
628
629control {
630
631 execute( TC_lcls_gcr_only() );
632 execute( TC_lcls_gcr_bway_connect() );
Philipp Maier61f6b572018-07-06 14:03:38 +0200633 execute( TC_lcls_gcr_bway_connect_hr() );
Philipp Maier55f27f52018-07-10 09:15:09 +0200634 execute( TC_lcls_gcr_bway_codec_mismatch() );
Harald Weltecc0b0142018-05-29 15:19:33 +0200635 execute( TC_lcls_gcr_nomatch_bway_connect() );
636 execute( TC_lcls_gcr_bway_dont_connect() );
637 execute( TC_lcls_gcr_unsuppported_cfg() );
638 execute( TC_lcls_gcr_unsuppported_csc() );
639 execute( TC_lcls_gcr_bway_dont_connect_csc() );
640 execute( TC_lcls_connect_break() );
641 execute( TC_lcls_connect_clear() );
642
643
644}
645
646
647}