blob: 1dc491064a0b031279d73bd2d441d071af3ce3de [file] [log] [blame]
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +02001module BSC_Tests_VAMOS {
2
3/* Integration Tests for OsmoBSC
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 OsmoBSC while emulating both multiple BTS + MS as
13 * well as the MSC. See README for more details.
14 *
15 * There are test cases that run in so-called 'handler mode' and test cases
16 * that run directly on top of the BSSAP and RSL CodecPorts. The "handler mode"
17 * tests abstract the multiplexing/demultiplexing of multiple SCCP connections
18 * and/or RSL channels and are hence suitable for higher-level test cases, while
19 * the "raw" tests directly on top of the CodecPorts are more suitable for lower-
20 * level testing.
21 */
22
23import from BSC_Tests all;
24
25import from Misc_Helpers all;
26import from General_Types all;
27import from Osmocom_Types all;
28import from GSM_Types all;
29import from IPL4asp_Types all;
30
31import from BSSAP_Types all;
32import from RAN_Adapter all;
33import from BSSAP_LE_Adapter all;
34import from BSSAP_LE_CodecPort all;
35import from BSSAP_LE_Types all;
36import from BSSLAP_Types all;
37import from BSSAP_CodecPort all;
38import from BSSMAP_Templates all;
39import from IPA_Emulation all;
40import from IPA_CodecPort all;
41import from IPA_Types all;
42import from IPA_Testing all;
43import from RSL_Types all;
44import from RSL_Emulation all;
45import from MGCP_Emulation all;
46import from MGCP_Templates all;
47import from MGCP_Types all;
48import from MGCP_CodecPort all;
49
50import from Osmocom_CTRL_Functions all;
51import from Osmocom_CTRL_Types all;
52import from Osmocom_CTRL_Adapter all;
53
54import from StatsD_Types all;
55import from StatsD_CodecPort all;
56import from StatsD_CodecPort_CtrlFunct all;
57import from StatsD_Checker all;
58
59import from Osmocom_VTY_Functions all;
60import from TELNETasp_PortType all;
61
62import from MobileL3_CommonIE_Types all;
63import from MobileL3_Types all;
64import from MobileL3_RRM_Types all;
65import from L3_Templates all;
66import from GSM_RR_Types all;
67
68import from SCCP_Templates all;
69import from BSSMAP_Templates all;
70import from BSSMAP_LE_Templates all;
71
72import from SCCPasp_Types all;
73
74import from GSM_SystemInformation all;
75import from GSM_RestOctets all;
76import from TCCConversion_Functions all;
77
78import from RAN_Emulation all;
79import from MSC_ConnectionHandler all;
80
81import from Native_Functions all;
82
83const integer NUM_BTS := 3;
84const integer NUM_MSC := 3;
85
Neels Hofmeyr52b2b262022-02-07 23:34:35 +010086private function f_rsl_chan_nr_to_subslot(RslChannelNr chan_nr, boolean use_vamos_subslot_nr := false)
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +020087return integer
88{
89 var integer subslot;
90 select (chan_nr) {
91 case (t_RslChanNr_Bm(?)) {
92 /* TCH/F, always subslot 0 */
93 subslot := 0;
94 }
95 case (t_RslChanNr_Lm(?, ?)) {
96 /* TCH/H */
97 subslot := chan_nr.u.lm.sub_chan;
98 }
99 case (t_RslChanNr_Osmo_VAMOS_Bm(?)) {
Neels Hofmeyr52b2b262022-02-07 23:34:35 +0100100 /* TCH/F shadow */
101 if (use_vamos_subslot_nr) {
102 subslot := 1;
103 } else {
104 subslot := 0;
105 }
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200106 }
107 case (t_RslChanNr_Osmo_VAMOS_Lm(?, ?)) {
Neels Hofmeyr52b2b262022-02-07 23:34:35 +0100108 /* TCH/H shadow */
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200109 subslot := chan_nr.u.lm.sub_chan;
Neels Hofmeyr52b2b262022-02-07 23:34:35 +0100110 if (use_vamos_subslot_nr) {
111 subslot := subslot + 2;
112 }
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200113 }
114 case else {
115 setverdict(fail, "unsupported RslChannelNr type in f_rsl_chan_nr_to_subslot()");
116 mtc.stop;
117 }
118 }
119 return subslot;
120}
121
122private function f_rsl_chan_nr_to_rsl_cbits(RslChannelNr chan_nr)
123return BIT5
124{
125 var BIT5 rsl_cbits;
126 select (chan_nr) {
127 case (t_RslChanNr_Bm(?)) {
128 rsl_cbits := '00001'B;
129 }
130 case (t_RslChanNr_Lm(?, ?)) {
131 rsl_cbits := int2bit(2 + chan_nr.u.lm.sub_chan, 5); /* '0001x'B */
132 }
133 case (t_RslChanNr_Osmo_VAMOS_Bm(?)) {
134 rsl_cbits := '11101'B;
135 }
136 case (t_RslChanNr_Osmo_VAMOS_Lm(?, ?)) {
137 rsl_cbits := int2bit(30 + chan_nr.u.lm.sub_chan, 5); /* '1111x'B */
138 }
139 case else {
140 setverdict(fail, "unsupported RslChannelNr type in f_rsl_chan_nr_to_rsl_cbits()");
141 mtc.stop;
142 }
143 }
144 return rsl_cbits;
145}
146
147private function f_rsl_chan_nr_to_rr_cbits(RslChannelNr chan_nr)
148return BIT5
149{
150 var BIT5 rr_cbits;
151 select (chan_nr) {
152 case (t_RslChanNr_Bm(?)) {
153 rr_cbits := '00001'B;
154 }
155 case (t_RslChanNr_Lm(?, ?)) {
156 rr_cbits := int2bit(2 + chan_nr.u.lm.sub_chan, 5); /* '0001x'B */
157 }
158 case (t_RslChanNr_Osmo_VAMOS_Bm(?)) {
159 rr_cbits := '00001'B;
160 /* In RR, there must *not* be Osmocom specific cbits */
161 }
162 case (t_RslChanNr_Osmo_VAMOS_Lm(?, ?)) {
163 rr_cbits := int2bit(2 + chan_nr.u.lm.sub_chan, 5); /* '0001x'B */
164 /* In RR, there must *not* be Osmocom specific cbits */
165 }
166 case else {
167 setverdict(fail, "unsupported RslChannelNr type in f_rsl_chan_nr_to_rr_cbits()");
168 mtc.stop;
169 }
170 }
171 return rr_cbits;
172}
173
174private function f_rsl_chan_nr_to_chrt(RslChannelNr chan_nr, boolean vamos)
175return RSL_ChanRateType
176{
177 var boolean fr;
178 select (chan_nr) {
179 case (t_RslChanNr_Bm(?)) {
180 fr := true;
181 }
182 case (t_RslChanNr_Lm(?, ?)) {
183 fr := false;
184 }
185 case (t_RslChanNr_Osmo_VAMOS_Bm(?)) {
186 fr := true;
187 }
188 case (t_RslChanNr_Osmo_VAMOS_Lm(?, ?)) {
189 fr := false;
190 }
191 case else {
192 setverdict(fail, "unsupported RslChannelNr type in f_rsl_chan_nr_to_chrt()");
193 mtc.stop;
194 }
195 }
196 if (fr) {
197 if (vamos) {
198 return RSL_CHRT_OSMO_TCH_F_VAMOS;
199 } else {
200 return RSL_CHRT_TCH_F;
201 }
202 } else {
203 if (vamos) {
204 return RSL_CHRT_OSMO_TCH_H_VAMOS;
205 } else {
206 return RSL_CHRT_TCH_H;
207 }
208 }
209}
210
Neels Hofmeyr52b2b262022-02-07 23:34:35 +0100211private function f_lchan_str(integer bts_nr, integer trx_nr, RslChannelNr chan_nr, boolean use_vamos_subslot_nr := false)
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200212return charstring
213{
Neels Hofmeyr52b2b262022-02-07 23:34:35 +0100214 var integer subslot := f_rsl_chan_nr_to_subslot(chan_nr, use_vamos_subslot_nr := use_vamos_subslot_nr);
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200215 return "lchan " & int2str(bts_nr) & " " & int2str(trx_nr) & " " & int2str(chan_nr.tn) & " " & int2str(subslot);
216}
217
218private function f_long_lchan_str(integer bts_nr, integer trx_nr, RslChannelNr chan_nr)
219return charstring
220{
221 var integer subslot := f_rsl_chan_nr_to_subslot(chan_nr);
222 return "bts " & int2str(bts_nr) & " trx " & int2str(trx_nr) & " timeslot " & int2str(chan_nr.tn) & " sub-slot " & int2str(subslot);
223}
224
225private function f_lchan_ensure_established(TELNETasp_PT vty, integer bts_nr, integer trx_nr, RslChannelNr chan_nr)
226{
Neels Hofmeyr52b2b262022-02-07 23:34:35 +0100227 var charstring lchan_str := f_lchan_str(bts_nr, trx_nr, chan_nr, use_vamos_subslot_nr := true);
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200228 var charstring lchan_info := f_vty_transceive_ret(vty, "show " & lchan_str);
229 if (f_strstr(lchan_info, "State: ESTABLISHED") < 0) {
230 log("'show lchan' replied: ", lchan_info);
231 setverdict(fail, "lchan " & lchan_str & " is not in state ESTABLISHED");
232 mtc.stop;
233 }
234 setverdict(pass);
235}
236
237/* Activate a primary lchan in VAMOS speech mode */
238testcase TC_chan_act_to_vamos() runs on test_CT {
239 f_init_vty();
240
241 f_logp(BSCVTY, "TC_chan_act_to_vamos");
242
243 f_init(1, false);
244 f_sleep(1.0);
245
246 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 activate-vamos fr");
247
248 var RSL_Message rsl;
249
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600250 rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200251
252 var RSL_IE_Body chan_mode_ie;
253 if (f_rsl_find_ie(rsl, RSL_IE_CHAN_MODE, chan_mode_ie) == false) {
254 setverdict(fail, "Cannot find RSL_IE_CHAN_MODE");
255 mtc.stop;
256 }
257 if (chan_mode_ie.chan_mode.ch_rate_type != RSL_CHRT_OSMO_TCH_F_VAMOS) {
258 setverdict(fail, "expected chan_mode.ch_rate_type == RSL_CHRT_OSMO_TCH_F_VAMOS");
259 mtc.stop;
260 }
261
262 var RSL_IE_Body osmo_tsc_ie;
263 if (f_rsl_find_ie(rsl, RSL_IE_OSMO_TRAINING_SEQUENCE, osmo_tsc_ie) == false) {
264 setverdict(fail, "Cannot find RSL_IE_OSMO_TRAINING_SEQUENCE");
265 mtc.stop;
266 }
267
268 var RslChannelNr chan_nr := rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600269 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 23+10));
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200270
271 f_sleep(1.0);
272 f_lchan_ensure_established(BSCVTY, 0, 0, chan_nr);
273
Vadim Yanitskiyce8eb852022-02-07 14:15:10 +0600274 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 deactivate");
275
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200276 f_shutdown_helper();
277}
278
279/* verify that DTAP passes through both ways with the right cbits */
280private function f_verify_dtap() runs on MSC_ConnHdlr
281{
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200282 var PDU_BSSAP rx_bssap_dtap;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +0100283 var octetstring l3_data := gen_l3_valid_payload();
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200284
285 /* MS to NW */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +0100286 RSL.send(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_data));
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200287 BSSAP.receive(tr_BSSAP_DTAP) -> value rx_bssap_dtap;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +0100288 if (not match(rx_bssap_dtap.pdu.dtap, l3_data)) {
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200289 setverdict(fail, "unexpected L3 data");
290 mtc.stop;
291 }
292
293 /* NW to MS */
294 l3_data := '0800dcba9876543210'O;
295 BSSAP.send(ts_BSSAP_DTAP(l3_data, '00'O));
296 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, tr_RslLinkID_DCCH(0), l3_data));
297}
298
299
300private function f_est_lchan_and_mode_modify_to_vamos() runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200301 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +0200302 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200303
304 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
305 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
306 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
307 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
308 g_pars.ass_codec_list.codecElements[0];
309 if (isvalue(g_pars.expect_mr_s0_s7)) {
310 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
311 g_pars.expect_mr_s0_s7;
312 }
313 }
314 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
315 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
316 log("expecting ASS COMPL like this: ", exp_compl);
317
318 f_establish_fully(ass_cmd, exp_compl);
319
320 f_lchan_ensure_established(BSCVTY, 0, 0, g_chan_nr);
321
322 var charstring current_long_lchan_str := f_long_lchan_str(0, 0, g_chan_nr);
323 f_vty_transceive(BSCVTY, current_long_lchan_str & " modify vamos tsc 2 3");
324
325 var RSL_Message rsl_rr;
326 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl_rr;
327
328 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl_rr.ies[2].body.l3_info.payload);
329
330 var integer current_subslot := f_rsl_chan_nr_to_subslot(g_chan_nr);
331
332 template PDU_ML3_NW_MS expect_rr_modify := tr_RRM_ModeModify(
333 tr_ChannelDescription2_V(timeslotNumber := int2bit(g_chan_nr.tn, 3)),
334 tr_ChannelMode_V(mode := 'C1'O /* 1 1 0 0 0 0 0 1 speech full rate or half rate version 1 in VAMOS mode (3GPP TS 44.018) */),
335 extendedTSCSet := tr_ExtendedTSCSet_TV(cSDomainTSCSet := '01'B));
336
337 if (not match(l3, expect_rr_modify)) {
338 log("expected: ", expect_rr_modify);
339 log("got: ", l3);
340 setverdict(fail, "RR channelModeModify message is not as expected");
341 mtc.stop;
342 }
343 f_rsl_reply(ts_RRM_ModeModifyAck(l3.msgs.rrm.channelModeModify.channelDescription,
344 l3.msgs.rrm.channelModeModify.channelMode,
345 l3.msgs.rrm.channelModeModify.extendedTSCSet), rsl_rr);
346
347 var RSL_Message rsl;
348 RSL.receive(tr_RSL_MODE_MODIFY_REQ_with_OSMO_TSC(g_chan_nr, tr_RSL_ChanMode(f_rsl_chan_nr_to_chrt(g_chan_nr, true), RSL_CMOD_SP_GSM1),
349 tsc_set := 1, /* 1 means TSC Set 2 (range 1-4 in spec tables and naming, 0-3 on the wire) */
350 tsc := 3));
351 RSL.send(ts_RSL_MODE_MODIFY_ACK(g_chan_nr));
352 f_sleep(1.0);
353
354 f_lchan_ensure_established(BSCVTY, 0, 0, g_chan_nr);
355 f_verify_dtap();
356}
357
358private function f_TC_mode_modify_to_vamos(charstring id) runs on MSC_ConnHdlr {
359 f_est_lchan_and_mode_modify_to_vamos();
Vadim Yanitskiy41b702f2022-02-07 14:16:14 +0600360 f_perform_clear(RSL);
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200361}
362
363/* Modify a primary lchan into VAMOS speech mode */
364testcase TC_mode_modify_to_vamos_fr() runs on test_CT {
365 var TestHdlrParams pars := f_gen_test_hdlr_pars();
366 var MSC_ConnHdlr vc_conn;
367
368 f_init(1, true);
369 f_sleep(1.0);
370
371 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
372 vc_conn := f_start_handler(refers(f_TC_mode_modify_to_vamos), pars);
373 vc_conn.done;
374 f_shutdown_helper();
375}
376
377/* Modify a primary lchan into VAMOS speech mode */
378testcase TC_mode_modify_to_vamos_hr() runs on test_CT {
379 var TestHdlrParams pars := f_gen_test_hdlr_pars();
380 var MSC_ConnHdlr vc_conn;
381
382 f_init(1, true);
383 f_sleep(1.0);
384
385 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
386 vc_conn := f_start_handler(refers(f_TC_mode_modify_to_vamos), pars);
387 vc_conn.done;
388 f_shutdown_helper();
389}
390
391/* Establish a primary lchan, and then do a re-assignment to a VAMOS shadow lchan. */
392private function f_reassign_secondary_to_primary_lchan(RslChannelNr new_chan_nr) runs on MSC_ConnHdlr
393{
394 var integer current_subslot := f_rsl_chan_nr_to_subslot(g_chan_nr);
395
396 var integer new_subslot := f_rsl_chan_nr_to_subslot(new_chan_nr);
397 var BIT5 new_rr_cbits := f_rsl_chan_nr_to_rr_cbits(new_chan_nr);
398
399 activate(as_Media_mgw());
400
401 f_rslem_register(0, new_chan_nr, RSL_PROC);
402 log("f_rslem_register(0, new_chan_nr = ", new_chan_nr, ")");
403
404 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot " & int2str(g_chan_nr.tn) & " vamos-sub-slot " & int2str(current_subslot)
405 & " reassign-to trx 0 timeslot " & int2str(new_chan_nr.tn) & " sub-slot " & int2str(new_subslot));
406 /* RSL CHAN ACT is ACKed by RSL emulation */
407
408 var RSL_Message rsl;
409 var RSL_IE_Body ie;
410 var boolean b_unused;
411 interleave {
412 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
413 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
414 var template PDU_ML3_NW_MS expect_rr_assignment := tr_RR_AssignmentCommand(
415 desc := tr_ChannelDescription2_V(timeslotNumber := int2bit(new_chan_nr.tn, 3),
416 channelTypeandTDMAOffset := new_rr_cbits),
417 mode := tr_ChannelMode_TV(mode := '01'O
418 /* 0 0 0 0 0 0 0 1 speech full rate or half rate version 1 (3GPP TS 44.018) */),
419 extendedTSCSet := omit);
420 if (not match(l3, expect_rr_assignment)) {
421 log("expected: ", expect_rr_assignment);
422 log("got: ", l3);
423 setverdict(fail, "RR assignmentCommand message is not as expected");
424 mtc.stop;
425 }
426
427 var PDU_ML3_MS_NW l3_tx := valueof(ts_RRM_AssignmentComplete('00'O));
428 RSL.send(ts_RSL_EST_IND(new_chan_nr, valueof(ts_RslLinkID_DCCH(0)),
429 enc_PDU_ML3_MS_NW(l3_tx)));
430
431 }
432 [] RSL.receive(tr_RSL_IPA_CRCX(new_chan_nr)) -> value rsl {
433 var uint7_t rtp_pt := 0;
434 if (f_rsl_find_ie(rsl, RSL_IE_IPAC_RTP_PAYLOAD, ie)) {
435 rtp_pt := ie.ipa_rtp_pt;
436 }
437 RSL.send(ts_RSL_IPA_CRCX_ACK(new_chan_nr, 123,
Vadim Yanitskiyfc631642021-07-03 02:42:45 +0200438 f_inet_addr("1.2.3.4"),
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200439 4321,
440 rtp_pt));
441 }
442 [] RSL.receive(tr_RSL_IPA_MDCX(new_chan_nr, ?)) -> value rsl{
443 /* Extract conn_id, ip, port, rtp_pt2 from request + use in response */
444 b_unused := f_rsl_find_ie(rsl, RSL_IE_IPAC_CONN_ID, ie);
445 var uint16_t conn_id := ie.ipa_conn_id;
446 /* mandatory */
447 b_unused := f_rsl_find_ie(rsl, RSL_IE_IPAC_REMOTE_IP, ie);
448 var HostPort peer;
Vadim Yanitskiyfc631642021-07-03 02:42:45 +0200449 peer.host := f_inet_ntoa(ie.ipa_remote_ip);
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200450 b_unused := f_rsl_find_ie(rsl, RSL_IE_IPAC_REMOTE_PORT, ie);
451 peer.port_nr := ie.ipa_remote_port;
452 var uint7_t rtp_pt := 0;
453 /* optional */
454 if (f_rsl_find_ie(rsl, RSL_IE_IPAC_RTP_PAYLOAD, ie)) {
455 rtp_pt := ie.ipa_rtp_pt;
456 }
457 RSL.send(ts_RSL_IPA_MDCX_ACK(new_chan_nr, conn_id,
Vadim Yanitskiyfc631642021-07-03 02:42:45 +0200458 f_inet_addr(peer.host),
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200459 peer.port_nr,
460 rtp_pt));
461 }
462 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
463 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200464 RSL.send(ts_ASP_RSL_UD(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr),
465 IPAC_PROTO_RSL_TRX0));
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200466 f_rslem_unregister(0, g_chan_nr, RSL_PROC);
467 g_chan_nr := new_chan_nr;
468 }
469 /* (There must be no RSL_MT_REL_REQ on the old lchan.) */
470 }
471
472 setverdict(pass);
473
474 f_sleep(1.0);
Neels Hofmeyr52b2b262022-02-07 23:34:35 +0100475 f_lchan_ensure_established(BSCVTY, 0, 0, g_chan_nr);
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200476
477 f_verify_dtap();
478}
479
480private function f_est_and_reassign_to_secondary_lchan(RslChannelNr new_chan_nr) runs on MSC_ConnHdlr
481{
482 var integer new_subslot := f_rsl_chan_nr_to_subslot(new_chan_nr);
483 var BIT5 new_rr_cbits := f_rsl_chan_nr_to_rr_cbits(new_chan_nr);
484
485 var PDU_BSSAP ass_cmd := f_gen_ass_req();
486 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
487
488 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
489 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
490 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
491 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
492 g_pars.ass_codec_list.codecElements[0];
493 if (isvalue(g_pars.expect_mr_s0_s7)) {
494 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
495 g_pars.expect_mr_s0_s7;
496 }
497 }
498 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
499 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
500 log("expecting ASS COMPL like this: ", exp_compl);
501
502 f_establish_fully(ass_cmd, exp_compl);
503
504 var integer current_subslot := f_rsl_chan_nr_to_subslot(g_chan_nr);
505
506 f_sleep(1.0);
507
508 activate(as_Media_mgw());
509
510 f_rslem_register(0, new_chan_nr, RSL_PROC);
511 log("f_rslem_register(0, new_chan_nr = ", new_chan_nr, ")");
512
513 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot " & int2str(g_chan_nr.tn) & " sub-slot " & int2str(current_subslot)
514 & " reassign-to trx 0 timeslot " & int2str(new_chan_nr.tn) & " vamos-sub-slot " & int2str(new_subslot) & " tsc 4 2");
515 /* RSL CHAN ACT is ACKed by RSL emulation */
516
517 var RSL_Message rsl;
518 var RSL_IE_Body ie;
519 var boolean b_unused;
520 interleave {
521 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
522 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
523 var template PDU_ML3_NW_MS expect_rr_assignment := tr_RR_AssignmentCommand(
524 desc := tr_ChannelDescription2_V(timeslotNumber := int2bit(new_chan_nr.tn, 3),
525 channelTypeandTDMAOffset := new_rr_cbits),
526 mode := tr_ChannelMode_TV(mode := 'C1'O
527 /* 1 1 0 0 0 0 0 1 speech full rate or half rate version 1 in VAMOS mode (3GPP TS 44.018) */),
528 extendedTSCSet := tr_ExtendedTSCSet_TV(cSDomainTSCSet := '11'B
529 /* 3 means TSC Set 4 (range 1-4 in spec tables and naming, 0-3 on the wire) */));
530 if (not match(l3, expect_rr_assignment)) {
531 log("expected: ", expect_rr_assignment);
532 log("got: ", l3);
533 setverdict(fail, "RR assignmentCommand message is not as expected");
534 mtc.stop;
535 }
536
537 var PDU_ML3_MS_NW l3_tx := valueof(ts_RRM_AssignmentComplete('00'O));
538 RSL.send(ts_RSL_EST_IND(new_chan_nr, valueof(ts_RslLinkID_DCCH(0)),
539 enc_PDU_ML3_MS_NW(l3_tx)));
540
541 }
542 [] RSL.receive(tr_RSL_IPA_CRCX(new_chan_nr)) -> value rsl {
543 var uint7_t rtp_pt := 0;
544 if (f_rsl_find_ie(rsl, RSL_IE_IPAC_RTP_PAYLOAD, ie)) {
545 rtp_pt := ie.ipa_rtp_pt;
546 }
547 RSL.send(ts_RSL_IPA_CRCX_ACK(new_chan_nr, 123,
Vadim Yanitskiyfc631642021-07-03 02:42:45 +0200548 f_inet_addr("1.2.3.4"),
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200549 4321,
550 rtp_pt));
551 }
552 [] RSL.receive(tr_RSL_IPA_MDCX(new_chan_nr, ?)) -> value rsl{
553 /* Extract conn_id, ip, port, rtp_pt2 from request + use in response */
554 b_unused := f_rsl_find_ie(rsl, RSL_IE_IPAC_CONN_ID, ie);
555 var uint16_t conn_id := ie.ipa_conn_id;
556 /* mandatory */
557 b_unused := f_rsl_find_ie(rsl, RSL_IE_IPAC_REMOTE_IP, ie);
558 var HostPort peer;
Vadim Yanitskiyfc631642021-07-03 02:42:45 +0200559 peer.host := f_inet_ntoa(ie.ipa_remote_ip);
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200560 b_unused := f_rsl_find_ie(rsl, RSL_IE_IPAC_REMOTE_PORT, ie);
561 peer.port_nr := ie.ipa_remote_port;
562 var uint7_t rtp_pt := 0;
563 /* optional */
564 if (f_rsl_find_ie(rsl, RSL_IE_IPAC_RTP_PAYLOAD, ie)) {
565 rtp_pt := ie.ipa_rtp_pt;
566 }
567 RSL.send(ts_RSL_IPA_MDCX_ACK(new_chan_nr, conn_id,
Vadim Yanitskiyfc631642021-07-03 02:42:45 +0200568 f_inet_addr(peer.host),
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200569 peer.port_nr,
570 rtp_pt));
571 }
572 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
573 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200574 RSL.send(ts_ASP_RSL_UD(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr),
575 IPAC_PROTO_RSL_TRX0));
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200576 f_rslem_unregister(0, g_chan_nr, RSL_PROC);
577 g_chan_nr := new_chan_nr;
578 }
579 /* (There must be no RSL_MT_REL_REQ on the old lchan.) */
580 }
581
582 setverdict(pass);
583
584 f_sleep(1.0);
Neels Hofmeyr52b2b262022-02-07 23:34:35 +0100585 f_lchan_ensure_established(BSCVTY, 0, 0, g_chan_nr);
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200586 f_verify_dtap();
587}
588
589/* Establish a primary lchan, and then do a re-assignment to a VAMOS shadow lchan.
590 * Also re-assign back to a primary lchan. */
591private function f_TC_assign_to_secondary_lchan_fr(charstring id) runs on MSC_ConnHdlr {
592 f_est_and_reassign_to_secondary_lchan(valueof(t_RslChanNr_Osmo_VAMOS_Bm(2)));
593 f_reassign_secondary_to_primary_lchan(valueof(t_RslChanNr_Bm(3)));
594 f_perform_clear(RSL);
595 f_sleep(1.0);
596}
597
598/* Establish a primary lchan, and then do a re-assignment to a VAMOS shadow lchan. */
599testcase TC_assign_to_secondary_lchan_fr() runs on test_CT {
600 var TestHdlrParams pars := f_gen_test_hdlr_pars();
601 var MSC_ConnHdlr vc_conn;
602
603 f_init(1, true);
604 f_sleep(1.0);
605
606 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
607 vc_conn := f_start_handler(refers(f_TC_assign_to_secondary_lchan_fr), pars);
608 vc_conn.done;
609 f_shutdown_helper();
610}
611
612/* Establish a primary lchan, and then do a re-assignment to a VAMOS shadow lchan.
613 * Also re-assign back to a primary lchan. */
614private function f_TC_assign_to_secondary_lchan_hr(charstring id) runs on MSC_ConnHdlr {
615 f_est_and_reassign_to_secondary_lchan(valueof(t_RslChanNr_Osmo_VAMOS_Lm(6, 0)));
616 f_reassign_secondary_to_primary_lchan(valueof(t_RslChanNr_Lm(6, 1)));
617 f_perform_clear(RSL);
618 f_sleep(1.0);
619}
620
621/* Establish a primary lchan, and then do a re-assignment to a VAMOS shadow lchan. */
622testcase TC_assign_to_secondary_lchan_hr() runs on test_CT {
623 var TestHdlrParams pars := f_gen_test_hdlr_pars();
624 var MSC_ConnHdlr vc_conn;
625
626 f_init(1, true);
627 f_sleep(1.0);
628
629 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
630 vc_conn := f_start_handler(refers(f_TC_assign_to_secondary_lchan_hr), pars);
631 vc_conn.done;
632 f_shutdown_helper();
633}
634
Vadim Yanitskiy7bd04e42022-02-07 14:18:38 +0600635const charstring PRIMARY_LCHAN_DONE := "PRIMARY_LCHAN_DONE";
636const charstring MULTIPLEX_DONE := "MULTIPLEX_DONE";
637
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200638/* First, primary lchan of TC_vamos_multiplex_tch_f_tch_f() */
639private function f_TC_vamos_multiplex_tch_f_tch_f1(charstring id) runs on MSC_ConnHdlr {
640 f_est_lchan_and_mode_modify_to_vamos();
Vadim Yanitskiy7bd04e42022-02-07 14:18:38 +0600641 f_sleep(1.0);
642 COORD.send(PRIMARY_LCHAN_DONE);
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200643 f_logp(BSCVTY, "f_est_lchan_and_mode_modify_to_vamos done");
Vadim Yanitskiy7bd04e42022-02-07 14:18:38 +0600644 COORD.receive(MULTIPLEX_DONE);
645 f_perform_clear(RSL);
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200646}
647
648/* Second, VAMOS shadow lchan of TC_vamos_multiplex_tch_f_tch_f() */
649private function f_TC_vamos_multiplex_tch_f_tch_f2(charstring id) runs on MSC_ConnHdlr {
Vadim Yanitskiy7bd04e42022-02-07 14:18:38 +0600650 f_sleep(1.0);
651 COORD.receive(PRIMARY_LCHAN_DONE);
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200652 f_est_and_reassign_to_secondary_lchan(valueof(t_RslChanNr_Osmo_VAMOS_Bm(1)));
Vadim Yanitskiy7bd04e42022-02-07 14:18:38 +0600653 f_sleep(1.0);
654 COORD.send(MULTIPLEX_DONE);
655 f_perform_clear(RSL);
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200656}
657
658/* Establish a primary lchan and modify it to VAMOS speech mode. Then establish
659 * another primary lchan, and re-assign it to the VAMOS secondary lchan of the
660 * first primary lchan. */
661testcase TC_vamos_multiplex_tch_f_tch_f() runs on test_CT {
662 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
663 var MSC_ConnHdlr vc_conn1;
664
665 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
666 var MSC_ConnHdlr vc_conn2;
667 pars2.imsi := '001014234234234'H;
668 pars2.media_nr := 2;
669
670 f_init(1, true);
671 f_sleep(1.0);
672
673 pars1.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
674 pars2.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200675
Vadim Yanitskiy7bd04e42022-02-07 14:18:38 +0600676 vc_conn1 := f_start_handler(refers(f_TC_vamos_multiplex_tch_f_tch_f1), pars1);
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200677 vc_conn2 := f_start_handler(refers(f_TC_vamos_multiplex_tch_f_tch_f2), pars2);
Vadim Yanitskiy7bd04e42022-02-07 14:18:38 +0600678 connect(vc_conn1:COORD, vc_conn2:COORD);
679
680 vc_conn1.done;
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200681 vc_conn2.done;
Vadim Yanitskiy7bd04e42022-02-07 14:18:38 +0600682
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200683 f_shutdown_helper();
684}
685
Vadim Yanitskiy5f14d342022-02-07 14:18:38 +0600686const charstring DONE := "DONE";
687
688/*
689 * f1 f2 f3 f4
690 * COORD <--> COORD | COORD2 <--> COORD | COORD2 <--> COORD
691 * ---DONE-----> ---DONE-----> ---DONE----->
692 * <----DONE---- <----DONE---- <----DONE----
693 */
694
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200695/* First, primary lchan of TC_vamos_multiplex_tch_h_tch_h_tch_h_tch_h() */
696private function f_TC_vamos_multiplex_tch_h_tch_h1(charstring id) runs on MSC_ConnHdlr {
697 f_est_lchan_and_mode_modify_to_vamos();
698 f_logp(BSCVTY, "f_est_lchan_and_mode_modify_to_vamos done");
Vadim Yanitskiy5f14d342022-02-07 14:18:38 +0600699 COORD.send(DONE);
700 COORD.receive(DONE);
701 f_perform_clear(RSL);
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200702}
703
704/* Second, VAMOS shadow lchan of TC_vamos_multiplex_tch_h_tch_h_tch_h_tch_h() */
705private function f_TC_vamos_multiplex_tch_h_tch_h2(charstring id) runs on MSC_ConnHdlr {
Vadim Yanitskiy5f14d342022-02-07 14:18:38 +0600706 f_sleep(1.0);
707 COORD.receive(DONE);
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200708 f_est_and_reassign_to_secondary_lchan(valueof(t_RslChanNr_Osmo_VAMOS_Lm(5, 0)));
Vadim Yanitskiy5f14d342022-02-07 14:18:38 +0600709 COORD2.send(DONE);
710 COORD2.receive(DONE)
711 COORD.send(DONE);
712 f_perform_clear(RSL);
713}
714
715private function f_TC_vamos_multiplex_tch_h_tch_h3(charstring id) runs on MSC_ConnHdlr {
716 f_sleep(1.0);
717 COORD.receive(DONE);
718 f_est_lchan_and_mode_modify_to_vamos();
719 f_logp(BSCVTY, "f_est_lchan_and_mode_modify_to_vamos done");
720 COORD2.send(DONE);
721 COORD2.receive(DONE);
722 COORD.send(DONE);
723 f_perform_clear(RSL);
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200724}
725
726private function f_TC_vamos_multiplex_tch_h_tch_h4(charstring id) runs on MSC_ConnHdlr {
Vadim Yanitskiy5f14d342022-02-07 14:18:38 +0600727 f_sleep(1.0);
728 COORD.receive(DONE);
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200729 f_est_and_reassign_to_secondary_lchan(valueof(t_RslChanNr_Osmo_VAMOS_Lm(5, 1)));
Vadim Yanitskiy5f14d342022-02-07 14:18:38 +0600730 COORD.send(DONE);
731 f_perform_clear(RSL);
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200732}
733
734/* Establish a primary lchan and modify it to VAMOS speech mode. Then establish
735 * another primary lchan, and re-assign it to the VAMOS secondary lchan of the
736 * first primary lchan. */
737testcase TC_vamos_multiplex_tch_h_tch_h_tch_h_tch_h() runs on test_CT {
738 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
739 var MSC_ConnHdlr vc_conn1;
740 pars1.imsi := '001011111111111'H;
741 pars1.media_nr := 1;
742
743 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
744 var MSC_ConnHdlr vc_conn2;
745 pars2.imsi := '001012222222222'H;
746 pars2.media_nr := 2;
747
748 var TestHdlrParams pars3 := f_gen_test_hdlr_pars();
749 var MSC_ConnHdlr vc_conn3;
750 pars3.imsi := '001013333333333'H;
751 pars3.media_nr := 3;
752
753 var TestHdlrParams pars4 := f_gen_test_hdlr_pars();
754 var MSC_ConnHdlr vc_conn4;
755 pars4.imsi := '001014444444444'H;
756 pars4.media_nr := 4;
757
758 f_init(1, true);
759 f_sleep(1.0);
760
761 pars1.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
762 pars2.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
763 pars3.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
764 pars4.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
765
766 vc_conn1 := f_start_handler(refers(f_TC_vamos_multiplex_tch_h_tch_h1), pars1);
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200767 vc_conn2 := f_start_handler(refers(f_TC_vamos_multiplex_tch_h_tch_h2), pars2);
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200768
769 /* Also fill up the second subslot of the TCH/H timeslot */
Vadim Yanitskiy5f14d342022-02-07 14:18:38 +0600770 vc_conn3 := f_start_handler(refers(f_TC_vamos_multiplex_tch_h_tch_h3), pars3);
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200771 vc_conn4 := f_start_handler(refers(f_TC_vamos_multiplex_tch_h_tch_h4), pars4);
Vadim Yanitskiy5f14d342022-02-07 14:18:38 +0600772
773 /* see diagram above (search for "---DONE") */
774 connect(vc_conn1:COORD, vc_conn2:COORD);
775 connect(vc_conn2:COORD2, vc_conn3:COORD);
776 connect(vc_conn3:COORD2, vc_conn4:COORD);
777
778 vc_conn1.done;
779 vc_conn2.done;
780 vc_conn3.done;
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200781 vc_conn4.done;
Vadim Yanitskiy5f14d342022-02-07 14:18:38 +0600782
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200783 f_shutdown_helper();
784}
785
786control {
787 execute( TC_chan_act_to_vamos() );
788 execute( TC_mode_modify_to_vamos_fr() );
789 execute( TC_mode_modify_to_vamos_hr() );
790 execute( TC_assign_to_secondary_lchan_fr() );
791 execute( TC_assign_to_secondary_lchan_hr() );
792 execute( TC_vamos_multiplex_tch_f_tch_f() );
793 execute( TC_vamos_multiplex_tch_h_tch_h_tch_h_tch_h() );
794}
795
796}