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