blob: b99ba58df0c1edea505d9f60a655b114e3080907 [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();
131 var template PDU_BSSAP ass_compl := f_gen_exp_compl();
132 ass_req.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
133 f_establish_fully(ass_req, ass_compl);
134
135 /* 2) notify master that assignment has completed */
136 MASTER.send(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
137
138 /* 3) proxy packets between master component and various ports */
139 while (true) {
140 as_lcls_conn_hdlr_proxy();
141 }
142}
143
144type function lcls_void_fn(charstring id) runs on LCLS_MSC_ConnHdlr;
145
146/* first function inside ConnHdlr component; sets g_pars + starts function */
147private function f_handler_init(lcls_void_fn fn, charstring id, template (omit) TestHdlrParams pars := omit)
148runs on LCLS_MSC_ConnHdlr {
149 if (isvalue(pars)) {
150 g_pars := valueof(pars);
151 }
152 fn.apply(id);
153}
154
Harald Welteff579f92018-05-31 22:19:39 +0200155/* helper function to create and connect a MSC_ConnHdlr component */
156/* FIXME: Why can't we use BSC_Tests.f_connect_andler() ?!? */
157private function f_connect_handler(inout LCLS_MSC_ConnHdlr vc_conn) runs on lcls_test_CT {
158 connect(vc_conn:BSSMAPEM, g_bssap.vc_BSSMAP:PROC);
159 connect(vc_conn:MGCP_PROC, vc_MGCP:MGCP_PROC);
160 connect(vc_conn:RSL, bts[0].rsl.vc_RSL:CLIENT_PT);
161 connect(vc_conn:RSL_PROC, bts[0].rsl.vc_RSL:RSL_PROC);
162 if (isvalue(bts[1])) {
163 connect(vc_conn:RSL1, bts[1].rsl.vc_RSL:CLIENT_PT);
164 connect(vc_conn:RSL1_PROC, bts[1].rsl.vc_RSL:RSL_PROC);
165 }
166 connect(vc_conn:BSSAP, g_bssap.vc_BSSMAP:CLIENT);
167 connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT);
168}
169
Harald Weltecc0b0142018-05-29 15:19:33 +0200170/* function creating the two ConnHdlrs, connecting them + starting them */
171private function f_lcls_test_init(TestHdlrParams pars_a, TestHdlrParams pars_b) runs on lcls_test_CT {
172 var charstring id_a := testcasename() & "-A";
173 var charstring id_b := testcasename() & "-B";
174
175 pars_b.imsi := '002029876543210'H;
176 pars_b.media_nr := 2;
177
178 /* create and connect the two ConnHandlers */
179 vc_CONN_A := LCLS_MSC_ConnHdlr.create(id_a);
180 f_connect_handler(vc_CONN_A);
181 connect(vc_CONN_A:MASTER, self:CONN_A);
182
183 vc_CONN_B := LCLS_MSC_ConnHdlr.create(id_b);
184 f_connect_handler(vc_CONN_B);
185 connect(vc_CONN_B:MASTER, self:CONN_B);
186
187 /* start the two components */
188 vc_CONN_A.start(f_handler_init(refers(f_lcls_connhdlr_main), id_a, pars_a));
189 f_sleep(3.0);
190 vc_CONN_B.start(f_handler_init(refers(f_lcls_connhdlr_main), id_b, pars_b));
191}
192
193private function f_lcls_test_fini() runs on lcls_test_CT {
194 vc_CONN_A.stop;
195 vc_CONN_B.stop;
196}
197
198/* ignore some messages which we're not interested in evaluating (yet) */
199private altstep as_ignore() runs on lcls_test_CT {
200 [] CONN_A.receive(tr_DLCX) { repeat; }
201 [] CONN_B.receive(tr_DLCX) { repeat; }
202}
203
204/* fail if any notify is being received */
205private altstep as_fail_on_lcls_notify() runs on lcls_test_CT
206{
207 [] CONN_A.receive(tr_BSSMAP_LclsNotification(?, *)) {
208 setverdict(fail, "Unexpected BSSMAP LCLS Notification");
209 }
210 [] CONN_B.receive(tr_BSSMAP_LclsNotification(?, *)) {
211 setverdict(fail, "Unexpected BSSMAP LCLS Notification");
212 }
213}
214
215private function f_wait_fail_notify() runs on lcls_test_CT
216{
217 timer T := 3.0;
218 T.start;
219 alt {
220 [] as_fail_on_lcls_notify();
221 [] T.timeout { }
222 }
223}
224
225private function f_lcls_init(integer nr_bts := 1) runs on lcls_test_CT
226{
227 var default d;
228
229 d := activate(as_ignore());
230 f_init(nr_bts, true);
231 f_sleep(1.0);
232}
233
234
235/* Send an ASSIGNMENT REQ with LCLS GCR only, without LCLS CFG or CSC */
236testcase TC_lcls_gcr_only() runs on lcls_test_CT {
237 var TestHdlrParams pars := valueof(t_def_TestHdlrPars);
238 var MSC_ConnHdlr vc_conn;
239
240 f_lcls_init();
241
242 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
243 pars.lcls.gcr := valueof(ts_GCR('010203'O, '0405'O, '060708090a'O));
244 /* Expect LCLS status to be not reported, as no LCLS config was signalled */
245 pars.lcls.exp_sts := omit;
246
247 f_lcls_test_init(pars, pars);
248 CONN_A.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
249 CONN_B.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
250 f_wait_fail_notify();
251 f_lcls_test_fini();
252}
253
254/* Send an ASSIGNMENT REQ with LCLS GCR+CFG+CSC; expect connect both-way */
255testcase TC_lcls_gcr_bway_connect() runs on lcls_test_CT {
256 var TestHdlrParams pars_a := valueof(t_def_TestHdlrPars);
257 var TestHdlrParams pars_b;
258 var MSC_ConnHdlr vc_conn;
259 var MgcpCommand mgcp_cmd;
260
261 f_lcls_init();
262
263 pars_a.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
264 pars_a.lcls.gcr := valueof(ts_GCR('010203'O, '0405'O, '060708090a'O));
265 pars_a.lcls.cfg := LCLS_CFG_both_way;
266 pars_a.lcls.csc := LCLS_CSC_connect;
267 pars_b := pars_a;
268
269 /* first call is not possible to be LS (no second leg yet) */
270 pars_a.lcls.exp_sts := LCLS_STS_not_possible_ls;
271 /* second call should then reuslt in LS */
272 pars_b.lcls.exp_sts := LCLS_STS_locally_switched;
273
274 f_lcls_test_init(pars_a, pars_b);
275 CONN_A.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
276 interleave {
277 [] CONN_A.receive(tr_BSSMAP_LclsNotificationSts(LCLS_STS_not_yet_ls));
278 [] CONN_A.receive(tr_BSSMAP_LclsNotificationSts(LCLS_STS_locally_switched));
279 [] CONN_B.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
280 [] CONN_A.receive(tr_MDCX) -> value mgcp_cmd {
281 CONN_A.send(f_build_mdcx_rsp(mgcp_cmd));
282 }
283 }
284
285 f_lcls_test_fini();
286}
287
288/* Send an ASSIGNMENT REQ with LCLS CFG+CSC enabling LCLS but GCR doesn't match! */
289testcase TC_lcls_gcr_nomatch_bway_connect() runs on lcls_test_CT {
290 var TestHdlrParams pars_a := valueof(t_def_TestHdlrPars);
291 var TestHdlrParams pars_b;
292 var MSC_ConnHdlr vc_conn;
293 var MgcpCommand mgcp_cmd;
294
295 f_lcls_init();
296
297 pars_a.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
298 pars_a.lcls.cfg := LCLS_CFG_both_way;
299 pars_a.lcls.csc := LCLS_CSC_connect;
300 pars_a.lcls.exp_sts := LCLS_STS_not_possible_ls;
301
302 pars_b := pars_a;
303
304 /* first call is not possible to be LS (no second leg yet) */
305 pars_a.lcls.gcr := valueof(ts_GCR('010203'O, '0405'O, '060708090a'O));
306 pars_b.lcls.gcr := valueof(ts_GCR('010203'O, '0405'O, '060708090b'O));
307
308 f_lcls_test_init(pars_a, pars_b);
309 CONN_A.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
310 CONN_B.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
311 f_wait_fail_notify();
312 f_lcls_test_fini();
313}
314
315
316/* Send an ASSIGNMENT REQ with LCLS GCR+CFG+CSC; expect no connect */
317testcase TC_lcls_gcr_bway_dont_connect() runs on lcls_test_CT {
318 var TestHdlrParams pars_a := valueof(t_def_TestHdlrPars);
319 var TestHdlrParams pars_b;
320 var MSC_ConnHdlr vc_conn;
321
322 f_lcls_init();
323
324 pars_a.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
325 pars_a.lcls.gcr := valueof(ts_GCR('010203'O, '0405'O, '060708090a'O));
326 pars_a.lcls.cfg := LCLS_CFG_both_way;
327 pars_a.lcls.csc := LCLS_CSC_do_not_connect;
328 pars_b := pars_a;
329
330 /* first call is not possible to be LS (no second leg yet) */
331 pars_a.lcls.exp_sts := LCLS_STS_not_possible_ls;
332 /* Expect LCLS is *NOT* established */
333 pars_b.lcls.exp_sts := LCLS_STS_not_yet_ls;
334
335 f_lcls_test_init(pars_a, pars_b);
336 CONN_A.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
337 CONN_B.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
338 CONN_A.receive(tr_BSSMAP_LclsNotificationSts(LCLS_STS_not_yet_ls));
339 f_wait_fail_notify();
340 f_lcls_test_fini();
341}
342
343/* Send an ASSIGNMENT REQ with LCLS GCR+CFG+CSC; expect no connect */
344testcase TC_lcls_gcr_unsuppported_cfg() runs on lcls_test_CT {
345 var TestHdlrParams pars := valueof(t_def_TestHdlrPars);
346 var MSC_ConnHdlr vc_conn;
347
348 f_lcls_init();
349
350 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
351 pars.lcls.gcr := valueof(ts_GCR('010203'O, '0405'O, '060708090a'O));
352 pars.lcls.cfg := LCLS_CFG_both_way_and_send_DL;
353 pars.lcls.csc := LCLS_CSC_connect;
354 /* Expect LCLS is *NOT* established with "LCLS_STS_req_lcls_not_supp" */
355 pars.lcls.exp_sts := LCLS_STS_req_lcls_not_supp;
356
357 f_lcls_test_init(pars, pars);
358 CONN_A.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
359 CONN_B.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
360 f_wait_fail_notify();
361 f_lcls_test_fini();
362}
363
364/* Send an ASSIGNMENT REQ with LCLS GCR+CFG+CSC; expect no connect */
365testcase TC_lcls_gcr_unsuppported_csc() runs on lcls_test_CT {
366 var TestHdlrParams pars_a := valueof(t_def_TestHdlrPars);
367 var TestHdlrParams pars_b;
368 var MSC_ConnHdlr vc_conn;
369
370 f_lcls_init();
371
372 pars_a.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
373 pars_a.lcls.gcr := valueof(ts_GCR('010203'O, '0405'O, '060708090a'O));
374 pars_a.lcls.cfg := LCLS_CFG_both_way;
375 pars_a.lcls.csc := LCLS_CSC_bicast_UL_and_recv_DL_at_handover;
376 pars_b := pars_a;
377
378 /* first call is not possible to be LS (no second leg yet) */
379 pars_a.lcls.exp_sts := LCLS_STS_not_possible_ls;
380 /* Expect LCLS is *NOT* established */
381 pars_b.lcls.exp_sts := LCLS_STS_not_yet_ls;
382
383 f_lcls_test_init(pars_a, pars_b);
384 CONN_A.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
385 CONN_B.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
386 CONN_A.receive(tr_BSSMAP_LclsNotificationSts(LCLS_STS_not_yet_ls));
387 f_lcls_test_fini();
388}
389
390/* Send an ASSIGNMENT REQ with "do not connect" and enable later using LCLS CTRL */
391testcase TC_lcls_gcr_bway_dont_connect_csc() runs on lcls_test_CT {
392 var TestHdlrParams pars_a := valueof(t_def_TestHdlrPars);
393 var TestHdlrParams pars_b;
394 var MSC_ConnHdlr vc_conn;
395 var MgcpCommand mgcp_cmd;
396
397 f_lcls_init();
398
399 pars_a.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
400 pars_a.lcls.gcr := valueof(ts_GCR('010203'O, '0405'O, '060708090a'O));
401 pars_a.lcls.cfg := LCLS_CFG_both_way;
402 pars_a.lcls.csc := LCLS_CSC_do_not_connect;
403 pars_b := pars_a;
404
405 /* first call is not possible to be LS (no second leg yet) */
406 pars_a.lcls.exp_sts := LCLS_STS_not_possible_ls;
407 /* Expect LCLS is *NOT* established */
408 pars_b.lcls.exp_sts := LCLS_STS_not_yet_ls;
409
410 /* start call and expect it to be "not yet" LS */
411 f_lcls_test_init(pars_a, pars_b);
412 CONN_A.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
413 CONN_B.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
414 CONN_A.receive(tr_BSSMAP_LclsNotificationSts(LCLS_STS_not_yet_ls));
415 f_sleep(2.0);
416
417 /* send "connect" on A side, expect call to remain in "not yet" */
418 CONN_A.send(ts_BSSMAP_LclsConnCtrl(omit, ts_BSSMAP_IE_LclsCsc(LCLS_CSC_connect)));
419 CONN_A.receive(tr_BSSMAP_LclsConnCtrlAck(tr_BSSMAP_IE_LclsSts(LCLS_STS_not_yet_ls)));
420 f_sleep(2.0);
421
422 /* send "connect" on B side, expect call to go LS, with notify to A side */
423 CONN_B.send(ts_BSSMAP_LclsConnCtrl(omit, ts_BSSMAP_IE_LclsCsc(LCLS_CSC_connect)));
424 interleave {
425 [] CONN_B.receive(tr_BSSMAP_LclsConnCtrlAck(tr_BSSMAP_IE_LclsSts(LCLS_STS_locally_switched)));
426 [] CONN_A.receive(tr_BSSMAP_LclsNotificationSts(LCLS_STS_locally_switched));
427 [] CONN_A.receive(tr_MDCX) -> value mgcp_cmd {
428 CONN_A.send(f_build_mdcx_rsp(mgcp_cmd));
429 }
430 [] CONN_B.receive(tr_MDCX) -> value mgcp_cmd {
431 CONN_B.send(f_build_mdcx_rsp(mgcp_cmd));
432 }
433 }
434 f_wait_fail_notify();
435 f_lcls_test_fini();
436}
437
438private function f_build_mdcx_rsp(MgcpCommand mdcx) return MgcpResponse
439{
440 var MgcpConnectionId conn_id := f_MgcpCmd_extract_conn_id(mdcx);
441 var SDP_Message sdp_in := mdcx.sdp;
442 var MgcpResponse resp;
443 var SDP_Message sdp_out;
444 var integer rtp_pt := str2int(sdp_in.media_list[0].media_field.fmts[0]);
445
446 sdp_out := valueof(ts_SDP(sdp_in.connection.conn_addr.addr, sdp_in.connection.conn_addr.addr,
447 "foo", "21", sdp_in.media_list[0].media_field.ports.port_number,
448 { int2str(rtp_pt) },
449 { valueof(ts_SDP_rtpmap(rtp_pt, "AMR/8000")),
450 valueof(ts_SDP_ptime(20)) } ));
451 return valueof(ts_MDCX_ACK(mdcx.line.trans_id, conn_id, sdp_out));
452}
453
454/* Establish LCLS "connect" followed by a MSC-initiated break */
455testcase TC_lcls_connect_break() runs on lcls_test_CT {
456 var TestHdlrParams pars_a := valueof(t_def_TestHdlrPars);
457 var TestHdlrParams pars_b;
458 var MSC_ConnHdlr vc_conn;
459 var MgcpCommand mgcp_cmd;
460
461 f_lcls_init();
462
463 pars_a.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
464 pars_a.lcls.gcr := valueof(ts_GCR('010203'O, '0405'O, '060708090a'O));
465 pars_a.lcls.cfg := LCLS_CFG_both_way;
466 pars_a.lcls.csc := LCLS_CSC_connect;
467 pars_b := pars_a;
468
469 /* first call is not possible to be LS (no second leg yet) */
470 pars_a.lcls.exp_sts := LCLS_STS_not_possible_ls;
471 /* second call should then reuslt in LS */
472 pars_b.lcls.exp_sts := LCLS_STS_locally_switched;
473
474 /* Expect LS to be established successfully */
475 f_lcls_test_init(pars_a, pars_b);
476 CONN_A.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
477 interleave {
478 [] CONN_A.receive(tr_BSSMAP_LclsNotificationSts(LCLS_STS_not_yet_ls));
479 [] CONN_A.receive(tr_BSSMAP_LclsNotificationSts(LCLS_STS_locally_switched));
480 [] CONN_B.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
481 [] CONN_A.receive(tr_MDCX) -> value mgcp_cmd {
482 CONN_A.send(f_build_mdcx_rsp(mgcp_cmd));
483 }
484/* not needed, as this MDCX is still handled within MSC_ConnectionHandler
485 [] CONN_B.receive(tr_MDCX) -> value mgcp_cmd {
486 CONN_B.send(f_build_mdcx_rsp(mgcp_cmd));
487 }
488*/
489 }
490
491 /* request LS release on "A" side; call continues to be locally switched */
492 CONN_A.send(ts_BSSMAP_LclsConnCtrl(omit, ts_BSSMAP_IE_LclsCsc(LCLS_CSC_release_lcls)));
493 CONN_A.receive(tr_BSSMAP_LclsConnCtrlAck(tr_BSSMAP_IE_LclsSts(LCLS_STS_locally_switched)));
494 f_sleep(2.0);
495
496 /* request LS release on "B" side; call LS is released */
497 CONN_B.send(ts_BSSMAP_LclsConnCtrl(omit, ts_BSSMAP_IE_LclsCsc(LCLS_CSC_release_lcls)));
498 interleave {
499 [] CONN_A.receive(tr_MDCX) -> value mgcp_cmd {
500 CONN_A.send(f_build_mdcx_rsp(mgcp_cmd));
501 }
502 [] CONN_B.receive(tr_MDCX) -> value mgcp_cmd {
503 CONN_B.send(f_build_mdcx_rsp(mgcp_cmd));
504 }
505 [] CONN_B.receive(tr_BSSMAP_LclsConnCtrlAck(tr_BSSMAP_IE_LclsSts(LCLS_STS_no_longer_ls)));
506 [] CONN_A.receive(tr_BSSMAP_LclsNotificationSts(LCLS_STS_no_longer_ls));
507 }
508
509 f_lcls_test_fini();
510}
511
512/* Establish LCLS "connect" followed by a SCCP-level release of one leg */
513testcase TC_lcls_connect_clear() runs on lcls_test_CT {
514 var TestHdlrParams pars_a := valueof(t_def_TestHdlrPars);
515 var TestHdlrParams pars_b;
516 var MSC_ConnHdlr vc_conn;
517 var MgcpCommand mgcp_cmd;
518 var RSL_Message rsl;
519
520 f_lcls_init();
521
522 pars_a.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
523 pars_a.lcls.gcr := valueof(ts_GCR('010203'O, '0405'O, '060708090a'O));
524 pars_a.lcls.cfg := LCLS_CFG_both_way;
525 pars_a.lcls.csc := LCLS_CSC_connect;
526 pars_b := pars_a;
527
528 /* first call is not possible to be LS (no second leg yet) */
529 pars_a.lcls.exp_sts := LCLS_STS_not_possible_ls;
530 /* second call should then reuslt in LS */
531 pars_b.lcls.exp_sts := LCLS_STS_locally_switched;
532
533 /* Expect LS to be established successfully */
534 f_lcls_test_init(pars_a, pars_b);
535 CONN_A.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
536 interleave {
537 [] CONN_A.receive(tr_BSSMAP_LclsNotificationSts(LCLS_STS_not_yet_ls));
538 [] CONN_A.receive(tr_BSSMAP_LclsNotificationSts(LCLS_STS_locally_switched));
539 [] CONN_B.receive(LclsCompSync:LCLS_COMP_SYNC_ASS_COMPL);
540 [] CONN_A.receive(tr_MDCX) -> value mgcp_cmd {
541 CONN_A.send(f_build_mdcx_rsp(mgcp_cmd));
542 }
543 }
544
545 /* Perform hard BSSMAP Clear on "A" side, expect no LS on "B" side */
546 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_CALL_CONTROL;
547 var octetstring l3_rr_chan_rel := '060D00'O;
548 CONN_A.send(ts_BSSMAP_ClearCommand(enum2int(cause_val)));
549 interleave {
550 [] CONN_A.receive(tr_RSL_DATA_REQ(?, tr_RslLinkID_DCCH(0), l3_rr_chan_rel));
551 [] CONN_A.receive(tr_RSL_DEACT_SACCH(?));
552 [] CONN_A.receive(tr_RSL_RF_CHAN_REL(?)) -> value rsl {
553 var RSL_IE_Body ieb;
554 f_rsl_find_ie(rsl, RSL_IE_CHAN_NR, ieb);
555 CONN_A.send(ts_RSL_RF_CHAN_REL_ACK(ieb.chan_nr));
556 }
Harald Welte935fbe32018-06-11 15:20:39 +0200557 [] CONN_A.receive(tr_BSSMAP_ClearComplete) {
558 CONN_A.send(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
559 }
Harald Weltecc0b0142018-05-29 15:19:33 +0200560 [] CONN_B.receive(tr_BSSMAP_LclsNotificationSts(LCLS_STS_not_possible_ls));
561 }
562 f_sleep(2.0);
563
564 f_lcls_test_fini();
565}
566
567
568
569
570/* TODO:
571 * verify IP/Port information in LCLS-triggered MDCX
572 * establish with one side connect, then enable using LCLS CTRL
573 * LCLS CTRL for call that doesn't have LCLS enabled
574 * LCLS IEs without GCR in ASS CMD
575 * GCR updates?
576 * Handover related LCLS bits (after we have inter-BSC HO in OsmoBSC)
577*/
578
579
580control {
581
582 execute( TC_lcls_gcr_only() );
583 execute( TC_lcls_gcr_bway_connect() );
584 execute( TC_lcls_gcr_nomatch_bway_connect() );
585 execute( TC_lcls_gcr_bway_dont_connect() );
586 execute( TC_lcls_gcr_unsuppported_cfg() );
587 execute( TC_lcls_gcr_unsuppported_csc() );
588 execute( TC_lcls_gcr_bway_dont_connect_csc() );
589 execute( TC_lcls_connect_break() );
590 execute( TC_lcls_connect_clear() );
591
592
593}
594
595
596}