blob: f40b19e4db6f4ff864a88445dd28c977bdaeeac1 [file] [log] [blame]
Harald Welte28d943e2017-11-25 15:00:50 +01001module BSC_Tests {
2
Harald Welte21b46bd2017-12-17 19:46:32 +01003/* Integration Tests for OsmoBSC
Harald Weltea0630032018-03-20 21:09:55 +01004 * (C) 2017-2018 by Harald Welte <laforge@gnumonks.org>
Harald Welte21b46bd2017-12-17 19:46:32 +01005 * 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 *
Harald Welte34b5a952019-05-27 11:54:11 +020010 * SPDX-License-Identifier: GPL-2.0-or-later
11 *
Harald Welte21b46bd2017-12-17 19:46:32 +010012 * 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
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +020023friend module BSC_Tests_VAMOS;
Vadim Yanitskiy5eb06a32022-06-23 18:39:46 +070024friend module BSC_Tests_CBSP;
Vadim Yanitskiy3cc065b2023-01-06 21:35:12 +070025friend module BSC_Tests_LCLS;
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +020026
Neels Hofmeyr4f118412020-06-04 15:25:10 +020027import from Misc_Helpers all;
Harald Welte4003d112017-12-09 22:35:39 +010028import from General_Types all;
Harald Welte28d943e2017-11-25 15:00:50 +010029import from Osmocom_Types all;
Harald Welteae026692017-12-09 01:03:01 +010030import from GSM_Types all;
Harald Welte28d943e2017-11-25 15:00:50 +010031import from IPL4asp_Types all;
32
Harald Welte6f521d82017-12-11 19:52:02 +010033import from BSSAP_Types all;
Harald Welte6811d102019-04-14 22:23:14 +020034import from RAN_Adapter all;
Harald Welte47cd0e32020-08-21 12:39:11 +020035import from BSSAP_LE_Adapter all;
36import from BSSAP_LE_CodecPort all;
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020037import from BSSAP_LE_Types all;
38import from BSSLAP_Types all;
Harald Welteae026692017-12-09 01:03:01 +010039import from BSSAP_CodecPort all;
40import from BSSMAP_Templates all;
Harald Welte28d943e2017-11-25 15:00:50 +010041import from IPA_Emulation all;
Stefan Sperling830dc9d2018-02-12 21:08:28 +010042import from IPA_CodecPort all;
Harald Welteae026692017-12-09 01:03:01 +010043import from IPA_Types all;
Stefan Sperling0796a822018-10-05 13:01:39 +020044import from IPA_Testing all;
Harald Welteae026692017-12-09 01:03:01 +010045import from RSL_Types all;
Harald Welte624f9632017-12-16 19:26:04 +010046import from RSL_Emulation all;
Daniel Willmann191e0d92018-01-17 12:44:35 +010047import from MGCP_Emulation all;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010048import from MGCP_Templates all;
49import from MGCP_Types all;
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +020050import from MGCP_CodecPort all;
Harald Welte28d943e2017-11-25 15:00:50 +010051
Harald Welte96c94412017-12-09 03:12:45 +010052import from Osmocom_CTRL_Functions all;
Harald Weltea5d2ab22017-12-09 14:21:42 +010053import from Osmocom_CTRL_Types all;
Harald Welteffe55fc2018-01-17 22:39:54 +010054import from Osmocom_CTRL_Adapter all;
Harald Welte96c94412017-12-09 03:12:45 +010055
Daniel Willmannebdecc02020-08-12 15:30:17 +020056import from StatsD_Types all;
57import from StatsD_CodecPort all;
58import from StatsD_CodecPort_CtrlFunct all;
59import from StatsD_Checker all;
60
Harald Weltebc03c762018-02-12 18:09:38 +010061import from Osmocom_VTY_Functions all;
62import from TELNETasp_PortType all;
63
Harald Welte6f521d82017-12-11 19:52:02 +010064import from MobileL3_CommonIE_Types all;
Harald Weltee3bd6582018-01-31 22:51:25 +010065import from MobileL3_Types all;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010066import from MobileL3_RRM_Types all;
Harald Welte6f521d82017-12-11 19:52:02 +010067import from L3_Templates all;
68import from GSM_RR_Types all;
69
Stefan Sperlingc307e682018-06-14 15:15:46 +020070import from SCCP_Templates all;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010071import from BSSMAP_Templates all;
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020072import from BSSMAP_LE_Templates all;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010073
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010074import from SCCPasp_Types all;
75
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020076import from GSM_SystemInformation all;
77import from GSM_RestOctets all;
Neels Hofmeyrad132f22020-07-08 02:20:16 +020078import from TCCConversion_Functions all;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020079
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060080const integer NUM_TRX := 4;
Harald Welte5d1a2202017-12-13 19:51:29 +010081const integer NUM_BTS := 3;
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +020082const integer NUM_BTS_CFG := 4; /* we have 4 BTS in the osmo-bsc.cfg (for inter-BSC HO tests) but use only 3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060083const integer NUM_TRX_CFG := 1; /* we support up to 4 TRX per BTS, but have only 1 TRX per BTS in osmo-bsc.cfg */
Neels Hofmeyrf246a922020-05-13 02:27:10 +020084const integer NUM_MSC := 3;
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020085const integer NUM_MGW := 2;
Harald Welteae026692017-12-09 01:03:01 +010086const float T3101_MAX := 12.0;
Harald Welte28d943e2017-11-25 15:00:50 +010087
Harald Welte799c97b2017-12-14 17:50:30 +010088/* make sure to sync this with the osmo-bts.cfg you're using */
Philipp Maiercb6cc482018-03-26 13:08:00 +020089const integer NUM_TCHH_PER_BTS := 2;
90const integer NUM_TCHF_PER_BTS := 4;
Neels Hofmeyr74083c22020-07-29 00:43:01 +020091const integer NUM_SDCCH_PER_BTS := 3;
Harald Welte799c97b2017-12-14 17:50:30 +010092
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060093friend type record BtsTrxIdx {
94 uint8_t bts,
95 uint8_t trx
96}
97
98private type record BtsParams {
99 integer trx_num,
100 integer tsc
101}
102
Neels Hofmeyrbf720202021-10-02 12:58:24 +0200103/* Default Training Sequence Code expected for bts[i]:
104 * BTS 0 has BSIC 10 (and no explicit timeslot training_sequence_code config), so expecting TSC = (BSIC & 7) = 2.
105 * BTS 1 has BSIC 11, TSC = (BSIC & 7) = 3.
106 * BTS 2 has BSIC 12, TSC = (BSIC & 7) = 4.
107 * BTS 2 has BSIC 12, TSC = (BSIC & 7) = 4.
108 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600109private const BtsParams c_BtsParams[NUM_BTS_CFG] := {
110 /* BTS0 */ { trx_num := 1, tsc := 2 },
111 /* BTS1 */ { trx_num := 1, tsc := 3 },
Vadim Yanitskiy7a3d2932022-05-29 20:37:46 +0600112 /* BTS2 */ { trx_num := 4, tsc := 4 },
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600113 /* BTS3 */ { trx_num := 1, tsc := 4 }
Neels Hofmeyrbf720202021-10-02 12:58:24 +0200114}
Harald Welte4003d112017-12-09 22:35:39 +0100115
Vadim Yanitskiy59494702022-09-14 15:29:04 +0700116private const RSL_IE_Body c_mr_conf_5_90 :=
Pau Espin Pedrolf7634dc2022-09-02 17:56:00 +0200117 valueof(RSL_IE_Body:{multirate_cfg := ts_RSL_MultirateCfg(true, 0, '00000100'B /* 5,90k */)});
118
Harald Welte21b46bd2017-12-17 19:46:32 +0100119/* per-BTS state which we keep */
Harald Welte96c94412017-12-09 03:12:45 +0100120type record BTS_State {
Harald Welte21b46bd2017-12-17 19:46:32 +0100121 /* component reference to the IPA_Client component used for RSL */
Harald Weltea5d2ab22017-12-09 14:21:42 +0100122 IPA_Client rsl
Harald Welte96c94412017-12-09 03:12:45 +0100123}
124
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200125/* Default list of counters for an 'msc' entity. */
126const CounterNameVals counternames_msc_mscpool := {
127 { "mscpool:subscr:new", 0 },
128 { "mscpool:subscr:known", 0 },
129 { "mscpool:subscr:reattach", 0 },
130 { "mscpool:subscr:attach_lost", 0 },
131 { "mscpool:subscr:paged", 0 }
132};
133
Neels Hofmeyrbf037052020-10-28 22:52:02 +0000134/* List of global mscpool counters, not related to a specific 'msc' entity. */
135const CounterNameVals counternames_bsc_mscpool := {
136 { "mscpool:subscr:no_msc", 0 }
137};
138
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000139/* Default list of counters for 'bsc' and 'bts' entities. */
140const CounterNameVals counternames_bsc_bts_handover := {
141 { "assignment:attempted", 0 },
142 { "assignment:completed", 0 },
143 { "assignment:stopped", 0 },
144 { "assignment:no_channel", 0 },
145 { "assignment:timeout", 0 },
146 { "assignment:failed", 0 },
147 { "assignment:error", 0 },
148
149 { "handover:attempted", 0 },
150 { "handover:completed", 0 },
151 { "handover:stopped", 0 },
152 { "handover:no_channel", 0 },
153 { "handover:timeout", 0 },
154 { "handover:failed", 0 },
155 { "handover:error", 0 },
156
157 { "intra_cell_ho:attempted", 0 },
158 { "intra_cell_ho:completed", 0 },
159 { "intra_cell_ho:stopped", 0 },
160 { "intra_cell_ho:no_channel", 0 },
161 { "intra_cell_ho:timeout", 0 },
162 { "intra_cell_ho:failed", 0 },
163 { "intra_cell_ho:error", 0 },
164
165 { "intra_bsc_ho:attempted", 0 },
166 { "intra_bsc_ho:completed", 0 },
167 { "intra_bsc_ho:stopped", 0 },
168 { "intra_bsc_ho:no_channel", 0 },
169 { "intra_bsc_ho:timeout", 0 },
170 { "intra_bsc_ho:failed", 0 },
171 { "intra_bsc_ho:error", 0 },
172
173 { "interbsc_ho_out:attempted", 0 },
174 { "interbsc_ho_out:completed", 0 },
175 { "interbsc_ho_out:stopped", 0 },
176 { "interbsc_ho_out:timeout", 0 },
177 { "interbsc_ho_out:failed", 0 },
178 { "interbsc_ho_out:error", 0 },
179
180 { "interbsc_ho_in:attempted", 0 },
181 { "interbsc_ho_in:completed", 0 },
182 { "interbsc_ho_in:stopped", 0 },
183 { "interbsc_ho_in:no_channel", 0 },
184 { "interbsc_ho_in:timeout", 0 },
185 { "interbsc_ho_in:failed", 0 },
186 { "interbsc_ho_in:error", 0 }
187};
188
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100189const CounterNameVals counternames_bts_handover := {
190 { "incoming_intra_bsc_ho:attempted", 0 },
191 { "incoming_intra_bsc_ho:completed", 0 },
192 { "incoming_intra_bsc_ho:stopped", 0 },
193 { "incoming_intra_bsc_ho:no_channel", 0 },
194 { "incoming_intra_bsc_ho:timeout", 0 },
195 { "incoming_intra_bsc_ho:failed", 0 },
196 { "incoming_intra_bsc_ho:error", 0 }
197};
198
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200199/* Set of all System Information received during one RSL port's startup.
200 * Note that some System Information may be sent on RSL, but lacking actual SI data, to indicate that the BTS should not
201 * broadcast that SI type. That will be reflected as 'omit' here.
202 */
203type record SystemInformationConfig {
204 SystemInformationType1 si1 optional,
205 SystemInformationType2 si2 optional,
206 SystemInformationType2bis si2bis optional,
207 SystemInformationType2ter si2ter optional,
Neels Hofmeyrad132f22020-07-08 02:20:16 +0200208 SI2quaterRestOctetsList si2quater optional,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200209 SystemInformationType3 si3 optional,
210 SystemInformationType4 si4 optional,
Pau Espin Pedrol28652d82021-02-09 20:20:17 +0100211 SystemInformationType13 si13 optional,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200212 SystemInformationType5 si5 optional,
213 SystemInformationType5bis si5bis optional,
214 SystemInformationType5ter si5ter optional,
215 SystemInformationType6 si6 optional
216};
217
218const SystemInformationConfig SystemInformationConfig_omit := {
219 si1 := omit,
220 si2 := omit,
221 si2bis := omit,
222 si2ter := omit,
223 si2quater := omit,
224 si3 := omit,
225 si4 := omit,
226 si13 := omit,
227 si5 := omit,
228 si5bis := omit,
229 si5ter := omit,
230 si6 := omit
231};
232
233/* tr_EUTRAN_CellDesc with defaults used in BSC_Tests.ttcn */
234template EUTRAN_CellDesc tr_EUTRAN_CellDesc_default(template (present) uint16_t e_arfcn := ?,
235 template uint3_t meas_bw := 3)
236:= tr_EUTRAN_CellDesc(e_arfcn := e_arfcn,
237 meas_bw_presence := '1'B,
238 meas_bw := meas_bw);
239
240/* tr_EUTRAN_NeighbourCells with defaults used in BSC_Tests.ttcn */
Harald Welte65e419a2020-08-21 12:38:33 +0200241template EUTRAN_NeighbourCells tr_EUTRAN_NeighbourCells_default(template (present) EUTRAN_CellDescs cell_desc_list := { tr_EUTRAN_CellDesc_default },
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200242 template uint3_t prio := 3,
243 template (present) uint5_t thresh_high := 20,
244 template uint5_t thresh_low := 10,
245 template uint5_t qrxlevmin := 22)
246:= tr_EUTRAN_NeighbourCells(
247 cell_desc_list := cell_desc_list,
248 prio_presence := '1'B,
249 prio := prio,
250 thresh_high := thresh_high,
251 thresh_low_presence := '1'B,
252 thresh_low := thresh_low,
253 qrxlevmin_presence := '1'B,
254 qrxlevmin := qrxlevmin);
255
256template SystemInformationConfig SystemInformationConfig_default := {
257 si1 := {
258 cell_chan_desc := '8FB38000000000000000000000000000'O,
259 rach_control := {
260 max_retrans := RACH_MAX_RETRANS_7,
261 tx_integer := '1001'B,
262 cell_barr_access := false,
263 re_not_allowed := true,
264 acc := '0000010000000000'B
265 },
266 rest_octets := ?
267 },
268 si2 := {
269 bcch_freq_list := '00000000000000000000000000000000'O,
270 ncc_permitted := '11111111'B,
271 rach_control := {
272 max_retrans := RACH_MAX_RETRANS_7,
273 tx_integer := '1001'B,
274 cell_barr_access := false,
275 re_not_allowed := true,
276 acc := '0000010000000000'B
277 }
278 },
279 si2bis := omit,
280 si2ter := {
281 extd_bcch_freq_list := '8E320000000000000000000000000800'O,
282 rest_octets := ?
283 },
284 si2quater := {
285 tr_SI2quaterRestOctets_EUTRAN( repeated_neigh_cells := { tr_EUTRAN_NeighbourCells_default } )
286 },
287 si3 := {
288 cell_id := 0,
289 lai := {
290 mcc_mnc := '001F01'H,
291 lac := 1
292 },
293 ctrl_chan_desc := {
294 msc_r99 := true,
295 att := true,
296 bs_ag_blks_res := 1,
297 ccch_conf := CCHAN_DESC_1CCCH_COMBINED,
298 si22ind := false,
299 cbq3 := CBQ3_IU_MODE_NOT_SUPPORTED,
300 spare := '00'B,
301 bs_pa_mfrms := 3,
302 t3212 := 30
303 },
304 cell_options := {
305 dn_ind := false,
306 pwrc := false,
307 dtx := MS_SHALL_USE_UL_DTX,
308 radio_link_tout_div4 := 7
309 },
310 cell_sel_par := {
311 cell_resel_hyst_2dB := 2,
312 ms_txpwr_max_cch := 7,
313 acs := '0'B,
314 neci := true,
315 rxlev_access_min := 0
316 },
317 rach_control := {
318 max_retrans := RACH_MAX_RETRANS_7,
319 tx_integer := '1001'B,
320 cell_barr_access := false,
321 re_not_allowed := true,
322 acc := '0000010000000000'B
323 },
324 rest_octets := {
325 sel_params := {
326 presence := '0'B,
327 params := omit
328 },
329 pwr_offset := {
330 presence := '0'B,
331 offset := omit
332 },
333 si_2ter_ind := '1'B,
334 early_cm_ind := '0'B,
335 sched_where := {
336 presence := '0'B,
337 where := omit
338 },
339 gprs_ind := {
340 presence := '1'B,
341 ind := {
342 ra_colour := 0,
343 si13_pos := '0'B
344 }
345 },
346 umts_early_cm_ind := '1'B,
347 si2_quater_ind := {
348 presence := '1'B,
349 ind := '0'B
350 },
351 iu_mode_ind := omit,
352 si21_ind := {
353 presence := '0'B,
354 pos := omit
355 }
356 }
357 },
358 si4 := {
359 lai := {
360 mcc_mnc := '001F01'H,
361 lac := 1
362 },
363 cell_sel_par := {
364 cell_resel_hyst_2dB := 2,
365 ms_txpwr_max_cch := 7,
366 acs := '0'B,
367 neci := true,
368 rxlev_access_min := 0
369 },
370 rach_control := {
371 max_retrans := RACH_MAX_RETRANS_7,
372 tx_integer := '1001'B,
373 cell_barr_access := false,
374 re_not_allowed := true,
375 acc := '0000010000000000'B
376 },
Neels Hofmeyr74083c22020-07-29 00:43:01 +0200377 cbch_chan_desc := {
378 iei := '64'O,
379 v := {
380 chan_nr := {
381 u := {
382 sdcch4 := {
383 tag := '001'B,
384 sub_chan := 2
385 }
386 },
387 tn := 0
388 },
389 tsc := 2,
390 h := false,
391 arfcn := 871,
392 maio_hsn := omit
393 }
394 },
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200395 cbch_mobile_alloc := omit,
396 rest_octets := {
397 sel_params := {
398 presence := '0'B,
399 params := omit
400 },
401 pwr_offset := {
402 presence := '0'B,
403 offset := omit
404 },
405 gprs_ind := {
406 presence := '1'B,
407 ind := {
408 ra_colour := 0,
409 si13_pos := '0'B
410 }
411 },
412 s_presence := '0'B,
413 s := omit
414 }
415 },
Pau Espin Pedrol28652d82021-02-09 20:20:17 +0100416 si13 := {
417 rest_octets := {
418 presence := '1'B,
419 bcch_change_mark := ?,
420 si_change_field := '0000'B,
421 presence2 := '0'B,
422 si13_change_mark := omit,
423 gprs_ma := omit,
424 zero := '0'B, /* PBCCH not present in cell */
425 rac := 0,
426 spgc_ccch_sup := '0'B,
427 priority_access_thr := '110'B,
428 network_control_order := '00'B,
429 gprs_cell_opts := {
430 nmo := '01'B,
431 t3168 := '011'B,
432 t3192 := '010'B,
433 drx_timer_max := '011'B,
434 access_burst_type := '0'B,
435 control_ack_type := '1'B,
436 bs_cv_max := 15,
437 pan_presence := '1'B,
438 pan_dec := 1,
439 pan_inc := 1,
440 pan_max := '111'B,
441 ext_info_presence := ?,
442 ext_info_length := *,
443 ext_info := *
444 },
445 gprs_pwr_ctrl_params := {
446 alpha := 0,
447 t_avg_w := '10000'B,
448 t_avg_t := '10000'B,
449 pc_meas_chan := '0'B,
450 n_avg_i := '1000'B
451 }
452 }
453 },
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200454 si5 := {
455 bcch_freq_list := '10000000000000000000000000000000'O
456 },
457 si5bis := omit,
458 si5ter := {
459 extd_bcch_freq_list := '9E050020000000000000000000000000'O
460 },
461 si6 := {
462 cell_id := 0,
463 lai := {
464 mcc_mnc := '001F01'H,
465 lac := 1
466 },
467 cell_options := {
468 dtx_ext := '1'B,
469 pwrc := false,
470 dtx := '01'B,
471 radio_link_timeout := '0111'B
472 },
473 ncc_permitted := '11111111'B,
Vadim Yanitskiy348b07c2022-03-10 17:11:22 +0300474 rest_octets := {
475 pch_nch_info := ?,
476 vbs_vgcs_options := ?,
477 dtm_support := '0'B,
478 rac := omit,
479 max_lapdm := omit,
480 band_ind := '0'B /* C0 ARFCN indicates 1800 band */
481 }
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200482 }
483 };
484
485
486/* List of all the System Information received on all RSL ports */
487type record of SystemInformationConfig SystemInformationConfig_list;
488
489function f_sysinfo_dec_raw(inout SystemInformationConfig si, RSL_Message rsl)
490{
491 var RSL_IE_Body sysinfo_type_ie;
492 var RSL_IE_SysinfoType si_type;
493 var octetstring data;
494
495 if (f_rsl_find_ie(rsl, RSL_IE_SYSINFO_TYPE, sysinfo_type_ie) == false) {
496 setverdict(fail, "Cannot find RSL_IE_SYSINFO_TYPE");
497 mtc.stop;
498 }
499 si_type := sysinfo_type_ie.sysinfo_type;
500
501 if (rsl.msg_type == RSL_MT_BCCH_INFO) {
502 var RSL_IE_Body bcch_ie;
503 if (f_rsl_find_ie(rsl, RSL_IE_FULL_BCCH_INFO, bcch_ie)) {
504 data := bcch_ie.other.payload;
505 }
506 } else if (rsl.msg_type == RSL_MT_SACCH_FILL) {
507 var RSL_IE_Body l3_ie;
508 if (f_rsl_find_ie(rsl, RSL_IE_L3_INFO, l3_ie)) {
509 data := l3_ie.l3_info.payload;
510 }
511 } else {
512 setverdict(fail, "Don't understand this System Information message");
513 mtc.stop;
514 }
515
516 var boolean handled := false;
517
518 if (rsl.msg_type == RSL_MT_BCCH_INFO) {
519 handled := true;
520
521 if (si_type == RSL_SYSTEM_INFO_1) {
522 if (not isbound(data)) {
523 si.si1 := omit;
524 } else {
525 si.si1 := dec_SystemInformation(data).payload.si1;
526 }
527 } else if (si_type == RSL_SYSTEM_INFO_2) {
528 if (not isbound(data)) {
529 si.si2 := omit;
530 } else {
531 si.si2 := dec_SystemInformation(data).payload.si2;
532 }
533 } else if (si_type == RSL_SYSTEM_INFO_2bis) {
534 if (not isbound(data)) {
535 si.si2bis := omit;
536 } else {
537 si.si2bis := dec_SystemInformation(data).payload.si2bis;
538 }
539 } else if (si_type == RSL_SYSTEM_INFO_2ter) {
540 if (not isbound(data)) {
541 si.si2ter := omit;
542 } else {
543 si.si2ter := dec_SystemInformation(data).payload.si2ter;
544 }
545 } else if (si_type == RSL_SYSTEM_INFO_2quater) {
546 if (not isbound(data)) {
547 si.si2quater := {};
548 } else {
549 var SystemInformationType2quater decoded := dec_SystemInformation(data).payload.si2quater;
550 /* this is a *record* of SI2quaterRestOctets! (multiplexed) */
551 si.si2quater[decoded.rest_octets.si2quater_index] := decoded.rest_octets;
552 }
553 } else if (si_type == RSL_SYSTEM_INFO_3) {
554 if (not isbound(data)) {
555 si.si3 := omit;
556 } else {
557 si.si3 := dec_SystemInformation(data).payload.si3;
558 }
559 } else if (si_type == RSL_SYSTEM_INFO_4) {
560 if (not isbound(data)) {
561 si.si4 := omit;
562 } else {
563 si.si4 := dec_SystemInformation(data).payload.si4;
564 }
565 } else if (si_type == RSL_SYSTEM_INFO_13) {
566 if (not isbound(data)) {
567 si.si13 := omit;
568 } else {
Pau Espin Pedrol28652d82021-02-09 20:20:17 +0100569 si.si13 := dec_SystemInformation(data).payload.si13;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200570 }
571 } else {
572 handled := false;
573 }
574 } else if (rsl.msg_type == RSL_MT_SACCH_FILL) {
575 handled := true;
576
577 if (si_type == RSL_SYSTEM_INFO_5) {
578 if (not isbound(data)) {
579 si.si5 := omit;
580 } else {
581 si.si5 := dec_SystemInformation(data).payload.si5;
582 }
583 } else if (si_type == RSL_SYSTEM_INFO_5bis) {
584 if (not isbound(data)) {
585 si.si5bis := omit;
586 } else {
587 si.si5bis := dec_SystemInformation(data).payload.si5bis;
588 }
589 } else if (si_type == RSL_SYSTEM_INFO_5ter) {
590 if (not isbound(data)) {
591 si.si5ter := omit;
592 } else {
593 si.si5ter := dec_SystemInformation(data).payload.si5ter;
594 }
595 } else if (si_type == RSL_SYSTEM_INFO_6) {
596 if (not isbound(data)) {
597 si.si6 := omit;
598 } else {
599 si.si6 := dec_SystemInformation(data).payload.si6;
600 }
601 } else {
602 handled := false;
603 }
604 }
605
606 if (not handled) {
607 setverdict(fail, "Unexpected SI type in ", rsl.msg_type, " message: ", si_type);
608 }
609}
610
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +0100611friend function gen_l3_valid_payload(hexstring imsi := ''H) return octetstring {
612 var octetstring l3_payload;
613 if (lengthof(imsi) == 0) {
614 imsi := f_rnd_imsi('00101'H);
615 }
616 l3_payload := enc_PDU_ML3_MS_NW(valueof(ts_LU_REQ(LU_Type_IMSI_Attach, ts_MI_LV(ts_MI_IMSI(imsi)))));
617 return l3_payload;
618}
619
Harald Weltea4ca4462018-02-09 00:17:14 +0100620type component test_CT extends CTRL_Adapter_CT {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600621 /* Array of per-BTS/TRX state */
622 var BTS_State bts[NUM_BTS][NUM_TRX];
Harald Welte89ab1912018-02-23 18:56:29 +0100623 /* RSL common Channel Port (for RSL_Emulation) */
624 port RSL_CCHAN_PT RSL_CCHAN[NUM_BTS];
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600625 /* array of per-BTS/TRX RSL test ports */
626 port IPA_RSL_PT IPA_RSL[NUM_BTS][NUM_TRX];
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100627 port IPA_CODEC_PT IPA; /* Required for compilation of TC_rsl_unknown_unit_id() */
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +0200628 /* CTRL muxed over IPA in SCCPlite conn BSC<->MSC (or BSC-NAT) */
629 port IPA_CTRL_PT SCCPLITE_IPA_CTRL;
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +0200630 /* Configure/manage IPA_Emulation per-BTS/TRX port: */
631 port IPA_CFG_PT IPA_CFG_PORT[NUM_BTS][NUM_TRX];
Harald Weltea5d2ab22017-12-09 14:21:42 +0100632
Pau Espin Pedrol3c630532022-10-20 19:00:11 +0200633 var MGCP_Emulation_CT vc_MGCP[NUM_MGW];
634 var integer g_nr_mgw; /* number of vc_MGCP to initialize */
Harald Weltebc03c762018-02-12 18:09:38 +0100635 port TELNETasp_PT BSCVTY;
Daniel Willmann191e0d92018-01-17 12:44:35 +0100636
Daniel Willmannebdecc02020-08-12 15:30:17 +0200637 /* StatsD */
638 var StatsD_Checker_CT vc_STATSD;
639
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200640 var RAN_Adapter g_bssap[NUM_MSC];
Harald Welte47cd0e32020-08-21 12:39:11 +0200641 var BSSAP_LE_Adapter g_bssap_le;
Harald Weltea4ca4462018-02-09 00:17:14 +0100642 /* for old legacy-tests only */
643 port BSSAP_CODEC_PT BSSAP;
Harald Welte47cd0e32020-08-21 12:39:11 +0200644 port BSSAP_LE_CODEC_PT BSSAP_LE;
Harald Weltea4ca4462018-02-09 00:17:14 +0100645
Harald Welte21b46bd2017-12-17 19:46:32 +0100646 /* are we initialized yet */
Harald Welte28d943e2017-11-25 15:00:50 +0100647 var boolean g_initialized := false;
Harald Welte21b46bd2017-12-17 19:46:32 +0100648
Neels Hofmeyr38632aa2023-04-05 03:50:51 +0200649 var boolean g_handler_mode := false;
650
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200651 /* Osmux is enabled through VTY */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200652 var boolean g_osmux_enabled_cn := false;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +0200653 var boolean g_osmux_enabled_bts := false;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200654
Pau Espin Pedrolc675b612020-01-09 19:55:40 +0100655 /*Configure T(tias) over VTY, seconds */
656 var integer g_bsc_sccp_timer_ias := 7 * 60;
657 /*Configure T(tiar) over VTY, seconds */
658 var integer g_bsc_sccp_timer_iar := 15 * 60;
659
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +0200660 /* global test case guard timer (actual timeout value is set in f_init()) */
Harald Welteae026692017-12-09 01:03:01 +0100661 timer T_guard := 30.0;
662
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200663 var CounterNameValsList g_ctr_msc;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000664 var CounterNameValsList g_ctr_bsc;
665 var CounterNameValsList g_ctr_bts;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200666
667 /* System Information bytes as received during RSL startup, for each RSL[idx]. */
668 var SystemInformationConfig_list g_system_information := {};
Harald Welte28d943e2017-11-25 15:00:50 +0100669}
670
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200671type record of charstring phys_chan_configs;
Harald Welte28d943e2017-11-25 15:00:50 +0100672modulepar {
Harald Welte21b46bd2017-12-17 19:46:32 +0100673 /* IP address at which the BSC can be reached */
Harald Welte696ddb62017-12-08 14:01:43 +0100674 charstring mp_bsc_ip := "127.0.0.1";
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100675 /* port number to which to establish the IPA OML connections */
676 integer mp_bsc_oml_port := 3002;
Harald Welte21b46bd2017-12-17 19:46:32 +0100677 /* port number to which to establish the IPA RSL connections */
Harald Welte696ddb62017-12-08 14:01:43 +0100678 integer mp_bsc_rsl_port := 3003;
Harald Welte21b46bd2017-12-17 19:46:32 +0100679 /* port number to which to establish the IPA CTRL connection */
Harald Welte96c94412017-12-09 03:12:45 +0100680 integer mp_bsc_ctrl_port := 4249;
Daniel Willmannebdecc02020-08-12 15:30:17 +0200681 /* port number to which to listen for STATSD metrics */
682 integer mp_bsc_statsd_port := 8125;
Daniel Willmann191e0d92018-01-17 12:44:35 +0100683 /* IP address at which the test binds */
684 charstring mp_test_ip := "127.0.0.1";
Harald Weltea4ca4462018-02-09 00:17:14 +0100685
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200686 RAN_Configurations mp_bssap_cfg := {
687 {
688 transport := BSSAP_TRANSPORT_AoIP,
689 sccp_service_type := "mtp3_itu",
690 sctp_addr := { 23905, "127.0.0.1", 2905, "127.0.0.1" },
691 own_pc := 185, /* 0.23.1 first MSC emulation */
692 own_ssn := 254,
693 peer_pc := 187, /* 0.23.3 osmo-bsc */
694 peer_ssn := 254,
695 sio := '83'O,
Harald Weltecb0cc432020-06-21 19:42:31 +0200696 rctx := 1
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200697 },
698 {
699 transport := BSSAP_TRANSPORT_AoIP,
700 sccp_service_type := "mtp3_itu",
701 sctp_addr := { 23906, "127.0.0.1", 2905, "127.0.0.1" },
702 own_pc := 2, /* 0.0.2 second MSC emulation */
703 own_ssn := 254,
704 peer_pc := 187, /* 0.23.3 osmo-bsc */
705 peer_ssn := 254,
706 sio := '83'O,
707 rctx := 2
708 },
709 {
710 transport := BSSAP_TRANSPORT_AoIP,
711 sccp_service_type := "mtp3_itu",
712 sctp_addr := { 23907, "127.0.0.1", 2905, "127.0.0.1" },
713 own_pc := 3, /* 0.0.3 third MSC emulation */
714 own_ssn := 254,
715 peer_pc := 187, /* 0.23.3 osmo-bsc */
716 peer_ssn := 254,
717 sio := '83'O,
718 rctx := 3
719 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100720 };
Pau Espin Pedrol58cf6822019-05-28 18:11:33 +0200721
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200722 /* Must match per BTS config in osmo-bsc.cfg */
723 phys_chan_configs phys_chan_config := {
724 "CCCH+SDCCH4+CBCH",
725 "TCH/F",
726 "TCH/F",
727 "TCH/F",
728 "TCH/F",
Vadim Yanitskiy343c9eb2021-07-16 18:36:01 +0600729 "TCH/H",
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200730 "PDCH",
731 "PDCH"
732 };
733
Harald Welte47cd0e32020-08-21 12:39:11 +0200734 BSSAP_LE_Configuration mp_bssap_le_cfg := {
735 sccp_service_type := "mtp3_itu",
736 sctp_addr := { 23908, "127.0.0.1", 2905, "127.0.0.1" },
Neels Hofmeyrac086c12020-09-18 23:46:42 +0200737 own_pc := 190, /* 0.23.6 SMLC emulation */
Harald Welte47cd0e32020-08-21 12:39:11 +0200738 own_ssn := 252, /* SMLC side SSN */
739 peer_pc := 187, /* 0.23.3 osmo-bsc */
740 peer_ssn := 250, /* BSC side SSN */
741 sio := '83'O,
742 rctx := 6
743 };
Neels Hofmeyrcfe44062020-10-15 02:28:08 +0200744 boolean mp_enable_lcs_tests := true;
Harald Welte47cd0e32020-08-21 12:39:11 +0200745
Pau Espin Pedrol8f30ccd2019-11-01 17:30:57 +0100746 /* Value set in osmo-bsc.cfg "ms max power" */
747 uint8_t mp_exp_ms_power_level := 7;
Vadim Yanitskiy6e068012022-02-05 21:35:43 +0600748
749 /* Whether to check for memory leaks */
750 boolean mp_verify_talloc_count := true;
Harald Weltea4ca4462018-02-09 00:17:14 +0100751}
752
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200753friend function f_gen_test_hdlr_pars(integer bssap_idx := 0) return TestHdlrParams {
Philipp Maier48604732018-10-09 15:00:37 +0200754
755 var TestHdlrParams pars := valueof(t_def_TestHdlrPars);
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200756 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier48604732018-10-09 15:00:37 +0200757 pars.aoip := true;
758 } else {
759 pars.aoip := false;
760 }
Pau Espin Pedrol8f30ccd2019-11-01 17:30:57 +0100761 pars.exp_ms_power_level := mp_exp_ms_power_level;
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200762 pars.mscpool.bssap_idx := bssap_idx;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600763 pars.expect_tsc := c_BtsParams[0].tsc;
Vadim Yanitskiy96bb9cb2021-12-10 21:14:15 +0300764 pars.imsi := f_rnd_imsi('00101'H);
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +0100765 pars.imei := f_rnd_imei('00101'H);
Vadim Yanitskiy96bb9cb2021-12-10 21:14:15 +0300766
767 log(testcasename(), ": using IMSI ", pars.imsi);
Neels Hofmeyrb5b7a6e2021-06-04 19:03:45 +0200768
Philipp Maier48604732018-10-09 15:00:37 +0200769 return pars;
770}
771
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200772/* Convenience functions for rate counters using g_ctr_msc. */
773
774private function f_ctrs_msc_init(integer mscs_count := NUM_MSC, CounterNameVals counternames := counternames_msc_mscpool) runs on test_CT {
775 g_ctr_msc := f_counter_name_vals_get_n(IPA_CTRL, "msc", mscs_count, counternames);
776 log("initial msc rate counters: ", g_ctr_msc);
777}
778
779private function f_ctrs_msc_add(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
Neels Hofmeyr9656e922020-06-30 01:27:01 +0200780 f_counter_name_vals_list_add(g_ctr_msc, msc_nr, countername, val);
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200781}
782
783/* f_ctrs_msc_init();
784 * f_do_thing(on_msc := 0);
785 * f_do_thing(on_msc := 0);
786 * f_do_other(on_msc := 1);
787 * f_ctrs_msc_add(0, "thing", 2);
788 * f_ctrs_msc_add(1, "other");
789 * f_ctrs_msc_verify();
790 */
791private function f_ctrs_msc_verify() runs on test_CT {
792 log("verifying msc rate counters: ", g_ctr_msc);
793 f_counter_name_vals_expect_n(IPA_CTRL, "msc", g_ctr_msc);
794}
795
796/* convenience: f_ctrs_msc_add() and f_ctrs_msc_verify() in one call.
797 * f_ctrs_msc_init();
798 * f_do_thing(on_msc := 0);
799 * f_do_thing(on_msc := 0);
800 * f_do_thing(on_msc := 0);
801 * f_ctrs_msc_expect(0, "thing", 3);
802 */
803private function f_ctrs_msc_expect(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
804 f_ctrs_msc_add(msc_nr, countername, val);
805 f_ctrs_msc_verify();
806}
807
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000808/* Convenience functions for rate counters using g_ctr_bts, always also including g_ctr_bsc. */
809
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100810private function f_ctrs_bts_init(integer bts_count := NUM_BTS, CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000811 g_ctr_bts := f_counter_name_vals_get_n(IPA_CTRL, "bts", bts_count, counternames);
Neels Hofmeyr4dec8cc2021-11-29 15:59:44 +0100812 log("initial bts rate counters: ", g_ctr_bts);
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100813}
814
815function f_ctrs_bsc_and_bts_init(integer bts_count := NUM_BTS, CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
816 f_ctrs_bts_init(bts_count, counternames);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000817 f_ctrs_bsc_init(counternames);
818}
819
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100820private function f_ctrs_bsc_and_bts_handover_init(integer bts_count := NUM_BTS) runs on test_CT {
821 var CounterNameVals bts_names := counternames_bsc_bts_handover & counternames_bts_handover;
Neels Hofmeyr4dec8cc2021-11-29 15:59:44 +0100822 f_ctrs_bts_init(bts_count, bts_names);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100823 f_ctrs_bsc_init(counternames_bsc_bts_handover);
824}
825
826private function f_ctrs_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000827 f_counter_name_vals_list_add(g_ctr_bts, bts_nr, countername, val);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100828}
829
830private function f_ctrs_bsc_and_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
831 f_ctrs_bts_add(bts_nr, countername, val);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000832 f_ctrs_bsc_add(countername, val);
833}
834
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100835function f_ctrs_bts_verify() runs on test_CT {
836 f_counter_name_vals_expect_n(IPA_CTRL, "bts", g_ctr_bts);
837}
838
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000839/* f_ctrs_bsc_and_bts_init();
840 * f_do_thing(on_bts := 0);
841 * f_do_thing(on_bts := 0);
842 * f_do_other(on_bts := 1);
843 * f_ctrs_bsc_and_bts_add(0, "thing", 2);
844 * f_ctrs_bsc_and_bts_add(1, "other");
845 * f_ctrs_bsc_and_bts_verify();
846 */
847private function f_ctrs_bsc_and_bts_verify() runs on test_CT {
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100848 f_ctrs_bts_verify();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000849 f_ctrs_bsc_verify();
850}
851
852/* convenience: f_ctrs_bsc_and_bts_add() and f_ctrs_bsc_and_bts_verify() in one call.
853 * f_ctrs_bsc_and_bts_init();
854 * f_do_thing(on_bts := 0);
855 * f_do_thing(on_bts := 0);
856 * f_do_thing(on_bts := 0);
857 * f_ctrs_bsc_and_bts_expect(0, "thing", 3);
858 */
859private function f_ctrs_bsc_and_bts_expect(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
860 f_ctrs_bsc_and_bts_add(bts_nr, countername, val);
861 f_ctrs_bsc_and_bts_verify();
862}
863
864
865/* Convenience functions for rate counters using g_ctr_bsc. */
866
867private function f_ctrs_bsc_init(CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
868 g_ctr_bsc := f_counter_name_vals_get_n(IPA_CTRL, "bsc", 1, counternames);
869 log("initial bsc rate counters: ", g_ctr_bsc);
870}
871
872private function f_ctrs_bsc_add(charstring countername, integer val := 1) runs on test_CT {
873 f_counter_name_vals_list_add(g_ctr_bsc, 0, countername, val);
874}
875
876/* f_ctrs_bsc_init();
877 * f_do_thing();
878 * f_do_thing();
879 * f_do_other();
880 * f_ctrs_bsc_add("thing", 2);
881 * f_ctrs_bsc_add("other");
882 * f_ctrs_bsc_verify();
883 */
884private function f_ctrs_bsc_verify() runs on test_CT {
885 f_counter_name_vals_expect_n(IPA_CTRL, "bsc", g_ctr_bsc);
886}
887
888/* convenience: f_ctrs_bsc_add() and f_ctrs_bsc_verify() in one call.
889 * f_ctrs_bsc_init();
890 * f_do_thing();
891 * f_ctrs_bsc_expect("thing", 1);
892 */
893private function f_ctrs_bsc_expect(charstring countername, integer val := 1) runs on test_CT {
894 f_ctrs_bsc_add(countername, val);
895 f_ctrs_bsc_verify();
896}
897
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200898
Oliver Smith39f53072022-10-27 14:44:04 +0200899friend function f_shutdown_helper(boolean ho := false) runs on test_CT {
Neels Hofmeyr18997492021-12-13 17:30:35 +0100900 /* Run the subscr and conn leak test only when the VTY is initialized */
Vadim Yanitskiy6e068012022-02-05 21:35:43 +0600901 if (BSCVTY.checkstate("Mapped") and mp_verify_talloc_count) {
Neels Hofmeyr18997492021-12-13 17:30:35 +0100902 f_verify_talloc_count(BSCVTY, {"struct bsc_subscr", "struct gsm_subscriber_connection"});
903 }
904
Oliver Smith39f53072022-10-27 14:44:04 +0200905 /* Reset handover related configuration */
906 if (ho) {
907 f_bts_0_cfg(BSCVTY,
908 {"no neighbors",
909 "neighbor-list mode manual-si5",
910 "neighbor-list add arfcn 100",
911 "neighbor-list add arfcn 200",
912 "si5 neighbor-list add arfcn 10",
913 "si5 neighbor-list add arfcn 20",
914 "handover algorithm 1"});
915 }
916
Daniel Willmann637ef6c2018-07-25 10:49:09 +0200917 all component.stop;
Philipp Maier282ca4b2018-02-27 17:17:00 +0100918 setverdict(pass);
Daniel Willmannafce8662018-07-06 23:11:32 +0200919 mtc.stop;
Philipp Maier282ca4b2018-02-27 17:17:00 +0100920}
921
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200922private function f_legacy_bssap_reset(integer bssap_idx := 0) runs on test_CT {
Harald Weltea4ca4462018-02-09 00:17:14 +0100923 var BSSAP_N_UNITDATA_ind ud_ind;
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200924 var boolean reset_received := false;
Harald Weltea4ca4462018-02-09 00:17:14 +0100925 timer T := 5.0;
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200926 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[bssap_idx].sccp_addr_peer, g_bssap[bssap_idx].sccp_addr_own,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200927 ts_BSSMAP_Reset(0, g_osmux_enabled_cn)));
Harald Weltea4ca4462018-02-09 00:17:14 +0100928 T.start;
929 alt {
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200930 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(g_bssap[bssap_idx].sccp_addr_own, g_bssap[bssap_idx].sccp_addr_peer,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200931 tr_BSSMAP_ResetAck(g_osmux_enabled_cn))) {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200932 log("BSSMAP: Received RESET-ACK in response to RESET, we're ready to go!");
Harald Weltea4ca4462018-02-09 00:17:14 +0100933 }
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200934 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) -> value ud_ind {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200935 log("BSSMAP: Respoding to inbound RESET with RESET-ACK");
Harald Weltea4ca4462018-02-09 00:17:14 +0100936 BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200937 ts_BSSMAP_ResetAck(g_osmux_enabled_cn)));
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200938 reset_received := true;
Harald Weltea4ca4462018-02-09 00:17:14 +0100939 repeat;
940 }
941 [] BSSAP.receive { repeat; }
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200942 [] T.timeout {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200943 log("BSSMAP: Timeout waiting for RESET-ACK after sending RESET");
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200944 /* If we received a RESET after ours was sent, it
945 may be a race condition where the other peer beacame
946 available after we sent it, but we are in a desired
947 state anyway, so go forward. */
948 if (not reset_received) {
949 setverdict(fail);
950 }
951 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100952 }
Harald Welte28d943e2017-11-25 15:00:50 +0100953}
954
Harald Welteae026692017-12-09 01:03:01 +0100955type record IPA_Client {
Harald Welte21b46bd2017-12-17 19:46:32 +0100956 /* IPA Emulation component reference */
Harald Welteae026692017-12-09 01:03:01 +0100957 IPA_Emulation_CT vc_IPA,
Harald Welte21b46bd2017-12-17 19:46:32 +0100958 /* Unit-ID and other CCM parameters to use for IPA client emulation */
Harald Welteae026692017-12-09 01:03:01 +0100959 IPA_CCM_Parameters ccm_pars,
Harald Welte21b46bd2017-12-17 19:46:32 +0100960 /* String identifier for this IPA Client */
Harald Welte624f9632017-12-16 19:26:04 +0100961 charstring id,
Harald Welte21b46bd2017-12-17 19:46:32 +0100962 /* Associated RSL Emulation Component (if any). Only used in "Handler mode" */
Harald Welte624f9632017-12-16 19:26:04 +0100963 RSL_Emulation_CT vc_RSL optional
Harald Welte28d943e2017-11-25 15:00:50 +0100964}
965
Harald Welte21b46bd2017-12-17 19:46:32 +0100966/*! Start the IPA/RSL related bits for one IPA_Client.
967 * \param clnt IPA_Client for which to establish
968 * \param bsc_host IP address / hostname of the BSC
969 * \param bsc_port TCP port number of the BSC
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600970 * \param idx BTS/TRX index values
Harald Welte21b46bd2017-12-17 19:46:32 +0100971 * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600972function f_ipa_rsl_start(inout IPA_Client clnt, charstring bsc_host, PortNumber bsc_port,
973 BtsTrxIdx idx := {0, 0}, boolean handler_mode := false)
Harald Welte28d943e2017-11-25 15:00:50 +0100974runs on test_CT {
Harald Welteae026692017-12-09 01:03:01 +0100975 timer T := 10.0;
976
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600977 clnt.id := "IPA-BTS" & int2str(idx.bts) & "-TRX" & int2str(idx.trx) & "-RSL";
Harald Welte71389132021-12-09 21:58:18 +0100978 clnt.vc_IPA := IPA_Emulation_CT.create(clnt.id & "-IPA") alive;
Harald Welteae026692017-12-09 01:03:01 +0100979 clnt.ccm_pars := c_IPA_default_ccm_pars;
980 clnt.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600981 clnt.ccm_pars.unit_id := int2str(1234 + idx.bts) & "/0/" & int2str(idx.trx);
Harald Welte624f9632017-12-16 19:26:04 +0100982 if (handler_mode) {
Harald Welte71389132021-12-09 21:58:18 +0100983 clnt.vc_RSL := RSL_Emulation_CT.create(clnt.id & "-RSL") alive;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600984 connect(clnt.vc_RSL:CCHAN_PT, self:RSL_CCHAN[idx.bts]);
Harald Welte624f9632017-12-16 19:26:04 +0100985 }
Harald Welteae026692017-12-09 01:03:01 +0100986
987 map(clnt.vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +0200988 connect(clnt.vc_IPA:CFG_PORT, self:IPA_CFG_PORT[idx.bts][idx.trx]);
Harald Welte624f9632017-12-16 19:26:04 +0100989 if (handler_mode) {
990 connect(clnt.vc_IPA:IPA_RSL_PORT, clnt.vc_RSL:IPA_PT);
991 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600992 connect(clnt.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[idx.bts][idx.trx]);
Harald Welte624f9632017-12-16 19:26:04 +0100993 }
Harald Welteae026692017-12-09 01:03:01 +0100994
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600995 var integer local_port := 10000 + idx.bts * 1000 + idx.trx;
996 clnt.vc_IPA.start(IPA_Emulation.main_client(bsc_host, bsc_port, "", local_port, clnt.ccm_pars));
Harald Welte624f9632017-12-16 19:26:04 +0100997 if (handler_mode) {
998 clnt.vc_RSL.start(RSL_Emulation.main());
999 return;
1000 }
Harald Welteae026692017-12-09 01:03:01 +01001001
1002 /* wait for IPA RSL link to connect and send ID ACK */
1003 T.start;
1004 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001005 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK)) {
Harald Welteae026692017-12-09 01:03:01 +01001006 T.stop;
Harald Welteae026692017-12-09 01:03:01 +01001007 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001008 [] IPA_RSL[idx.bts][idx.trx].receive(ASP_IPA_Event:?) { repeat }
1009 [] IPA_RSL[idx.bts][idx.trx].receive { repeat }
Harald Welteae026692017-12-09 01:03:01 +01001010 [] T.timeout {
Harald Welte96c94412017-12-09 03:12:45 +01001011 setverdict(fail, "Timeout RSL waiting for ASP_IPA_EVENT_ID_ACK");
Daniel Willmannafce8662018-07-06 23:11:32 +02001012 mtc.stop;
Harald Welteae026692017-12-09 01:03:01 +01001013 }
1014 }
1015}
1016
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +02001017function f_ipa_rsl_stop(inout IPA_Client clnt, BtsTrxIdx idx := {0, 0}) runs on test_CT {
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001018 var IPL4asp_Types.Result res := {
1019 errorCode := omit,
1020 connId := omit,
1021 os_error_code := omit,
1022 os_error_text := omit
1023 };
1024
Harald Welte12055472018-03-17 20:10:08 +01001025 if (not isbound(clnt) or not isbound(clnt.vc_IPA)) {
1026 return;
1027 }
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001028
1029 /* Alive components don't finish sockets (TCP FIN) when they are
1030 * stopped. Hence, we need to manually call close() on them to make sure
1031 * the IUT knows about it. */
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +02001032 f_ipa_cfg_disconnect(IPA_CFG_PORT[idx.bts][idx.trx], res);
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001033
Harald Welte12055472018-03-17 20:10:08 +01001034 clnt.vc_IPA.stop;
1035 if (isbound(clnt.vc_RSL)) {
1036 clnt.vc_RSL.stop;
1037 }
1038}
1039
Harald Welte21b46bd2017-12-17 19:46:32 +01001040/* Wait for the OML connection to be brought up by the external osmo-bts-omldummy */
Harald Weltea5d2ab22017-12-09 14:21:42 +01001041function f_wait_oml(integer bts_nr, charstring status, float secs_max) runs on test_CT {
1042 timer T := secs_max;
1043 T.start;
1044 while (true) {
1045 if (f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-connection-state") == status) {
1046 T.stop;
Harald Weltebd868bd2017-12-10 18:28:40 +01001047 /* the 'degraded' state exists from OML connection time, and we have to wait
1048 * until all MO's are initialized */
1049 T.start(1.0);
1050 T.timeout;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001051 return;
1052 }
Harald Weltef0d6ac62017-12-17 17:02:21 +01001053 f_sleep(0.1);
Harald Weltea5d2ab22017-12-09 14:21:42 +01001054 if (not T.running) {
Max99253902018-11-16 17:57:39 +01001055 setverdict(fail, "Timeout waiting for BTS" & int2str(bts_nr) & " oml-connection-state ", status);
Daniel Willmannafce8662018-07-06 23:11:32 +02001056 mtc.stop;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001057 }
1058 }
1059}
1060
Harald Welte21b46bd2017-12-17 19:46:32 +01001061/* global altstep for global guard timer; also takes care of responding RESET witH RESET-ACK */
Harald Welteae026692017-12-09 01:03:01 +01001062altstep as_Tguard() runs on test_CT {
Harald Welte60e823a2017-12-10 14:10:59 +01001063 var BSSAP_N_UNITDATA_ind ud_ind;
Neels Hofmeyrcc3f76a2018-03-12 01:43:25 +01001064 [] T_guard.timeout {
1065 setverdict(fail, "Timeout of T_guard");
Daniel Willmannafce8662018-07-06 23:11:32 +02001066 mtc.stop;
Neels Hofmeyrcc3f76a2018-03-12 01:43:25 +01001067 }
Harald Welte60e823a2017-12-10 14:10:59 +01001068 /* always respond with RESET ACK to RESET */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001069 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) -> value ud_ind {
Harald Welte60e823a2017-12-10 14:10:59 +01001070 BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001071 ts_BSSMAP_ResetAck(g_osmux_enabled_cn)));
Harald Welte69c1c262017-12-13 21:02:08 +01001072 repeat;
Harald Welte60e823a2017-12-10 14:10:59 +01001073 }
Harald Welte28d943e2017-11-25 15:00:50 +01001074}
1075
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001076altstep no_bssmap_reset() runs on test_CT {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001077 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001078 setverdict(fail, "unexpected BSSMAP Reset");
Daniel Willmannafce8662018-07-06 23:11:32 +02001079 mtc.stop;
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001080 }
1081}
1082
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001083function f_init_mgcp(integer mgw_nr, charstring id) runs on test_CT {
1084 id := id & "-MGCP-" & int2str(mgw_nr);
Daniel Willmann191e0d92018-01-17 12:44:35 +01001085
1086 var MGCPOps ops := {
1087 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
1088 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
1089 };
1090 var MGCP_conn_parameters mgcp_pars := {
1091 callagent_ip := mp_bsc_ip,
Harald Welte9e4273e2018-01-29 22:01:22 +01001092 callagent_udp_port := -1,
Daniel Willmann191e0d92018-01-17 12:44:35 +01001093 mgw_ip := mp_test_ip,
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001094 mgw_udp_port := 2427 + mgw_nr,
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02001095 /* Enable it for SCCPlite, since we have 2 MGCP sockets towards MGW (UDP one +
Pau Espin Pedrol36eeaf72022-10-20 16:50:31 +02001096 the one with MGCP over IPA forwarded from MSC one) */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001097 multi_conn_mode := (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER)
Daniel Willmann191e0d92018-01-17 12:44:35 +01001098 };
1099
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001100 vc_MGCP[mgw_nr] := MGCP_Emulation_CT.create(id) alive;
1101 vc_MGCP[mgw_nr].start(MGCP_Emulation.main(ops, mgcp_pars, id));
Daniel Willmann191e0d92018-01-17 12:44:35 +01001102}
1103
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001104/* Enable or disable (current default) Osmux. When enabling, BSSMAP Reset
1105 * contains extra IE (OsmuxSupport) and osmo-bsc will handle AssignReq with
1106 * OsmuxCID IE.
1107 */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001108private function f_vty_allow_osmux_cn(boolean allow) runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001109 f_vty_enter_cfg_msc(BSCVTY, 0);
1110 if (allow) {
1111 f_vty_transceive(BSCVTY, "osmux on");
1112 } else {
1113 f_vty_transceive(BSCVTY, "osmux off");
1114 }
1115 f_vty_transceive(BSCVTY, "exit");
1116 f_vty_transceive(BSCVTY, "exit");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001117}
1118
Max2253c0b2018-11-06 19:28:05 +01001119function f_init_vty(charstring id := "foo") runs on test_CT {
Harald Welte94e0c342018-04-07 11:33:23 +02001120 if (BSCVTY.checkstate("Mapped")) {
1121 /* skip initialization if already executed once */
1122 return;
1123 }
Harald Weltebc03c762018-02-12 18:09:38 +01001124 map(self:BSCVTY, system:BSCVTY);
1125 f_vty_set_prompts(BSCVTY);
1126 f_vty_transceive(BSCVTY, "enable");
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01001127 f_cs7_inst_0_cfg(BSCVTY, {"sccp-timer ias " & int2str(g_bsc_sccp_timer_ias),
1128 "sccp-timer iar " & int2str(g_bsc_sccp_timer_iar)});
Harald Weltebc03c762018-02-12 18:09:38 +01001129}
1130
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +02001131friend function f_logp(TELNETasp_PT pt, charstring log_msg)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02001132{
1133 // log on TTCN3 log output
1134 log(log_msg);
1135 // log in stderr log
Neels Hofmeyr8bdafe52021-12-14 17:25:48 +01001136 if (pt.checkstate("Mapped")) {
1137 f_vty_transceive(pt, "logp lglobal notice TTCN3 f_logp(): " & log_msg);
1138 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02001139}
1140
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001141private function f_sysinfo_seen(integer rsl_idx, RSL_Message rsl) runs on test_CT
1142{
1143 if (rsl_idx >= lengthof(g_system_information)) {
1144 g_system_information[rsl_idx] := SystemInformationConfig_omit
1145 }
1146 f_sysinfo_dec_raw(g_system_information[rsl_idx], rsl);
1147}
1148
1149altstep as_catch_RSL_sysinfo(integer rsl_idx) runs on test_CT {
1150 var ASP_RSL_Unitdata rx_rsl_ud;
1151
1152 /* For handler_mode := false, receiving the RSL bootstrap messages directly on IPA_RSL */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001153 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD(tr_RSL_NO_BCCH_INFO)) -> value rx_rsl_ud {
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001154 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1155 repeat;
1156 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001157 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO)) -> value rx_rsl_ud {
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001158 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1159 repeat;
1160 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001161 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD(tr_RSL_NO_SACCH_FILL)) -> value rx_rsl_ud {
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001162 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1163 repeat;
1164 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001165 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD(tr_RSL_SACCH_FILL)) -> value rx_rsl_ud {
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001166 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1167 repeat;
1168 }
1169
1170 /* For handler_mode := true, receiving the RSL bootstrap messages via RSL_Emulation */
1171 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_BCCH_INFO)) -> value rx_rsl_ud {
1172 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1173 repeat;
1174 }
1175 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO)) -> value rx_rsl_ud {
1176 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1177 repeat;
1178 }
1179 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_SACCH_FILL)) -> value rx_rsl_ud {
1180 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1181 repeat;
1182 }
1183 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_SACCH_FILL)) -> value rx_rsl_ud {
1184 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1185 repeat;
1186 }
1187}
1188
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001189/* TODO: use BooleanList from COMMON/src/General_Types.ttcn */
1190private type record of boolean my_BooleanList;
1191
1192private function f_vty_msc_allow_attach(TELNETasp_PT pt, my_BooleanList allow_attach_list)
1193{
Neels Hofmeyr8f576712020-08-12 22:49:53 +00001194 var charstring config := f_vty_transceive_ret(pt, "show running-config");
1195
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001196 for (var integer msc_nr := 0; msc_nr < sizeof(allow_attach_list); msc_nr := msc_nr+1) {
Neels Hofmeyr8f576712020-08-12 22:49:53 +00001197 if (f_strstr(config, "\nmsc " & int2str(msc_nr) & "\n") < 0) {
1198 /* There is no 'msc N' for this msc_nr in the running config, so don't create an empty msc by
1199 * stepping into that config node. */
1200 log("msc ", msc_nr, " is not configured, skipping");
1201 continue;
1202 }
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001203 f_vty_enter_cfg_msc(pt, msc_nr);
1204 if (allow_attach_list[msc_nr]) {
1205 /* strict := false: ignore if osmo-bsc does not support this config option (latest build) */
1206 f_vty_transceive(pt, "allow-attach", strict := false);
1207 } else {
1208 f_vty_transceive(pt, "no allow-attach", strict := false);
1209 }
1210 f_vty_transceive(pt, "exit");
1211 f_vty_transceive(pt, "exit");
1212 }
1213}
1214
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02001215private function f_bssap_idx_init(integer bssap_idx) runs on test_CT {
1216 /* Call a function of our 'parent component' RAN_Adapter_CT to start the
1217 * MSC-side BSSAP emulation */
1218 if (g_handler_mode) {
1219 var RanOps ranops := MSC_RanOps;
1220 ranops.use_osmux := g_osmux_enabled_cn;
1221 f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", ranops);
1222 connect(self:SCCPLITE_IPA_CTRL, g_bssap[bssap_idx].vc_RAN:CTRL_CLIENT);
1223 f_ran_adapter_start(g_bssap[bssap_idx]);
1224 } else {
1225 f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", omit);
1226 connect(self:BSSAP, g_bssap[bssap_idx].vc_SCCP:SCCP_SP_PORT);
1227 f_ran_adapter_start(g_bssap[bssap_idx]);
1228 f_legacy_bssap_reset();
1229 }
1230}
1231
1232private function f_bssap_idx_disconnect(integer bssap_idx) runs on test_CT {
1233 f_ran_adapter_cleanup(g_bssap[bssap_idx]);
1234}
1235
Harald Welte21b46bd2017-12-17 19:46:32 +01001236/* global initialization function
1237 * \param nr_bts Number of BTSs we should start/bring up
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001238 * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false).
1239 * \param nr_msc Number of virtual MSCs to bring up to connect to osmo-bsc.
1240 */
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02001241function f_init(integer nr_bts := NUM_BTS, boolean handler_mode := false,
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001242 integer nr_msc := 1, integer nr_mgw := 1, float guard_timeout := 30.0) runs on test_CT {
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001243 var integer bssap_idx;
Harald Welte28d943e2017-11-25 15:00:50 +01001244
Harald Welteae026692017-12-09 01:03:01 +01001245 if (g_initialized) {
1246 return;
Harald Welte28d943e2017-11-25 15:00:50 +01001247 }
Harald Welteae026692017-12-09 01:03:01 +01001248 g_initialized := true;
1249
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +02001250 T_guard.start(guard_timeout);
Daniel Willmanne68f9272018-11-27 15:15:28 +01001251 activate(as_Tguard());
1252
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001253 f_init_vty("VirtMSC");
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02001254 f_vty_allow_osmux_cn(g_osmux_enabled_cn);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001255
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001256 var my_BooleanList allow_attach := { false, false, false };
Daniel Willmannebdecc02020-08-12 15:30:17 +02001257 f_init_statsd("VirtMSC", vc_STATSD, mp_test_ip, mp_bsc_statsd_port);
1258
Neels Hofmeyr9db8e0e2021-08-23 20:45:58 +02001259 /* Make sure each MSC's internal state is "DISCONNECTED" at first */
1260 for (bssap_idx := 0; bssap_idx < NUM_MSC; bssap_idx := bssap_idx+1) {
1261 f_vty_transceive(BSCVTY, "msc " & int2str(bssap_idx) & " bssmap reset", strict := false);
1262 }
1263
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02001264 g_handler_mode := handler_mode;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001265 for (bssap_idx := 0; bssap_idx < nr_msc; bssap_idx := bssap_idx+1) {
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001266 allow_attach[bssap_idx] := true;
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02001267 f_bssap_idx_init(bssap_idx);
Harald Welte67089ee2018-01-17 22:19:03 +01001268 }
Harald Welted5833a82018-05-27 16:52:56 +02001269
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02001270 if (mp_enable_lcs_tests) {
1271 if (handler_mode) {
1272 f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", SMLC_BssapLeOps);
1273 } else {
1274 f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", omit);
1275 connect(self:BSSAP_LE, g_bssap_le.vc_SCCP:SCCP_SP_PORT);
1276 }
1277 f_bssap_le_adapter_start(g_bssap_le);
Harald Welte47cd0e32020-08-21 12:39:11 +02001278 }
Harald Welte47cd0e32020-08-21 12:39:11 +02001279
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001280 /* start the test with exactly all enabled MSCs allowed to attach */
1281 f_vty_msc_allow_attach(BSCVTY, allow_attach);
1282
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01001283 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Harald Welte28d943e2017-11-25 15:00:50 +01001284
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001285 g_nr_mgw := nr_mgw;
1286 for (var integer i := 0; i < g_nr_mgw; i := i+1) {
1287 f_init_mgcp(i, "VirtMGW");
1288 }
Daniel Willmann191e0d92018-01-17 12:44:35 +01001289
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001290 for (var integer i := 0; i < nr_bts; i := i+1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001291 f_init_bts(i, c_BtsParams[i].trx_num, handler_mode);
Harald Welte696ddb62017-12-08 14:01:43 +01001292 }
Neels Hofmeyr9c0f9c82022-01-23 01:20:28 +01001293
1294 /* Emit a marker to appear in the SUT's own logging output */
1295 f_logp(BSCVTY, testcasename() & "() start");
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001296}
Harald Welte696ddb62017-12-08 14:01:43 +01001297
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001298function f_init_bts(integer bts_idx := 0,
1299 integer trx_num := NUM_TRX_CFG,
1300 boolean handler_mode := false)
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001301runs on test_CT {
1302 /* wait until osmo-bts-omldummy has respawned */
1303 f_wait_oml(bts_idx, "degraded", 5.0);
1304
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001305 /* start RSL connection(s) */
1306 for (var integer trx_idx := 0; trx_idx < trx_num; trx_idx := trx_idx + 1) {
1307 f_ipa_rsl_start(bts[bts_idx][trx_idx].rsl,
1308 mp_bsc_ip, mp_bsc_rsl_port,
1309 {bts_idx, trx_idx}, handler_mode);
1310 }
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001311 /* wait until BSC tells us "connected" */
1312 f_wait_oml(bts_idx, "connected", 5.0);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001313
1314 /* Set up BTS with VTY commands: */
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01001315 f_vty_enter_cfg_bts(BSCVTY, bts_idx);
1316 if (g_osmux_enabled_bts) {
1317 f_vty_transceive(BSCVTY, "osmux on");
1318 } else {
1319 f_vty_transceive(BSCVTY, "osmux off");
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001320 }
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01001321 f_vty_transceive(BSCVTY, "end");
Harald Welte28d943e2017-11-25 15:00:50 +01001322}
1323
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001324function f_init_bts_and_check_sysinfo(integer bts_idx := 0,
1325 integer trx_num := NUM_TRX_CFG,
1326 boolean handler_mode := false,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001327 template SystemInformationConfig expect_si)
1328runs on test_CT {
1329 var default sysinfo := activate(as_catch_RSL_sysinfo(bts_idx));
1330
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001331 f_init_bts(bts_idx, trx_num, handler_mode);
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001332
1333 /* Give some time to (hopefully/most likely) collect all system informations from RSL startup.
1334 * We could stop as soon as all expected SI are received, but then we might miss SI that we don't expect and
1335 * that might be sent afterwards. So rather give a generous timeout and be quite sure to catch all SI.
1336 */
1337 f_sleep(5.0);
1338 log("RSL ", bts_idx, " SYSTEM INFORMATION: ", g_system_information[bts_idx]);
1339
1340 deactivate(sysinfo);
1341
1342 if (match(g_system_information[bts_idx], expect_si)) {
1343 setverdict(pass);
1344 } else {
1345 log("RSL ", bts_idx, ": EXPECTED SI: ", expect_si);
1346 log("RSL ", bts_idx, ": GOT SI: ", g_system_information[bts_idx]);
1347 setverdict(fail, "received SI does not match expectations");
1348 return;
1349 }
1350}
1351
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001352/* expect to receive a RSL message matching a specified template on a given BTS / TRX */
1353function f_exp_ipa_rx(template (present) RSL_Message t_rx,
1354 BtsTrxIdx idx := {0, 0},
1355 float Tval := 2.0)
Harald Welteae026692017-12-09 01:03:01 +01001356runs on test_CT return RSL_Message {
1357 var ASP_RSL_Unitdata rx_rsl_ud;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001358 timer T := Tval;
Harald Welteae026692017-12-09 01:03:01 +01001359
1360 T.start;
1361 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001362 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
Harald Welteae026692017-12-09 01:03:01 +01001363 T.stop;
1364 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001365 [] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
Harald Welteb2917702017-12-10 15:48:52 +01001366 [] T.timeout {
1367 setverdict(fail, "Timeout expecting ", t_rx);
Daniel Willmannafce8662018-07-06 23:11:32 +02001368 mtc.stop;
Harald Welteb2917702017-12-10 15:48:52 +01001369 }
Harald Welteae026692017-12-09 01:03:01 +01001370 }
1371 return rx_rsl_ud.rsl;
1372}
1373
Harald Welte21b46bd2017-12-17 19:46:32 +01001374/* helper function to transmit RSL on a given BTS/stream */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001375function f_ipa_tx(template (value) RSL_Message t_tx,
1376 BtsTrxIdx idx := {0, 0},
1377 IpaStreamId sid := IPAC_PROTO_RSL_TRX0)
Harald Welteae026692017-12-09 01:03:01 +01001378runs on test_CT {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001379 IPA_RSL[idx.bts][idx.trx].send(ts_ASP_RSL_UD(t_tx, sid));
Harald Welteae026692017-12-09 01:03:01 +01001380}
1381
1382
Harald Welte4003d112017-12-09 22:35:39 +01001383/* verify we get a CHAN_ACT after CHAN RQD */
Harald Welteae026692017-12-09 01:03:01 +01001384testcase TC_chan_act_noreply() runs on test_CT {
1385 var BSSAP_N_UNITDATA_ind ud_ind;
Harald Welte930d0a72018-03-22 22:08:40 +01001386 var RSL_Message rsl_unused;
Harald Welte28d943e2017-11-25 15:00:50 +01001387
Harald Welte89d42e82017-12-17 16:42:41 +01001388 f_init(1);
Harald Welte28d943e2017-11-25 15:00:50 +01001389
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001390 f_ipa_tx(ts_RSL_CHAN_RQD('23'O, 23));
1391 rsl_unused := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001392 f_shutdown_helper();
Harald Welte28d943e2017-11-25 15:00:50 +01001393}
1394
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001395const CounterNameVals counternames_bts_chreq := {
1396 { "chreq:total", 0 },
1397 { "chreq:attempted_emerg", 0 },
1398 { "chreq:attempted_call", 0 },
1399 { "chreq:attempted_location_upd", 0 },
1400 { "chreq:attempted_pag", 0 },
1401 { "chreq:attempted_pdch", 0 },
1402 { "chreq:attempted_other", 0 },
1403 { "chreq:attempted_unknown", 0 },
1404 { "chreq:successful", 0 },
1405 { "chreq:successful_emerg", 0 },
1406 { "chreq:successful_call", 0 },
1407 { "chreq:successful_location_upd", 0 },
1408 { "chreq:successful_pag", 0 },
1409 { "chreq:successful_pdch", 0 },
1410 { "chreq:successful_other", 0 },
1411 { "chreq:successful_unknown", 0 },
1412 { "chreq:no_channel", 0 },
1413 { "chreq:max_delay_exceeded", 0 }
1414};
1415
1416/* verify the "chreq:*" counters */
1417private function f_chan_act_counter(OCT1 ra, charstring chreq_ctr_suffix) runs on test_CT
1418{
1419 var GsmFrameNumber fn := 23;
1420
1421 f_logp(BSCVTY, "f_chan_act_counter(" & chreq_ctr_suffix & ")");
1422
1423 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001424 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn));
1425 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001426 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1427
1428 f_ctrs_bts_add(0, "chreq:total");
1429 f_ctrs_bts_add(0, "chreq:attempted_" & chreq_ctr_suffix);
1430 f_ctrs_bts_verify();
1431
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001432 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
1433 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001434
1435 f_ctrs_bts_add(0, "chreq:successful");
1436 f_ctrs_bts_add(0, "chreq:successful_" & chreq_ctr_suffix);
1437 f_ctrs_bts_verify();
1438
1439 /* test is done, release RSL Conn Fail Ind to clean up */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001440 f_ipa_tx(ts_RSL_CONN_FAIL_IND(chan_nr, RSL_ERR_RADIO_LINK_FAIL));
1441 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
1442 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001443 f_sleep(1.0);
1444}
1445
Harald Welte4003d112017-12-09 22:35:39 +01001446testcase TC_chan_act_counter() runs on test_CT {
1447 var BSSAP_N_UNITDATA_ind ud_ind;
1448 var integer chreq_total;
Harald Welte930d0a72018-03-22 22:08:40 +01001449 var RSL_Message rsl_unused;
Harald Welte4003d112017-12-09 22:35:39 +01001450
Harald Welte89d42e82017-12-17 16:42:41 +01001451 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01001452
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001453 f_vty_allow_emerg_bts(true, 0);
1454
1455 f_ctrs_bts_init(1, counternames_bts_chreq);
1456
1457 /* emergency call: RA & 0xe0 == 0xa0 --> CHREQ_T_EMERG_CALL */
1458 f_chan_act_counter('a3'O, "emerg");
1459
1460 /* voice TCH/H: RA & 0xf0 == 0x40 --> CHREQ_T_VOICE_CALL_TCH_H */
1461 f_chan_act_counter('43'O, "call");
1462
1463 /* LU: RA & 0xf0 == 0x00 --> CHREQ_T_LOCATION_UPD */
1464 f_chan_act_counter('03'O, "location_upd");
1465
1466 /* Paging: RA & 0xf0 == 0x20 --> CHREQ_T_PAG_R_TCH_F */
1467 f_chan_act_counter('23'O, "pag");
1468 /* Paging: RA & 0xf0 == 0x30 --> CHREQ_T_PAG_R_TCH_FH */
1469 f_chan_act_counter('33'O, "pag");
1470
1471 /* LU: RA & 0xfc == 0x78 --> CHREQ_T_PDCH_TWO_PHASE */
1472 /* no PCU, so PDCH not allowed. Skip this test for now. */
1473 /* f_chan_act_counter('7b'O, "pdch"); */
1474
1475 /* LU: RA & 0xf0 == 0x10 --> CHREQ_T_SDCCH */
1476 f_chan_act_counter('13'O, "other");
Harald Welte4003d112017-12-09 22:35:39 +01001477
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001478 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01001479}
1480
Harald Welteae026692017-12-09 01:03:01 +01001481/* CHAN RQD -> CHAN ACT -> CHAN ACT ACK -> RF CHAN REL */
Philipp Maier9c60a622020-07-09 15:08:46 +02001482private function f_TC_chan_act_ack_noest(OCT1 ra := '23'O) runs on test_CT {
Harald Welteae026692017-12-09 01:03:01 +01001483 var RSL_Message rx_rsl;
1484
Harald Welteae026692017-12-09 01:03:01 +01001485 /* Send CHAN RQD and wait for allocation; acknowledge it */
Philipp Maier9c60a622020-07-09 15:08:46 +02001486 var RslChannelNr chan_nr := f_chreq_act_ack(ra);
Harald Welteae026692017-12-09 01:03:01 +01001487
1488 /* expect BSC to disable the channel again if there's no RLL EST IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001489 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := T3101_MAX);
Harald Welteae026692017-12-09 01:03:01 +01001490
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001491 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001492}
1493
Philipp Maier9c60a622020-07-09 15:08:46 +02001494/* Normal variant */
1495testcase TC_chan_act_ack_noest() runs on test_CT {
Philipp Maieraf58db22020-08-12 17:24:40 +02001496 f_init(1);
Philipp Maier9c60a622020-07-09 15:08:46 +02001497 f_TC_chan_act_ack_noest();
1498}
1499
1500/* Emergency call variant */
1501testcase TC_chan_act_ack_noest_emerg() runs on test_CT {
1502 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
Philipp Maieraf58db22020-08-12 17:24:40 +02001503 f_init(1);
1504 f_vty_allow_emerg_bts(true, 0);
Philipp Maier9c60a622020-07-09 15:08:46 +02001505 f_TC_chan_act_ack_noest(ra := 'A5'O);
1506}
1507
Philipp Maier606f07d2020-08-12 17:21:58 +02001508/* Emergency call variant, but emergency calls are not allowed */
1509testcase TC_chan_rqd_emerg_deny() runs on test_CT {
1510 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
1511
1512 var RSL_Message rx_rsl;
1513 var GsmRrMessage rr;
1514
1515 f_init(1);
1516 f_vty_allow_emerg_bts(false, 0);
1517
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001518 IPA_RSL[0][0].clear;
1519 f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
Philipp Maier606f07d2020-08-12 17:21:58 +02001520
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001521 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
Philipp Maier606f07d2020-08-12 17:21:58 +02001522 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
1523 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1524 setverdict(pass);
1525 } else {
1526 setverdict(fail, "immediate assignment not rejected");
1527 }
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01001528
1529 f_shutdown_helper();
Philipp Maier606f07d2020-08-12 17:21:58 +02001530}
1531
Harald Welteae026692017-12-09 01:03:01 +01001532/* Test behavior if MSC never answers to CR */
1533testcase TC_chan_act_ack_est_ind_noreply() runs on test_CT {
Harald Weltef77aef62018-01-28 15:35:42 +01001534 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
1535 var IpaStreamId sid := IPAC_PROTO_RSL_TRX0;
Harald Welteae026692017-12-09 01:03:01 +01001536 var RSL_Message rx_rsl;
Harald Weltef77aef62018-01-28 15:35:42 +01001537 var ASP_RSL_Unitdata rx_rsl_ud;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001538 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welteae026692017-12-09 01:03:01 +01001539
Harald Welte89d42e82017-12-17 16:42:41 +01001540 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001541
1542 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001543 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001544
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001545 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welteae026692017-12-09 01:03:01 +01001546
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001547 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload)));
Harald Welteae026692017-12-09 01:03:01 +01001548
1549 /* expect BSC to disable the channel again if there's no response from MSC */
Harald Weltef77aef62018-01-28 15:35:42 +01001550 /* MS waits 20s (T3210) at LU; 10s (T3230) at CM SERV REQ and 5s (T3220) AT detach */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001551 f_expect_chan_rel(chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001552 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001553}
1554
1555/* Test behavior if MSC answers with CREF to CR */
1556testcase TC_chan_act_ack_est_ind_refused() runs on test_CT {
1557 var BSSAP_N_CONNECT_ind rx_c_ind;
1558 var RSL_Message rx_rsl;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001559 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welteae026692017-12-09 01:03:01 +01001560
Harald Welte89d42e82017-12-17 16:42:41 +01001561 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001562
1563 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001564 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001565
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001566 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welteae026692017-12-09 01:03:01 +01001567
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001568 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Harald Welteae026692017-12-09 01:03:01 +01001569 BSSAP.send(ts_BSSAP_DISC_req(rx_c_ind.connectionId, 0));
1570
1571 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001572 f_expect_chan_rel(chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001573 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001574}
1575
Harald Welte618ef642017-12-14 14:58:20 +01001576/* CHAN RQD -> CHAN ACT -> CHAN ACT NACK -> RF CHAN REL */
1577testcase TC_chan_act_nack() runs on test_CT {
1578 var RSL_Message rx_rsl;
1579 var integer chact_nack;
1580
Harald Welte89d42e82017-12-17 16:42:41 +01001581 f_init(1);
Harald Welte618ef642017-12-14 14:58:20 +01001582
1583 chact_nack := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack");
1584
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001585 f_ipa_tx(ts_RSL_CHAN_RQD('33'O, 33));
1586 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Harald Welte618ef642017-12-14 14:58:20 +01001587 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1588
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001589 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
Harald Welte618ef642017-12-14 14:58:20 +01001590
1591 /* wait for some time to hope the NACK arrives before the CTRL GET below */
1592 f_sleep(0.5);
1593
1594 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack", chact_nack+1);
1595
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001596 f_shutdown_helper();
Harald Welte618ef642017-12-14 14:58:20 +01001597}
1598
Harald Welte799c97b2017-12-14 17:50:30 +01001599/* Test for channel exhaustion due to RACH overload */
1600testcase TC_chan_exhaustion() runs on test_CT {
1601 var ASP_RSL_Unitdata rsl_ud;
1602 var integer i;
1603 var integer chreq_total, chreq_nochan;
1604
Harald Welte89d42e82017-12-17 16:42:41 +01001605 f_init(1);
Harald Welte799c97b2017-12-14 17:50:30 +01001606
1607 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
1608 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
1609
Neels Hofmeyr85fa37f2021-10-06 13:50:38 +02001610 /* GSM 44.018 Table 9.1.8.2:
Pau Espin Pedrolfe200d72018-12-10 12:41:04 +01001611 * RA = '33'O -> Establishment cause = 0011xxxx (MS dual rate capable and asks for "TCH/H or TCH/F").
1612 * With current setup, expect 4xSDCCH + 4xTCH/F + 1xTCH/H to succeed */
Philipp Maiercb6cc482018-03-26 13:08:00 +02001613 for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolfe200d72018-12-10 12:41:04 +01001614 var RslChannelNr chan_nr := f_chreq_act_ack('33'O, i);
Harald Welte799c97b2017-12-14 17:50:30 +01001615 }
1616
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001617 IPA_RSL[0][0].clear;
Harald Welte799c97b2017-12-14 17:50:30 +01001618
Harald Weltedd8cbf32018-01-28 12:07:52 +01001619 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001620 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
Harald Welte799c97b2017-12-14 17:50:30 +01001621
1622 /* now expect additional channel activations to fail */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001623 f_ipa_tx(ts_RSL_CHAN_RQD('42'O, 42));
Harald Welte799c97b2017-12-14 17:50:30 +01001624
1625 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001626 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV))) {
Harald Welte799c97b2017-12-14 17:50:30 +01001627 setverdict(fail, "Received CHAN ACT ACK without resources?!?");
1628 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001629 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) -> value rsl_ud {
Harald Welte799c97b2017-12-14 17:50:30 +01001630 var GsmRrMessage rr;
1631 /* match on IMM ASS REJ */
1632 rr := dec_GsmRrMessage(rsl_ud.rsl.ies[1].body.full_imm_ass_info.payload);
1633 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1634 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001635 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS+1);
Harald Welte799c97b2017-12-14 17:50:30 +01001636 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel",
1637 chreq_nochan+1);
1638 setverdict(pass);
1639 } else {
1640 repeat;
1641 }
1642 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001643 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte799c97b2017-12-14 17:50:30 +01001644 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001645 f_shutdown_helper();
Harald Welte799c97b2017-12-14 17:50:30 +01001646}
1647
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001648/* Test channel deactivation due to silence from MS */
1649testcase TC_chan_deact_silence() runs on test_CT {
1650 var RslChannelNr chan_nr;
1651
1652 f_init(1);
1653
1654 /* Request for a dedicated channel */
1655 chan_nr := f_chreq_act_ack('23'O);
1656
1657 /* Wait some time until the channel is released */
1658 f_sleep(2.0);
1659
1660 /* Expect CHANnel RELease */
1661 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001662 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001663 log("Received CHANnel RELease");
1664 setverdict(pass);
1665 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001666 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001667 /* See OS#3709, OsmoBSC should not send Immediate
1668 * Assignment Reject since a dedicated channel was
1669 * already allocated, and Immediate Assignment was
1670 * already sent. */
1671 setverdict(fail, "Unexpected Immediate Assignment!");
1672 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001673 [] IPA_RSL[0][0].receive {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001674 setverdict(fail, "Unexpected RSL message!");
1675 }
1676 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001677 f_shutdown_helper();
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001678}
1679
Harald Weltecfe2c962017-12-15 12:09:32 +01001680/***********************************************************************
1681 * Assignment Testing
1682 ***********************************************************************/
1683
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02001684/* Verify that the BSC refuses any BSSAP connection from the MSC (They are all BSC->MSC direction,
1685 * except for the inter-BSC handover, MT side) */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001686testcase TC_outbound_connect(integer bssap_idx := 0) runs on test_CT {
Harald Welte89d42e82017-12-17 16:42:41 +01001687 f_init(1);
Harald Weltecfe2c962017-12-15 12:09:32 +01001688
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001689 BSSAP.send(ts_BSSAP_CONNECT_req(g_bssap[bssap_idx].sccp_addr_peer, g_bssap[bssap_idx].sccp_addr_own,
1690 2342, ts_BSSMAP_AssignmentReq));
Harald Weltecfe2c962017-12-15 12:09:32 +01001691 BSSAP.receive(tr_BSSAP_DISC_ind(2342, ?, ?));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001692 f_shutdown_helper();
Harald Weltecfe2c962017-12-15 12:09:32 +01001693}
1694
Harald Welte16a4adf2017-12-14 18:54:01 +01001695/* Test behavior if MSC answers with CREF to CR */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001696testcase TC_assignment_cic_only(integer bssap_idx := 0) runs on test_CT {
Harald Welte16a4adf2017-12-14 18:54:01 +01001697 var BSSAP_N_CONNECT_ind rx_c_ind;
1698 var RSL_Message rx_rsl;
1699 var DchanTuple dt;
1700
Harald Welte89d42e82017-12-17 16:42:41 +01001701 f_init(1);
Harald Welte16a4adf2017-12-14 18:54:01 +01001702
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001703 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001704 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte17b27da2018-05-25 20:33:53 +02001705 /* send assignment without AoIP IEs */
1706 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(ts_BSSMAP_IE_CIC(0, 1))));
1707 } else {
Pau Espin Pedrol35609792023-01-03 16:56:59 +01001708 /* Send assignment without CIC in IPA case */
Harald Welte17b27da2018-05-25 20:33:53 +02001709 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
1710 valueof(ts_BSSMAP_IE_AoIP_TLA4('01020304'O, 2342));
1711 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(omit, tla)));
1712 }
Harald Welte16a4adf2017-12-14 18:54:01 +01001713 alt {
1714 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1715 setverdict(fail, "AoIP BSC cannot accept ASSIGNMENT without AoIP Transport IE");
1716 }
Harald Welte235ebf12017-12-15 14:18:16 +01001717 /* TODO: Actually expect GSM0808_CAUSE_REQ_A_IF_TYPE_NOT_SUPP */
Harald Welte16a4adf2017-12-14 18:54:01 +01001718 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1719 setverdict(pass);
1720 }
1721 [] BSSAP.receive { repeat; }
1722 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001723 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001724 f_shutdown_helper();
Harald Welte16a4adf2017-12-14 18:54:01 +01001725}
1726
Harald Welteed848512018-05-24 22:27:58 +02001727/* generate an assignment request for either AoIP or SCCPlite */
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001728function f_gen_ass_req(boolean osmux_enabled := false, integer bssap_idx := 0, charstring aoip_tla := "1.2.3.4") return PDU_BSSAP {
Harald Welteed848512018-05-24 22:27:58 +02001729 var PDU_BSSAP ass_cmd;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001730 var BSSMAP_IE_Osmo_OsmuxCID osmux_cid := valueof(ts_OsmuxCID(0));
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001731 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welteed848512018-05-24 22:27:58 +02001732 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001733 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001734 if (osmux_enabled) {
1735 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla, osmux_cid));
1736 } else {
1737 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla));
1738 }
Harald Welteed848512018-05-24 22:27:58 +02001739 } else {
1740 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Pau Espin Pedrol096d73d2019-06-06 12:49:17 +02001741 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(cic, omit));
Harald Welteed848512018-05-24 22:27:58 +02001742 }
1743 return ass_cmd;
1744}
1745
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02001746function f_gen_handover_req(integer bssap_idx := 0, charstring aoip_tla := "1.2.3.4",
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001747 template (value) BSSMAP_IE_CellIdentifier cell_id_source := ts_CellID_LAC_CI(1, 1),
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001748 template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit,
1749 template (omit) TestHdlrEncrParams enc := omit) return PDU_BSSAP {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001750 var PDU_BSSAP ho_req;
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001751
1752 var BSSMAP_IE_EncryptionInformation encryptionInformation :=
1753 valueof(ts_BSSMAP_IE_EncrInfo('0000000000000000'O,'01'O));
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03001754 var template (omit) BSSMAP_IE_ChosenEncryptionAlgorithm chosenEncryptionAlgorithm := omit;
1755 var template (omit) BSSMAP_IE_KC128 kc128 := omit;
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001756 if (ispresent(enc)) {
1757 var TestHdlrEncrParams v_enc := valueof(enc);
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01001758 encryptionInformation := valueof(ts_BSSMAP_IE_EncrInfo(v_enc.enc_key, v_enc.enc_alg_permitted));
1759 if (ispresent(v_enc.enc_alg_chosen)) {
1760 chosenEncryptionAlgorithm := valueof(
1761 ts_BSSMAP_IE_ChosenEncryptionAlgorithm(int2oct(enum2int(
1762 f_cipher_mode_bssmap_to_rsl(v_enc.enc_alg_chosen)), 1)));
1763 }
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001764 if (ispresent(v_enc.enc_kc128)) {
1765 kc128 := ts_BSSMAP_IE_Kc128(v_enc.enc_kc128);
1766 }
1767 }
1768
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001769 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001770 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001771 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001772 ho_req := valueof(ts_BSSMAP_HandoverRequest(omit, tla,
1773 cell_id_source := cell_id_source,
1774 oldToNewBSSIEs := oldToNewBSSIEs,
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001775 encryptionInformation := encryptionInformation,
1776 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
Neels Hofmeyr9fe13202022-03-04 00:05:43 +01001777 kC128 := kc128,
1778 /* on AoIP, allow "all" codecs (until we add more concise
1779 * tests) */
1780 codecList := ts_BSSMAP_IE_CodecList(
1781 {ts_CodecAMR_F, ts_CodecAMR_H,
1782 ts_CodecEFR, ts_CodecFR, ts_CodecHR})));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001783 } else {
1784 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001785 ho_req := valueof(ts_BSSMAP_HandoverRequest(cic, omit,
1786 cell_id_source := cell_id_source,
1787 oldToNewBSSIEs := oldToNewBSSIEs,
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001788 encryptionInformation := encryptionInformation,
1789 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
1790 kC128 := kc128));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001791 }
1792 return ho_req;
1793}
1794
Harald Welteed848512018-05-24 22:27:58 +02001795/* generate an assignment complete template for either AoIP or SCCPlite */
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001796function f_gen_exp_compl(integer bssap_idx := 0)
1797runs on MSC_ConnHdlr return template PDU_BSSAP {
Harald Welteed848512018-05-24 22:27:58 +02001798 var template PDU_BSSAP exp_compl;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001799 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001800 var template BSSMAP_IE_Osmo_OsmuxCID exp_osmux_cid := omit;
1801 if (g_pars.use_osmux_cn) {
1802 var template (present) INT1 exp_cid := ?;
1803 if (isbound(g_media.mgcp_conn[0].local_osmux_cid) and isbound(g_media.mgcp_conn[1].local_osmux_cid)) {
1804 exp_cid := (g_media.mgcp_conn[0].local_osmux_cid, g_media.mgcp_conn[1].local_osmux_cid);
1805 } else if (isbound(g_media.mgcp_conn[0].local_osmux_cid)) {
1806 exp_cid := g_media.mgcp_conn[0].local_osmux_cid;
1807 } else if (isbound(g_media.mgcp_conn[1].local_osmux_cid)) {
1808 exp_cid := g_media.mgcp_conn[1].local_osmux_cid;
1809 }
1810 exp_osmux_cid := tr_OsmuxCID(exp_cid);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001811 }
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001812 exp_compl := tr_BSSMAP_AssignmentComplete(omit, ?, exp_osmux_cid);
Harald Welteed848512018-05-24 22:27:58 +02001813 } else {
1814 /* CIC is optional "*" as the MSC allocated it */
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001815 exp_compl := tr_BSSMAP_AssignmentComplete(*, omit, omit);
Harald Welteed848512018-05-24 22:27:58 +02001816 }
1817 return exp_compl;
1818}
1819
Harald Welte235ebf12017-12-15 14:18:16 +01001820/* Run everything required up to sending a caller-specified assignment command and expect response */
1821function f_assignment_exp(PDU_BSSAP ass_cmd, template PDU_BSSAP exp, charstring fail_text)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001822runs on test_CT return DchanTuple {
Harald Welte235ebf12017-12-15 14:18:16 +01001823 var BSSAP_N_CONNECT_ind rx_c_ind;
1824 var RSL_Message rx_rsl;
1825 var DchanTuple dt;
1826
Harald Welte89d42e82017-12-17 16:42:41 +01001827 f_init(1);
Harald Welte235ebf12017-12-15 14:18:16 +01001828
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001829 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte235ebf12017-12-15 14:18:16 +01001830 /* send assignment without AoIP IEs */
1831 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
1832 alt {
1833 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1834 if (ischosen(exp.pdu.bssmap.assignmentComplete)) {
1835 setverdict(pass);
1836 } else {
1837 setverdict(fail, fail_text);
1838 }
1839 }
1840 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1841 if (ischosen(exp.pdu.bssmap.assignmentFailure)) {
1842 setverdict(pass);
1843 } else {
1844 setverdict(fail, fail_text);
1845 }
1846 }
1847 [] BSSAP.receive { repeat; }
1848 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001849 return dt;
Harald Welte235ebf12017-12-15 14:18:16 +01001850}
Oliver Smithdd002752023-02-21 13:35:00 +01001851
1852private function f_tc_assignment_csd(charstring id) runs on MSC_ConnHdlr {
1853 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Harald Welteed848512018-05-24 22:27:58 +02001854 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Oliver Smithdd002752023-02-21 13:35:00 +01001855
Harald Welte235ebf12017-12-15 14:18:16 +01001856 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
Oliver Smithdd002752023-02-21 13:35:00 +01001857 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecCSData}));
1858
1859 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := GSM0808_DATA_RATE_TRANSP_4k8;
1860
1861 f_establish_fully(ass_cmd, exp_compl);
1862 f_perform_clear();
1863}
1864testcase TC_assignment_csd() runs on test_CT {
1865 if (Misc_Helpers.f_osmo_repo_is("nightly")) { /* osmo-bsc > 1.10.0 */
1866 var MSC_ConnHdlr vc_conn;
1867 var TestHdlrParams pars := f_gen_test_hdlr_pars();
1868 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
1869
1870 f_init(1, true);
1871 f_sleep(1.0);
1872 vc_conn := f_start_handler(refers(f_tc_assignment_csd), pars);
1873 vc_conn.done;
1874 } else {
1875 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
1876 var PDU_BSSAP ass_cmd := f_gen_ass_req();
1877 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
1878 //exp_fail.pdu.bssmap.assignmentFailure.cause.causeValue := int2bit(enum2int(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_UNAVAIL), 7);
1879 var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for CSD");
1880 f_perform_clear_test_ct(dt);
1881 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001882 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001883}
1884
1885testcase TC_assignment_ctm() runs on test_CT {
1886 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02001887 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte235ebf12017-12-15 14:18:16 +01001888 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCTM);
1889 //exp_fail.pdu.bssmap.assignmentFailure.cause.causeValue := int2bit(enum2int(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_UNAVAIL), 7);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001890 var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for Speech+CTM");
1891 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001892 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001893}
1894
Harald Welte4003d112017-12-09 22:35:39 +01001895type record DchanTuple {
1896 integer sccp_conn_id,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001897 RslChannelNr rsl_chan_nr,
1898 BtsTrxIdx idx
Harald Weltea5d2ab22017-12-09 14:21:42 +01001899}
1900
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +02001901type record of DchanTuple DchanTuples;
1902
Harald Welted6939652017-12-13 21:02:46 +01001903/* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001904private function f_chreq_act_ack(OCT1 ra := '23'O,
1905 GsmFrameNumber fn := 23,
1906 BtsTrxIdx idx := {0, 0})
Harald Welted6939652017-12-13 21:02:46 +01001907runs on test_CT return RslChannelNr {
1908 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001909 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
1910 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Harald Welted6939652017-12-13 21:02:46 +01001911 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001912 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10), idx);
1913 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Harald Welted6939652017-12-13 21:02:46 +01001914 return chan_nr;
1915}
1916
Harald Welte4003d112017-12-09 22:35:39 +01001917/* helper function to establish a dedicated channel via BTS and MSC */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001918function f_est_dchan(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1919 BtsTrxIdx idx := {0, 0})
Harald Welte4003d112017-12-09 22:35:39 +01001920runs on test_CT return DchanTuple {
1921 var BSSAP_N_CONNECT_ind rx_c_ind;
Harald Welte4003d112017-12-09 22:35:39 +01001922 var DchanTuple dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001923
Harald Welte4003d112017-12-09 22:35:39 +01001924 /* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001925 dt.rsl_chan_nr := f_chreq_act_ack(ra, fn, idx);
Harald Welte4003d112017-12-09 22:35:39 +01001926
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001927 f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3), idx);
Harald Welte4003d112017-12-09 22:35:39 +01001928
1929 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1930 dt.sccp_conn_id := rx_c_ind.connectionId;
1931 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1932
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001933 dt.idx := idx;
Harald Welte4003d112017-12-09 22:35:39 +01001934 return dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001935}
1936
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001937/* Like f_est_dchan(), but for the first lchan of a dynamic timeslot: first ACK the deactivation of PDCH. */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001938function f_est_dchan_dyn(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1939 BtsTrxIdx idx := {0, 0})
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001940runs on test_CT return DchanTuple {
1941 var BSSAP_N_CONNECT_ind rx_c_ind;
1942 var DchanTuple dt;
1943
1944 /* Send CHAN RQD */
1945 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001946 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001947
1948 /* The dyn TS first deactivates PDCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001949 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), idx, Tval := T3101_MAX);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001950 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001951 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001952
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001953 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001954 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
1955
1956 /* Now activates the signalling channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001957 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, fn+10), idx);
1958 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001959
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001960 f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001961
1962 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1963 dt.sccp_conn_id := rx_c_ind.connectionId;
1964 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1965
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001966 dt.idx := idx;
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001967 return dt;
1968}
1969
Harald Welte641fcbe2018-06-14 10:58:35 +02001970/* expect RF CAN REL from BTS, acknowledge it and clear the MSC side */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001971private function f_exp_chan_rel_and_clear(DchanTuple dt)
1972runs on test_CT {
Harald Welte641fcbe2018-06-14 10:58:35 +02001973 var RSL_Message rx_rsl;
1974 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001975 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), dt.idx, Tval := T3101_MAX);
Harald Welte641fcbe2018-06-14 10:58:35 +02001976 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001977 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), dt.idx);
Harald Welte641fcbe2018-06-14 10:58:35 +02001978
1979 /* expect Clear Complete from BSC */
1980 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
1981
1982 /* MSC disconnects as instructed. */
1983 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
1984}
1985
Harald Welte4003d112017-12-09 22:35:39 +01001986/* Test behavior of channel release after unilateral RLL REL IND (DISC from MS) */
1987testcase TC_chan_rel_rll_rel_ind() runs on test_CT {
Neels Hofmeyr27f64362018-03-12 01:44:00 +01001988 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01001989 var DchanTuple dt;
Harald Welte96c94412017-12-09 03:12:45 +01001990
Harald Welte89d42e82017-12-17 16:42:41 +01001991 f_init(1);
Harald Welte96c94412017-12-09 03:12:45 +01001992
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001993 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01001994
1995 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001996 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Harald Welte4003d112017-12-09 22:35:39 +01001997
Neels Hofmeyr27f64362018-03-12 01:44:00 +01001998 /* expect Clear Request on MSC side */
1999 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
2000
2001 /* Instruct BSC to clear channel */
2002 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
2003 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2004
Harald Welte4003d112017-12-09 22:35:39 +01002005 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002006 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr27f64362018-03-12 01:44:00 +01002007
2008 /* wait for SCCP emulation to do its job */
2009 f_sleep(1.0);
Harald Welte4003d112017-12-09 22:35:39 +01002010
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002011 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002012}
2013
2014/* Test behavior of channel release after CONN FAIL IND from BTS */
2015testcase TC_chan_rel_conn_fail() runs on test_CT {
2016 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002017 var DchanTuple dt;
2018
Harald Welte89d42e82017-12-17 16:42:41 +01002019 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002020
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002021 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002022
Vadim Yanitskiy01d0a902022-12-14 22:41:42 +07002023 /* Sending CONN FAIL IND immediately may trigger a race condition.
2024 * Give the BSC some time to process a new SCCP connection (OS#5823). */
2025 f_sleep(0.2);
2026
Harald Welte4003d112017-12-09 22:35:39 +01002027 /* simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002028 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte4003d112017-12-09 22:35:39 +01002029 /* TODO: different cause values? */
2030
Harald Welte4003d112017-12-09 22:35:39 +01002031 /* expect Clear Request from BSC */
2032 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
2033
2034 /* Instruct BSC to clear channel */
2035 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
2036 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2037
Harald Welte6ff76ea2018-01-28 13:08:01 +01002038 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002039 f_exp_chan_rel_and_clear(dt);
Harald Welte4003d112017-12-09 22:35:39 +01002040
2041 /* wait for SCCP emulation to do its job */
2042 f_sleep(1.0);
2043
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002044 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002045}
2046
Harald Welte99f3ca02018-06-14 13:40:29 +02002047/* Test behavior of early CONN FAIL IND from BTS (before EST IND!) */
2048/* See also https://www.osmocom.org/issues/3182 */
2049testcase TC_early_conn_fail() runs on test_CT {
2050 var RSL_Message rx_rsl;
2051 var DchanTuple dt;
2052
2053 f_init(1);
2054
2055 /* BTS->BSC: Send CHAN RQD and wait for allocation; acknowledge it */
Harald Weltec46ea3c2020-10-10 18:46:12 +02002056 dt.rsl_chan_nr := f_chreq_act_ack(f_rnd_ra_cs(), 23);
Harald Welte99f3ca02018-06-14 13:40:29 +02002057
2058 /* BTS->BSC: simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002059 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02002060
2061 /* BTS->BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002062 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02002063
2064 /* BTS<-BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002065 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002066
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002067 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002068}
2069
2070/* Test behavior of late CONN FAIL IND from BTS (ater REL IND!) */
2071/* See also https://www.osmocom.org/issues/3182 */
2072testcase TC_late_conn_fail() runs on test_CT {
2073 var RSL_Message rx_rsl;
2074 var DchanTuple dt;
2075
2076 f_init(1);
2077
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002078 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte99f3ca02018-06-14 13:40:29 +02002079
2080 /* BSC<-MSC: Instruct BSC to clear connection */
2081 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(0)));
2082
2083 /* BTS->BSC: expect BSC to deactivate SACCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002084 rx_rsl := f_exp_ipa_rx(tr_RSL_DEACT_SACCH(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002085
2086 /* BTS->BSC: simulate a late CONN FAIL IND from BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002087 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02002088
2089 /* BTS<-BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002090 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02002091 /* BTS->BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002092 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002093
2094 /* BSC->MSC: expect Clear Complete from BSC */
2095 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
2096
2097 /* BSC<-MSC: MSC disconnects as requested. */
2098 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2099
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002100 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002101}
2102
Oliver Smithaf03bef2021-08-24 15:34:51 +02002103private function f_TC_stats_conn_fail(charstring id) runs on MSC_ConnHdlr {
2104 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
2105 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2106
2107 f_statsd_reset();
2108
Oliver Smith15890b42023-03-08 14:12:28 +01002109 /* Establish SDCCH (invalid DataIndicator for exp_fail) */
Oliver Smithaf03bef2021-08-24 15:34:51 +02002110 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
Oliver Smith15890b42023-03-08 14:12:28 +01002111 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := 'ff'O;
Oliver Smithaf03bef2021-08-24 15:34:51 +02002112 f_establish_fully(ass_cmd, exp_fail);
2113
2114 /* Expect stats to be 0 */
2115 var StatsDExpects expect := {
2116 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 0, max := 0},
2117 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 0, max := 0}
2118 };
2119 f_statsd_expect(expect);
2120
2121 /* Simulate CONN FAIL IND on SDCCH */
2122 RSL.send(ts_ASP_RSL_UD(
2123 ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL),
2124 IPAC_PROTO_RSL_TRX0));
2125
Neels Hofmeyr58be48a2021-09-07 18:39:21 +02002126 f_sleep(1.0);
2127
Oliver Smithaf03bef2021-08-24 15:34:51 +02002128 /* Expect stats to be 1 */
2129 expect := {
2130 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 1, max := 1},
2131 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 1, max := 1}
2132 };
2133 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002134 BSSAP.receive(tr_BSSMAP_ClearRequest);
2135 f_perform_clear();
Oliver Smithaf03bef2021-08-24 15:34:51 +02002136}
2137testcase TC_stats_conn_fail() runs on test_CT {
2138 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2139 var MSC_ConnHdlr vc_conn;
2140
2141 f_init(1, true);
2142 f_sleep(1.0);
2143
2144 vc_conn := f_start_handler(refers(f_TC_stats_conn_fail), pars);
2145 vc_conn.done;
2146
2147 f_shutdown_helper();
2148}
2149
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002150function f_expect_chan_rel(RslChannelNr rsl_chan_nr,
2151 BtsTrxIdx idx := {0, 0},
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002152 boolean expect_deact_sacch := true,
2153 boolean expect_rr_chan_rel := true,
2154 boolean expect_rll_rel_req := true,
Harald Welte99787102019-02-04 10:41:36 +01002155 boolean handle_rll_rel := true,
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002156 template CellSelIndValue expect_cells := omit,
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002157 template (present) RR_Cause expect_rr_cause := ?
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002158 ) runs on test_CT {
Harald Welte91d54a52018-01-28 15:35:07 +01002159
2160 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002161 var boolean got_deact_sacch := false;
2162 var boolean got_rr_chan_rel := false;
2163 var boolean got_rll_rel_req := false;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002164 var ASP_RSL_Unitdata ud;
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002165 var RSL_IE_Body l3_ie;
2166 var PDU_ML3_NW_MS l3;
2167 var RR_Cause got_cause;
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002168 log("f_expect_chan_rel() expecting: expect_deact_sacch=", expect_deact_sacch, " expect_rr_chan_rel=", expect_rr_chan_rel,
2169 " expect_rll_rel_req=", expect_rll_rel_req);
Harald Welte91d54a52018-01-28 15:35:07 +01002170 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002171 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_DEACT_SACCH(rsl_chan_nr))) {
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002172 got_deact_sacch := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002173 repeat;
2174 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002175 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_DATA_REQ(rsl_chan_nr, ?, decmatch tr_RRM_RR_RELEASE))) -> value ud {
Harald Welte99787102019-02-04 10:41:36 +01002176 got_rr_chan_rel := true;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002177
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002178 if (f_rsl_find_ie(ud.rsl, RSL_IE_L3_INFO, l3_ie) == false) {
2179 setverdict(fail, "cannot find L3");
2180 mtc.stop;
2181 }
2182 l3 := dec_PDU_ML3_NW_MS(l3_ie.l3_info.payload);
2183
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002184 if (not istemplatekind(expect_cells, "omit")) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002185 var CellSelIndValue cells := dec_CellSelIndValue(
2186 l3.msgs.rrm.channelRelease.cellSelectionIndicator.cellSelectionIndicatorValue);
2187
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002188 log("GOT RR CHANNEL RELEASE WITH CELLS: ", cells);
2189 if (match(cells, expect_cells)) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002190 setverdict(pass);
2191 } else {
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002192 log("EXPECTED CELLS: ", expect_cells);
2193 setverdict(fail, "Received cells list on RR Channel Release does not match expectations");
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002194 }
2195 }
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002196
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002197 int2enum(oct2int(l3.msgs.rrm.channelRelease.rRCause.valuePart), got_cause);
2198 log("GOT CAUSE CODE: ", l3.msgs.rrm.channelRelease.rRCause.valuePart, " = ", got_cause);
2199 if (match(got_cause, expect_rr_cause)) {
2200 setverdict(pass);
2201 } else {
2202 log("EXPECTED CAUSE CODE: ", expect_rr_cause);
2203 setverdict(fail, "Received RR Channel Release Cause code does not match expectations");
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002204 }
Harald Welte99787102019-02-04 10:41:36 +01002205 repeat;
2206 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002207 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_REL_REQ(rsl_chan_nr, ?))) {
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002208 got_rll_rel_req := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002209 /* FIXME: Why are we getting this for LinkID SACCH? */
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002210 if (handle_rll_rel) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002211 f_ipa_tx(ts_RSL_REL_CONF(rsl_chan_nr, main_dcch));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002212 }
Harald Welte91d54a52018-01-28 15:35:07 +01002213 repeat;
2214 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002215 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL))) {
Harald Welte91d54a52018-01-28 15:35:07 +01002216 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002217 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(rsl_chan_nr));
Harald Welte91d54a52018-01-28 15:35:07 +01002218 }
2219 /* ignore any user data */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002220 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeR(?))) {
Harald Welte91d54a52018-01-28 15:35:07 +01002221 repeat;
2222 }
2223 }
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002224
2225 log("f_expect_chan_rel() summary: got_deact_sacch=", got_deact_sacch, " got_rr_chan_rel=", got_rr_chan_rel,
2226 " got_rll_rel_req=", got_rll_rel_req);
2227
2228 if (expect_deact_sacch != got_deact_sacch) {
2229 setverdict(fail, "f_expect_chan_rel(): expect_deact_sacch=", expect_deact_sacch, " got_deact_sacch=", got_deact_sacch);
2230 }
2231 if (expect_rr_chan_rel != got_rr_chan_rel) {
2232 setverdict(fail, "f_expect_chan_rel(): expect_rr_chan_rel=", expect_rr_chan_rel, " got_rr_chan_rel=", got_rr_chan_rel);
2233 }
2234 if (expect_rll_rel_req != got_rll_rel_req) {
2235 setverdict(fail, "f_expect_chan_rel(): expect_rll_rel_req=", expect_rll_rel_req, " got_rll_rel_req=", got_rll_rel_req);
2236 }
Harald Welte91d54a52018-01-28 15:35:07 +01002237}
2238
Harald Welte4003d112017-12-09 22:35:39 +01002239/* Test behavior of channel release after hard Clear Command from MSC */
2240testcase TC_chan_rel_hard_clear() runs on test_CT {
2241 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002242 var DchanTuple dt;
Harald Welte4003d112017-12-09 22:35:39 +01002243
Harald Welte89d42e82017-12-17 16:42:41 +01002244 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002245
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002246 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002247
2248 /* Instruct BSC to clear channel */
2249 var BssmapCause cause := 0;
2250 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2251
2252 /* expect Clear Complete from BSC on A */
2253 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2254 /* release the SCCP connection */
2255 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2256 }
2257
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002258 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002259 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002260}
2261
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002262function f_TC_chan_rel_last_eutran_plmn_hard_clear(boolean tx_csfb_ind) runs on test_CT {
2263 var BSSAP_N_DATA_ind rx_di;
2264 var DchanTuple dt;
2265
2266 f_init(1);
2267
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002268 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002269 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2270 /* yet when generating the EUTRAN neigh list in RR CHannel Release) */
2271 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
2272
2273 /* Instruct BSC to clear channel */
2274 var BssmapCause cause := 0;
2275 if (tx_csfb_ind) {
2276 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2277 } else {
2278 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2279 }
2280
2281 /* expect Clear Complete from BSC on A */
2282 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2283 /* release the SCCP connection */
2284 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2285 }
2286
2287 /* 1 neighbor is added by default in osmo-bts.cfg and
2288 SystemInformationConfig_default, use that: */
2289 var template CellSelIndValue exp_cells := f_tr_rr_chan_rel_earfcns(1);
2290
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002291 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false, expect_cells := exp_cells);
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002292 f_shutdown_helper();
2293}
2294
2295/* Test behavior of RR Channel rRelease after Clear Command without CSFB indicator
2296 from MSC, previously receiving any CommonID containing the "Last Used E-UTRAN
2297 PLMN Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2298 EUTRAN neighbor list sent later on by BSC in RR Channel, so receiving CSFB
2299 Indicator or not shouldn't matter at all. */
2300testcase TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() runs on test_CT {
2301 f_TC_chan_rel_last_eutran_plmn_hard_clear(false);
2302}
2303
2304/* Test behavior of RR Channel rRelease after Clear Command with CSFB indicator from
2305 MSC, previously receiving any CommonID containing the "Last Used E-UTRAN PLMN
2306 Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2307 EUTRAN neighbor list sent later on by BSC in RR Channel. */
2308testcase TC_chan_rel_last_eutran_plmn_hard_clear_csfb() runs on test_CT {
2309 f_TC_chan_rel_last_eutran_plmn_hard_clear(true);
2310}
2311
2312/* Test behavior of RR Channel Release after Clear Command with CSFB indicator from
2313 MSC, without receiving any CommonID containing the "Last Used E-UTRAN PLMN
2314 Id". According to spec (TS 48.008 version 16.0.0 Release 16 "3.2.1.21") the
2315 CSFB Indicator should not be used anymore, and hence, there should be no
2316 EUTRAN neighbor list sent by BSC in RR Channel release since no CommonId with
2317 Last Used E-UTRAN PLMN Id" IE was sent for this conn. */
Harald Welte99787102019-02-04 10:41:36 +01002318testcase TC_chan_rel_hard_clear_csfb() runs on test_CT {
2319 var BSSAP_N_DATA_ind rx_di;
2320 var DchanTuple dt;
2321
2322 f_init(1);
2323
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002324 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte99787102019-02-04 10:41:36 +01002325
2326 /* Instruct BSC to clear channel */
2327 var BssmapCause cause := 0;
2328 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2329
2330 /* expect Clear Complete from BSC on A */
2331 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2332 /* release the SCCP connection */
2333 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2334 }
2335
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002336 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002337 f_shutdown_helper();
Harald Welte99787102019-02-04 10:41:36 +01002338}
2339
Harald Welted8c36cd2017-12-09 23:05:31 +01002340/* Test behavior of channel release after hard RLSD from MSC */
2341testcase TC_chan_rel_hard_rlsd() runs on test_CT {
Harald Welted8c36cd2017-12-09 23:05:31 +01002342 var DchanTuple dt;
Harald Welted8c36cd2017-12-09 23:05:31 +01002343
Harald Welte89d42e82017-12-17 16:42:41 +01002344 f_init(1);
Harald Welted8c36cd2017-12-09 23:05:31 +01002345
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002346 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welted8c36cd2017-12-09 23:05:31 +01002347
2348 /* release the SCCP connection */
2349 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2350
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002351 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002352 f_shutdown_helper();
Harald Welted8c36cd2017-12-09 23:05:31 +01002353}
2354
Harald Welte550daf92018-06-11 19:22:13 +02002355/* Test behavior of channel release after hard RLSD from MSC and MS is not responding to RLL REL REQ */
2356testcase TC_chan_rel_hard_rlsd_ms_dead() runs on test_CT {
2357 var DchanTuple dt;
2358
2359 f_init(1);
2360
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002361 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte550daf92018-06-11 19:22:13 +02002362
2363 /* release the SCCP connection */
2364 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2365
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002366 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002367 f_shutdown_helper();
Harald Welte550daf92018-06-11 19:22:13 +02002368}
2369
Harald Welte85804d42017-12-10 14:11:58 +01002370/* Test behavior of channel release after BSSMAP RESET from MSC */
2371testcase TC_chan_rel_a_reset() runs on test_CT {
Harald Welte85804d42017-12-10 14:11:58 +01002372 var DchanTuple dt;
Harald Welte85804d42017-12-10 14:11:58 +01002373
Harald Welte89d42e82017-12-17 16:42:41 +01002374 f_init(1);
Harald Welte85804d42017-12-10 14:11:58 +01002375
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002376 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte85804d42017-12-10 14:11:58 +01002377
2378 /* Clear the queue, it might still contain stuff like IMMEDIATE ASSIGN */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002379 IPA_RSL[0][0].clear;
Harald Welte85804d42017-12-10 14:11:58 +01002380
2381 /* perform BSSAP RESET, expect RESET ACK and DISC.ind on connection */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002382 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own, ts_BSSMAP_Reset(0, g_osmux_enabled_cn)));
Harald Welte85804d42017-12-10 14:11:58 +01002383 interleave {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002384 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(g_bssap[0].sccp_addr_own, g_bssap[0].sccp_addr_peer, tr_BSSMAP_ResetAck(g_osmux_enabled_cn))) { }
Harald Welte85804d42017-12-10 14:11:58 +01002385 [] BSSAP.receive(tr_BSSAP_DISC_ind(dt.sccp_conn_id, ?, ?)) { }
2386 }
2387
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002388 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002389 f_shutdown_helper();
Harald Welte85804d42017-12-10 14:11:58 +01002390}
2391
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002392/* Verify T(iar) triggers and releases the channel */
2393testcase TC_chan_rel_sccp_tiar_timeout() runs on test_CT {
2394 var DchanTuple dt;
2395
2396 /* Set T(iar) in BSC low enough that it will trigger before other side
2397 has time to keep alive with a T(ias). Keep recommended ratio of
2398 T(iar) >= T(ias)*2 */
2399 g_bsc_sccp_timer_ias := 2;
2400 g_bsc_sccp_timer_iar := 5;
2401
2402 f_init(1);
2403
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002404 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002405 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002406 f_shutdown_helper();
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002407}
2408
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002409private function f_tc_chan_rel_rr_cause(myBSSMAP_Cause clear_cmd_cause,
2410 template (present) RR_Cause expect_rr_cause)
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002411runs on test_CT
2412{
2413 var DchanTuple dt;
2414
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002415 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002416 var BssmapCause cause := 0;
2417 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(clear_cmd_cause))));
2418 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2419 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2420 }
2421
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002422 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false, expect_rr_cause := expect_rr_cause);
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002423}
2424
2425/* Test that Clear Command cause codes affect the RR Channel Release cause code */
2426testcase TC_chan_rel_rr_cause() runs on test_CT {
2427 f_init(1);
2428
2429 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_CALL_CONTROL, GSM48_RR_CAUSE_NORMAL);
2430 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_HANDOVER_SUCCESSFUL, GSM48_RR_CAUSE_NORMAL);
2431 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_PREEMPTION, GSM48_RR_CAUSE_PREMPTIVE_REL);
2432 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, GSM48_RR_CAUSE_PROT_ERROR_UNSPC);
2433 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
2434 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_EQUIPMENT_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
Vadim Yanitskiye18aebb2021-01-03 13:10:43 +01002435
2436 f_shutdown_helper();
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002437}
2438
Harald Welte5cd20ed2017-12-13 21:03:20 +01002439/* Test behavior if RSL EST IND for non-active channel */
2440testcase TC_rll_est_ind_inact_lchan() runs on test_CT {
2441 timer T := 2.0;
2442
Harald Welte89d42e82017-12-17 16:42:41 +01002443 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002444
Harald Welte5cd20ed2017-12-13 21:03:20 +01002445 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002446 var octetstring l3_payload := gen_l3_valid_payload();
2447 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002448
2449 T.start;
2450 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002451 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002452 setverdict(fail, "MSC received COMPL L3 for non-active lchan");
2453 }
2454 [] BSSAP.receive {}
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002455 [] IPA_RSL[0][0].receive {}
Harald Welte5cd20ed2017-12-13 21:03:20 +01002456 [] T.timeout {}
2457 }
2458
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002459 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002460}
2461
2462/* Test behavior if RSL EST IND for invalid SAPI */
2463testcase TC_rll_est_ind_inval_sapi1() runs on test_CT {
2464 var RslChannelNr chan_nr;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002465 var octetstring l3_payload;
Harald Welte5cd20ed2017-12-13 21:03:20 +01002466
Harald Welte89d42e82017-12-17 16:42:41 +01002467 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002468
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002469 chan_nr := f_chreq_act_ack();
2470 l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002471
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002472 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(1)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002473
2474 timer T := 2.0;
2475 T.start;
2476 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002477 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002478 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 1");
2479 }
2480 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002481 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002482 [] T.timeout {}
2483 }
2484
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002485 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002486}
2487
2488/* Test behavior if RSL EST IND for invalid SAPI */
2489testcase TC_rll_est_ind_inval_sapi3() runs on test_CT {
2490 timer T := 2.0;
2491
Harald Welte89d42e82017-12-17 16:42:41 +01002492 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002493
2494 var RslChannelNr chan_nr := f_chreq_act_ack();
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002495 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002496
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002497 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(3)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002498
2499 T.start;
2500 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002501 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002502 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 3");
2503 }
2504 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002505 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002506 [] T.timeout {}
2507 }
2508
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002509 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002510}
2511
2512/* Test behavior if RSL EST IND for invalid SACCH */
2513testcase TC_rll_est_ind_inval_sacch() runs on test_CT {
2514 timer T := 2.0;
2515
Harald Welte89d42e82017-12-17 16:42:41 +01002516 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002517
2518 var RslChannelNr chan_nr := f_chreq_act_ack();
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002519 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002520
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002521 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_SACCH(0)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002522
2523 T.start;
2524 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002525 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002526 setverdict(fail, "MSC received COMPL L3 for invalid Link SACCH");
2527 }
2528 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002529 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002530 [] T.timeout {}
2531 }
2532
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002533 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002534}
2535
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002536/* Verify DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
2537private function f_TC_tch_dlci_link_id_sapi(charstring id) runs on MSC_ConnHdlr {
2538 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
2539 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2540
2541 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
2542 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
2543
2544 f_establish_fully(ass_cmd, exp_compl);
2545
2546 /* SAPI0 has already been established by f_establish_fully(), establish SAPI3 */
2547 RSL.send(ts_RSL_EST_IND(g_chan_nr, ts_RslLinkID_SACCH(3), '0904'O));
2548 /* Expect BSSAP/DTAP on SAPI3 (DLCI IE) */
2549 BSSAP.receive(PDU_BSSAP:{
2550 discriminator := '1'B,
2551 spare := '0000000'B,
2552 dlci := 'C3'O,
2553 lengthIndicator := ?,
2554 pdu := { dtap := '0904'O }
2555 });
2556
2557 /* Send messages on DCCH/SAPI0 and ACCH/SAPI3 */
2558 for (var integer i := 0; i < 32; i := i + 1) {
2559 var octetstring l3 := '09'O & f_rnd_octstring(14);
2560 var template (value) RslLinkId link_id;
2561 var template (value) OCT1 dlci;
2562
2563 if (i mod 2 == 0) {
2564 /* SAPI0 on FACCH or SDCCH */
2565 link_id := ts_RslLinkID_DCCH(0);
2566 dlci := '80'O;
2567 } else {
2568 /* SAPI3 on SACCH */
2569 link_id := ts_RslLinkID_SACCH(3);
2570 dlci := 'C3'O;
2571 }
2572
2573 /* Send MO message: RSL -> BSSAP */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002574 f_mo_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002575 /* Send MT message: BSSAP -> RSL */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002576 f_mt_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002577 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002578 f_perform_clear();
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002579}
2580testcase TC_tch_dlci_link_id_sapi() runs on test_CT {
2581 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2582 var MSC_ConnHdlr vc_conn;
2583
2584 f_init(1, true);
2585 f_sleep(1.0);
2586
2587 vc_conn := f_start_handler(refers(f_TC_tch_dlci_link_id_sapi), pars);
2588 vc_conn.done;
2589
2590 f_shutdown_helper();
2591}
2592
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002593private function f_exp_sapi_n_reject(template (present) GsmSapi sapi := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002594 template (present) myBSSMAP_Cause cause := ?,
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002595 template (present) BIT2 cc := ?,
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002596 float T_val := 2.0)
2597runs on test_CT {
2598 var BSSAP_N_DATA_ind rx_di;
2599 timer T;
2600
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002601 var template (present) BSSMAP_IE_Cause tr_cause := tr_BSSMAP_IE_Cause(cause);
2602 var template (present) PDU_BSSAP tr_pdu := tr_BSSMAP_SAPInReject(sapi);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002603
2604 T.start(T_val);
2605 alt {
2606 [] BSSAP.receive(tr_BSSAP_DATA_ind(?, tr_pdu)) -> value rx_di {
2607 var BSSMAP_IE_Cause rx_cause := rx_di.userData.pdu.bssmap.sAPInReject.cause;
2608 if (not match(rx_cause, tr_cause)) {
2609 setverdict(fail, "Rx unexpected Cause IE: ",
2610 rx_cause, " vs expected ", tr_cause);
2611 }
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002612
2613 /* Who ever on the earth decided to define this field as two separate bits?!? */
2614 var BIT2 rx_cc := rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c2
2615 & rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c1;
2616 if (not match(rx_cc, cc)) {
2617 setverdict(fail, "Rx unexpected Control Channel type: ",
2618 rx_cc, " vs expected ", cc);
2619 }
2620
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002621 setverdict(pass);
2622 }
2623 [] BSSAP.receive(BSSAP_N_DATA_ind:?) -> value rx_di {
2624 setverdict(fail, "Rx unexpected BSSAP PDU: ", rx_di);
2625 }
2626 [] T.timeout {
2627 setverdict(fail, "Timeout waiting for BSSMAP SAPI N Reject");
2628 }
2629 }
2630}
2631
2632/* Check if we get SAPI N Reject on receipt of unexpected RLL RELease INDication */
2633testcase TC_rll_rel_ind_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002634 var RSL_Message rx_rsl;
2635 var DchanTuple dt;
2636
2637 f_init(1);
2638
2639 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002640 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002641
2642 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002643 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(gen_l3_valid_payload(), '03'O)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002644 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002645 rx_rsl := f_exp_ipa_rx(tr_RSL_EST_REQ(dt.rsl_chan_nr, tr_RslLinkID_DCCH(3)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002646
2647 /* MS sends unexpected RELease INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002648 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002649 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2650 f_exp_sapi_n_reject(3, GSM0808_CAUSE_MS_NOT_EQUIPPED);
2651
2652 /* Clean up the connection */
2653 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002654 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002655
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002656 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002657}
2658
2659/* Check if we get SAPI N Reject on receipt of unexpected RLL ERROR INDication */
2660testcase TC_rll_err_ind_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002661 var RSL_Message rx_rsl;
2662 var DchanTuple dt;
2663
2664 f_init(1);
2665
2666 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002667 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002668
2669 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002670 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(gen_l3_valid_payload(), '03'O)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002671 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002672 rx_rsl := f_exp_ipa_rx(tr_RSL_EST_REQ(dt.rsl_chan_nr, tr_RslLinkID_DCCH(3)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002673
2674 /* BTS sends unexpected ERROR INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002675 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002676 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2677 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED);
2678
2679 /* Clean up the connection */
2680 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002681 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002682
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002683 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002684}
2685
2686/* Check if we get SAPI N Reject due to a SAPI=3 link establishment timeout */
2687testcase TC_rll_timeout_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002688 var RSL_Message rx_rsl;
2689 var DchanTuple dt;
2690
2691 f_init(1);
2692
2693 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002694 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002695
2696 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002697 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(gen_l3_valid_payload(), '03'O)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002698 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002699 rx_rsl := f_exp_ipa_rx(tr_RSL_EST_REQ(dt.rsl_chan_nr, tr_RslLinkID_DCCH(3)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002700
2701 /* MS does not respond, so the link establishment timeout triggers SAPI N Reject */
2702 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, T_val := 8.0);
2703
2704 /* Clean up the connection */
2705 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002706 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002707
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002708 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002709}
2710
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002711/* Check DLCI CC (Control Channel type) bits in SAPI N Reject */
2712testcase TC_rll_sapi_n_reject_dlci_cc() runs on test_CT {
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002713 var RSL_Message rx_rsl;
2714 var DchanTuple dt;
2715
2716 f_init(1);
2717
2718 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002719 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002720
2721 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002722 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(gen_l3_valid_payload(), '03'O)));
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002723 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002724 rx_rsl := f_exp_ipa_rx(tr_RSL_EST_REQ(dt.rsl_chan_nr, tr_RslLinkID_DCCH(3)));
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002725
2726 /* MS sends unexpected ERROR INDication on DCCH/ACCH SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002727 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Pau Espin Pedrol121f27f2022-01-12 12:02:10 +01002728 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, '10'B);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002729
2730 /* Clean up the connection */
2731 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002732 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002733
2734 f_shutdown_helper();
2735}
2736
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002737testcase TC_si_default() runs on test_CT {
2738 f_init(0);
2739 f_init_bts_and_check_sysinfo(0, expect_si := SystemInformationConfig_default);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002740 f_shutdown_helper();
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002741}
Harald Welte4003d112017-12-09 22:35:39 +01002742
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002743/* We're testing SI2quater with lists of EARFCNs. Instead of just incrementing EARFCNs, also pick some from the edges of
2744 * the entire value range. This function provides the same EARFCN numbers for the same earfcn_index */
2745private function f_test_si2quater_earfcn_by_idx(integer earfcn_index) return uint16_t
2746{
2747 select (earfcn_index) {
2748 case (0) {
2749 /* E-ARFCN 111 is already added in the osmo-bsc.cfg */
2750 return 111;
2751 }
2752 case (1) {
2753 return 1;
2754 }
2755 case (2) {
2756 return 0;
2757 }
2758 case (3) {
2759 return 65535;
2760 }
2761 case else {
2762 return 23 * (earfcn_index - 3);
2763 }
2764 }
2765}
2766
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002767function f_test_si2quater(integer total_earfcns, template SystemInformationConfig expect_si,
2768 template CellSelIndValue expect_cells := omit) runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002769
2770 f_init(0);
2771
2772 /* E-ARFCN 111 is already added in the osmo-bsc.cfg, so only add more arfcns if total_earfcns > 1 */
2773 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002774 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2775 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002776 }
2777
2778 f_init_bts_and_check_sysinfo(0, expect_si := expect_si);
2779
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002780 if (not istemplatekind(expect_cells, "omit")) {
2781 /* Also check that RR Channel Release contains these EARFCNs.
2782 * (copied code from TC_chan_rel_hard_clear_csfb) */
2783 var BSSAP_N_DATA_ind rx_di;
2784 var DchanTuple dt;
2785
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002786 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Pau Espin Pedrold0046312021-04-19 16:35:58 +02002787 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2788 * yet when generating the EUTRAN neigh list in RR CHannel Release) */
2789 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002790
2791 /* Instruct BSC to clear channel */
2792 var BssmapCause cause := 0;
2793 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2794
2795 /* expect Clear Complete from BSC on A */
2796 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2797 /* release the SCCP connection */
2798 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2799 }
2800
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002801 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false, expect_cells := expect_cells);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002802 }
2803
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002804 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002805 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list del earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))});
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002806 }
2807}
2808
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002809private function f_tr_si2quater_earfcns(integer count) return template SI2quaterRestOctetsList
2810{
2811 var template SI2quaterRestOctetsList si2quater := {};
2812 var integer si2quater_count := (count + 2) / 3;
2813
2814 for (var integer i := 0; i < count; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002815 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002816 var integer index := i / 3;
2817 var integer earfcn_index := i mod 3;
2818 if (index >= lengthof(si2quater)) {
2819 si2quater[index] := tr_SI2quaterRestOctets_EUTRAN(index := index, count := si2quater_count - 1);
2820 }
2821 si2quater[index].rel_additions.rel5.rel6.rel7.rel8.prio_eutran_params_desc.desc.eutran_params_desc.desc.repeated_neigh_cells[0].cell_desc_list[earfcn_index] := tr_EUTRAN_CellDesc_default(e_arfcn := earfcn);
2822 }
2823
2824 return si2quater;
2825}
2826
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002827private function f_tr_rr_chan_rel_earfcns(integer count) return template CellSelIndValue
2828{
2829 var template CellSelIndValue_EUTRAN_Descrs cells := {};
2830
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002831 /* the lte neighbors must match the config & vty to pass this test */
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002832 for (var integer i := 0; i < count; i := i + 1) {
2833 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002834 cells[i] := tr_CellSelIndValue_EUTRAN_Descr(earfcn, '1'B, 3);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002835 }
2836
2837 return tr_CellSelIndValue_EUTRAN(cells);
2838}
2839
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002840private function f_tc_si2quater_n_earfcns(integer n) runs on test_CT
2841{
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002842 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrol8ab62e42020-12-18 16:19:11 +01002843 sic.si2quater := f_tr_si2quater_earfcns(n);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002844 var template CellSelIndValue cells := f_tr_rr_chan_rel_earfcns(n);
2845 f_test_si2quater(n, sic, cells);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002846}
2847
2848testcase TC_si2quater_2_earfcns() runs on test_CT {
2849 f_tc_si2quater_n_earfcns(2);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002850 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002851}
2852
2853testcase TC_si2quater_3_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002854 f_tc_si2quater_n_earfcns(3);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002855 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002856}
2857
2858testcase TC_si2quater_4_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002859 f_tc_si2quater_n_earfcns(4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002860 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002861}
2862
2863testcase TC_si2quater_5_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002864 f_tc_si2quater_n_earfcns(5);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002865 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002866}
2867
2868testcase TC_si2quater_6_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002869 f_tc_si2quater_n_earfcns(6);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002870 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002871}
2872
2873testcase TC_si2quater_12_earfcns() runs on test_CT {
2874 f_tc_si2quater_n_earfcns(12);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002875 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002876}
2877
2878testcase TC_si2quater_23_earfcns() runs on test_CT {
2879 f_tc_si2quater_n_earfcns(23);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002880 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002881}
2882
2883testcase TC_si2quater_32_earfcns() runs on test_CT {
2884 f_tc_si2quater_n_earfcns(32);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002885 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002886}
2887
2888testcase TC_si2quater_33_earfcns() runs on test_CT {
2889 f_tc_si2quater_n_earfcns(33);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002890 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002891}
2892
2893testcase TC_si2quater_42_earfcns() runs on test_CT {
2894 f_tc_si2quater_n_earfcns(42);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002895 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002896}
2897
2898testcase TC_si2quater_48_earfcns() runs on test_CT {
2899 f_tc_si2quater_n_earfcns(48);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002900 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002901}
2902
2903/* verify the VTY error response when adding too many EARFCNs, and showing that osmo-bsc still sends 16 SI2quater with
2904 * 48 EARFCNs. */
2905testcase TC_si2quater_49_earfcns() runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002906 var template SystemInformationConfig sic := SystemInformationConfig_default;
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002907 sic.si2quater := f_tr_si2quater_earfcns(48); /* 48, not 49! */
2908 f_init(0);
2909
2910 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002911 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2912 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002913 }
2914
2915 /* The 49th EARFCN no longer fits, expect VTY error */
2916 f_vty_enter_cfg_bts(BSCVTY, 0);
2917 var charstring vty_error;
2918 vty_error := f_vty_transceive_ret(BSCVTY,
2919 "si2quater neighbor-list add earfcn 70 thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3")
2920 f_vty_transceive(BSCVTY, "end");
2921
2922 if (f_strstr(vty_error, "Unable to add ARFCN 70") >= 0) {
2923 log("Got expected VTY error: ", vty_error);
2924 setverdict(pass);
2925 } else {
2926 setverdict(fail, "Expected the 49th EUTRAN ARFCN to be rejected by vty config, got: ", vty_error);
2927 }
2928
2929 f_init_bts_and_check_sysinfo(0, expect_si := sic);
2930
2931 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002932 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list del earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))});
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002933 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002934 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002935}
2936
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002937private function f_acc09_count_allowed(AccessControlClass acc) return uint8_t
2938{
2939 var uint8_t count := 0;
2940 for (var integer i := 5; i < 16; i := i + 1) {
2941 if (acc[i] == '0'B) { /* the list marks barred, we count allowed */
2942 count := count + 1;
2943 }
2944 }
2945 return count;
2946}
2947
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002948private function f_recv_next_si1(integer rsl_idx := 0) runs on test_CT return SystemInformationType1
2949{
2950 var ASP_RSL_Unitdata rx_rsl_ud;
2951 var SystemInformationType1 last_si1;
2952
2953 timer T := 30.0;
2954 T.start;
2955 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002956 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD((tr_RSL_NO_BCCH_INFO,
2957 tr_RSL_BCCH_INFO,
2958 tr_RSL_NO_SACCH_FILL,
2959 tr_RSL_SACCH_FILL))) -> value rx_rsl_ud {
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002960 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
2961 if (g_system_information[rsl_idx].si1 == omit) {
2962 repeat;
2963 }
2964 last_si1 := g_system_information[rsl_idx].si1;
2965 g_system_information[rsl_idx].si1 := omit;
2966 T.stop;
2967 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002968 [] IPA_RSL[rsl_idx][0].receive { repeat; }
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002969 [] T.timeout { setverdict(fail, "Timeout receiving next SI1"); }
2970 }
2971 return last_si1;
2972}
2973
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002974/* verify ACC rotate feature */
2975testcase TC_si_acc_rotate() runs on test_CT {
2976 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002977 var SystemInformationType1 last_si1;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002978 var AccessControlClass acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002979 var uint8_t count;
2980 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2981
2982 f_init(0, guard_timeout := 60.0);
2983
2984 f_bts_0_cfg(BSCVTY, {"rach access-control-class 5 barred",
2985 "access-control-class-rotate 3",
2986 "access-control-class-rotate-quantum 1"});
2987
2988 /* Init and get first sysinfo */
2989 f_init_bts_and_check_sysinfo(0, expect_si := ?);
2990
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002991 for (var integer i:= 0; i < 20; i := i + 1) {
2992 last_si1 := f_recv_next_si1(0);
2993 acc := last_si1.rach_control.acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002994 count := f_acc09_count_allowed(acc);
2995 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
2996
2997 if (count != 3) {
2998 log("RSL: EXPECTED SI ACC len=3");
2999 setverdict(fail, "received SI does not match expectations");
3000 break;
3001 }
3002
3003 for (var integer j := 0; j < 10; j := j + 1) {
3004 if (acc[16 - 1 - j] == '0'B) { /* the list marks barred, we count allowed */
3005 times_allowed[j] := times_allowed[j] + 1;
3006 }
3007 }
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003008 }
3009
3010 for (var integer j := 0; j < 10; j := j + 1) {
3011 log("ACC", j, " allowed ", times_allowed[j], " times" );
3012 if (j != 5 and times_allowed[j] < 3) {
3013 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " < 1 times");
3014 } else if (j == 5 and times_allowed[j] > 0) {
3015 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " > 0 times");
3016 }
3017 }
3018
3019 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
3020 "rach access-control-class 5 allowed"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003021 f_shutdown_helper();
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003022}
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02003023
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003024/* verify ACC startup ramp+rotate feature */
3025testcase TC_si_acc_ramp_rotate() runs on test_CT {
3026 var template SystemInformationConfig sic := SystemInformationConfig_default;
3027 var SystemInformationType1 last_si1;
3028 var AccessControlClass acc;
3029 var ASP_RSL_Unitdata rx_rsl_ud;
3030 var uint8_t count;
3031 var uint8_t prev_count;
3032 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
3033
3034 f_init(0, guard_timeout := 80.0);
3035
3036 f_bts_0_cfg(BSCVTY, {"rach access-control-class 4 barred",
3037 "access-control-class-rotate 0",
3038 "access-control-class-rotate-quantum 1",
3039 "access-control-class-ramping",
3040 "access-control-class-ramping-step-interval 5",
3041 "access-control-class-ramping-step-size 5"});
3042
3043 /* Init and get first sysinfo */
3044 f_init_bts_and_check_sysinfo(0, expect_si := ?);
3045 last_si1 := g_system_information[0].si1;
3046 acc := last_si1.rach_control.acc;
3047 count := f_acc09_count_allowed(acc);
3048 /* Adm subset size was set to 0 above, so wait until all ACC are barred */
3049 while (count > 0) {
3050 last_si1 := f_recv_next_si1(0);
3051 acc := last_si1.rach_control.acc;
3052 count := f_acc09_count_allowed(acc);
3053 log("RSL: wait len()=0: GOT SI1 ACC len=", count, ": ", acc);
3054 }
3055
3056 /* Increase adm subset size, we should see ramping start up */
3057 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10"});
3058 prev_count := 0;
3059 while (true) {
3060 last_si1 := f_recv_next_si1(0);
3061 acc := last_si1.rach_control.acc;
3062 count := f_acc09_count_allowed(acc);
3063 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
3064
3065 if (prev_count > count) {
3066 setverdict(fail, "ACC allowed count dropped while expecting grow: ", prev_count, " -> ", count);
3067 break;
3068 }
3069
3070 if (count == 9) {
3071 break; /* Maximum reached (10 - 1 perm barred), done here */
3072 }
3073
3074 prev_count := count;
3075 }
3076
3077 setverdict(pass);
3078
3079 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
3080 "rach access-control-class 4 allowed",
3081 "no access-control-class-ramping"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003082 f_shutdown_helper();
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003083}
3084
Harald Welte4003d112017-12-09 22:35:39 +01003085testcase TC_ctrl_msc_connection_status() runs on test_CT {
3086 var charstring ctrl_resp;
3087
Harald Welte89d42e82017-12-17 16:42:41 +01003088 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003089
3090 /* See https://osmocom.org/issues/2729 */
3091 f_ctrl_get_exp(IPA_CTRL, "msc_connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003092 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01003093}
3094
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003095testcase TC_ctrl_msc0_connection_status() runs on test_CT {
3096 var charstring ctrl_resp;
3097
3098 f_init(1);
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003099
3100 f_ctrl_get_exp(IPA_CTRL, "msc.0.connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003101 f_shutdown_helper();
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003102}
3103
Neels Hofmeyr0bc470d2021-08-21 13:37:13 +02003104/* Verify correct stats on the number of configured and connected MSCs */
3105private function f_tc_stat_num_msc_connected_msc_connhdlr(integer expect_num_msc_connected) runs on MSC_ConnHdlr {
3106 g_pars := f_gen_test_hdlr_pars();
3107 var StatsDExpects expect := {
3108 { name := "TTCN3.bsc.0.num_msc.connected", mtype := "g", min := expect_num_msc_connected, max := expect_num_msc_connected },
3109 { name := "TTCN3.bsc.0.num_msc.total", mtype := "g", min := NUM_MSC, max := NUM_MSC }
3110 };
3111 f_statsd_expect(expect);
3112}
3113
3114private function f_tc_stat_num_msc_connected_test_ct(void_fn tc_fn, integer nr_msc) runs on test_CT
3115{
3116 var MSC_ConnHdlr vc_conn;
3117
3118 f_init(nr_bts := 1, handler_mode := true, nr_msc := nr_msc);
3119 f_sleep(1.0);
3120 vc_conn := f_start_handler(tc_fn);
3121 vc_conn.done;
3122
3123 /* Also verify stat exposed on CTRL interface */
3124 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:connected", int2str(nr_msc));
3125 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:total", int2str(NUM_MSC));
3126
3127 f_shutdown_helper();
3128}
3129
3130/* Verify that when 1 MSC is active, that num_msc:connected reports 1. */
3131private function f_tc_stat_num_msc_connected_1(charstring id) runs on MSC_ConnHdlr {
3132 f_tc_stat_num_msc_connected_msc_connhdlr(1);
3133}
3134testcase TC_stat_num_msc_connected_1() runs on test_CT {
3135 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_1), 1);
3136}
3137
3138/* Verify that when 2 MSCs are active, that num_msc:connected reports 2. */
3139private function f_tc_stat_num_msc_connected_2(charstring id) runs on MSC_ConnHdlr {
3140 f_tc_stat_num_msc_connected_msc_connhdlr(2);
3141}
3142testcase TC_stat_num_msc_connected_2() runs on test_CT {
3143 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_2), 2);
3144}
3145
3146/* Verify that when 3 MSCs are active, that num_msc:connected reports 3. */
3147private function f_tc_stat_num_msc_connected_3(charstring id) runs on MSC_ConnHdlr {
3148 f_tc_stat_num_msc_connected_msc_connhdlr(3);
3149}
3150testcase TC_stat_num_msc_connected_3() runs on test_CT {
3151 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_3), 3);
3152}
3153
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003154/* Verify correct stats on the number of configured and connected MSCs */
3155private function f_tc_stat_num_bts_connected_msc_connhdlr(integer expect_num_bts_connected) runs on MSC_ConnHdlr {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003156 var integer num_trx_connected := 0;
3157 var integer num_trx_total := 0;
3158
3159 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3160 var integer trx_num := c_BtsParams[i].trx_num;
3161 num_trx_total := num_trx_total + trx_num;
3162 if (i < expect_num_bts_connected) {
3163 num_trx_connected := num_trx_connected + trx_num;
3164 }
3165 }
3166
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003167 var StatsDExpects expect := {
3168 { name := "TTCN3.bsc.0.num_bts.oml_connected", mtype := "g", min := expect_num_bts_connected, max := NUM_BTS_CFG },
3169 { name := "TTCN3.bsc.0.num_bts.all_trx_rsl_connected", mtype := "g", min := expect_num_bts_connected, max := expect_num_bts_connected },
3170 { name := "TTCN3.bsc.0.num_bts.total", mtype := "g", min := NUM_BTS_CFG, max := NUM_BTS_CFG },
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003171 { name := "TTCN3.bsc.0.num_trx.rsl_connected", mtype := "g", min := num_trx_connected, max := num_trx_connected },
3172 { name := "TTCN3.bsc.0.num_trx.total", mtype := "g", min := num_trx_total, max := num_trx_total }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003173 };
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003174
3175 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003176 f_statsd_expect(expect);
3177}
3178
3179private function f_tc_stat_num_bts_connected_test_ct(void_fn tc_fn, integer nr_bts) runs on test_CT {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003180 var integer num_trx_connected := 0;
3181 var integer num_trx_total := 0;
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003182 var MSC_ConnHdlr vc_conn;
3183
3184 f_init(nr_bts := nr_bts, handler_mode := true, nr_msc := 1);
3185 f_sleep(1.0);
3186 vc_conn := f_start_handler(tc_fn);
3187 vc_conn.done;
3188
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003189 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3190 var integer trx_num := c_BtsParams[i].trx_num;
3191 num_trx_total := num_trx_total + trx_num;
3192 if (i < nr_bts) {
3193 num_trx_connected := num_trx_connected + trx_num;
3194 }
3195 }
3196
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003197 /* Also verify stat exposed on CTRL interface */
3198 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_bts:all_trx_rsl_connected", int2str(nr_bts));
3199 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_bts:total", int2str(NUM_BTS_CFG));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003200 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_trx:rsl_connected", int2str(num_trx_connected));
3201 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_trx:total", int2str(num_trx_total));
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003202
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003203 /* Verify rf_states exposed on CTRL interface */
3204 var charstring expect_net_rf_states := "";
3205 for (var integer i := 0; i < NUM_BTS_CFG; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003206 var charstring expect_bts_rf_states := "";
3207
3208 for (var integer j := 0; j < c_BtsParams[i].trx_num; j := j + 1) {
3209 expect_bts_rf_states := expect_bts_rf_states &
3210 int2str(i) & "," & int2str(j) & ",";
3211 if (i < NUM_BTS) {
3212 /* In these tests, OML for the first NUM_BTS are always connected via osmo-bts-omldummy */
3213 expect_bts_rf_states := expect_bts_rf_states & "operational,unlocked,";
3214 } else {
3215 /* For remaining i < NUM_BTS_CFG, OML is not connected, i.e. inoperational */
3216 expect_bts_rf_states := expect_bts_rf_states & "inoperational,locked,";
3217 }
3218 /* The RF policy is still global in osmo-bsc, i.e. always "on" */
3219 expect_bts_rf_states := expect_bts_rf_states & "on,";
3220 if (i < nr_bts) {
3221 /* For BTS where RSL is connected, the RSL state will be "up" */
3222 expect_bts_rf_states := expect_bts_rf_states & "rsl-up;";
3223 } else {
3224 expect_bts_rf_states := expect_bts_rf_states & "rsl-down;";
3225 }
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003226 }
3227
3228 f_ctrl_get_exp(IPA_CTRL, "bts." & int2str(i) & ".rf_states", expect_bts_rf_states);
3229 expect_net_rf_states := expect_net_rf_states & expect_bts_rf_states;
3230 }
3231 f_ctrl_get_exp(IPA_CTRL, "rf_states", expect_net_rf_states);
3232
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003233 f_shutdown_helper();
3234}
3235
3236/* Verify that when 1 BTS is connected, that num_{bts,trx}:*_connected reports 1. */
3237private function f_tc_stat_num_bts_connected_1(charstring id) runs on MSC_ConnHdlr {
3238 f_tc_stat_num_bts_connected_msc_connhdlr(1);
3239}
3240testcase TC_stat_num_bts_connected_1() runs on test_CT {
3241 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_1), 1);
3242}
3243
3244/* Verify that when 2 BTS is connected, that num_{bts,trx}:*_connected reports 2. */
3245private function f_tc_stat_num_bts_connected_2(charstring id) runs on MSC_ConnHdlr {
3246 f_tc_stat_num_bts_connected_msc_connhdlr(2);
3247}
3248testcase TC_stat_num_bts_connected_2() runs on test_CT {
3249 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_2), 2);
3250}
3251
3252/* Verify that when 3 BTS is connected, that num_{bts,trx}:*_connected reports 3. */
3253private function f_tc_stat_num_bts_connected_3(charstring id) runs on MSC_ConnHdlr {
3254 f_tc_stat_num_bts_connected_msc_connhdlr(3);
3255}
3256testcase TC_stat_num_bts_connected_3() runs on test_CT {
3257 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_3), 3);
3258}
3259
Harald Welte4003d112017-12-09 22:35:39 +01003260testcase TC_ctrl() runs on test_CT {
3261 var charstring ctrl_resp;
3262
Harald Welte89d42e82017-12-17 16:42:41 +01003263 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003264
3265 /* all below values must match the osmo-bsc.cfg config file used */
3266
Harald Welte6a129692018-03-17 17:30:14 +01003267 f_ctrl_get_exp(IPA_CTRL, "mcc", "001");
3268 f_ctrl_get_exp(IPA_CTRL, "mnc", "01");
Oliver Smith75aa0202019-08-19 14:17:50 +02003269 f_ctrl_get_exp(IPA_CTRL, "number-of-bts", "4");
Harald Welte4003d112017-12-09 22:35:39 +01003270
3271 var integer bts_nr := 0;
3272 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "location-area-code", "1");
3273 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "cell-identity", "0");
3274 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "oml-connection-state", "connected");
3275 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "gprs-mode", "gprs");
3276 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "rf_state", "operational,unlocked,on");
3277 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "arfcn", "871");
3278 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "max-power-reduction", "20");
3279
3280 var integer uptime := str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime"));
3281 f_sleep(2.0);
3282 if (str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime")) < uptime+1) {
3283 setverdict(fail, "oml-uptime not incrementing as expected");
3284 }
3285 /* TODO: Disconnect RSL, imply that OML is disconnected and check for uptime zero? */
3286
3287 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", 0);
3288
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003289 f_shutdown_helper();
Harald Welte96c94412017-12-09 03:12:45 +01003290}
3291
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003292/* Verify that Upon receival of SET "location", BSC forwards a TRAP
3293 "location-state" over the SCCPlite IPA conn */
3294testcase TC_ctrl_location() runs on test_CT {
3295 var MSC_ConnHdlr vc_conn;
3296 var integer bts_nr := 0;
3297
3298 f_init(1, true);
3299 f_sleep(1.0);
3300
3301 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234567,fix3d,0.340000,0.560000,0.780000");
3302 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3303 "1234567,fix3d,0.340000,0.560000,0.780000,operational,unlocked,on,001,01");
3304
3305 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "1");
3306 f_sleep(2.0);
3307
3308 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234888,fix3d,0.350000,0.570000,0.790000");
3309 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3310 "1234888,fix3d,0.350000,0.570000,0.790000,operational,locked,off,001,01");
3311
3312 /* should match the one from config */
3313 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "0");
3314
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003315 f_shutdown_helper();
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003316}
3317
Harald Welte6f521d82017-12-11 19:52:02 +01003318
3319/***********************************************************************
3320 * Paging Testing
3321 ***********************************************************************/
3322
3323type record Cell_Identity {
3324 GsmMcc mcc,
3325 GsmMnc mnc,
3326 GsmLac lac,
3327 GsmCellId ci
3328};
Harald Welte24135bd2018-03-17 19:27:53 +01003329private const Cell_Identity cid := { '001'H, '01'H, 1, 0 };
Stefan Sperling049a86e2018-03-20 15:51:00 +01003330private const Cell_Identity unknown_cid := { '678'H, 'f90'H, 1, 0 };
Harald Welte6f521d82017-12-11 19:52:02 +01003331
Harald Welte5d1a2202017-12-13 19:51:29 +01003332type set of integer BtsIdList;
3333
3334private function f_bts_in_list(integer bts_id, BtsIdList bts_ids) return boolean {
3335 for (var integer j := 0; j < sizeof(bts_ids); j := j + 1) {
3336 if (bts_id == bts_ids[j]) {
3337 return true;
3338 }
3339 }
3340 return false;
3341}
Harald Welte6f521d82017-12-11 19:52:02 +01003342
3343/* core paging test helper function; used by most paging test cases */
3344private function f_pageing_helper(hexstring imsi,
3345 template BSSMAP_FIELD_CellIdentificationList cid_list,
Harald Welte5d1a2202017-12-13 19:51:29 +01003346 BtsIdList bts_ids := { 0 },
Harald Welte6f521d82017-12-11 19:52:02 +01003347 template RSL_ChanNeeded rsl_chneed := omit,
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003348 template (omit) OCT4 tmsi := omit) runs on test_CT
Harald Welte6f521d82017-12-11 19:52:02 +01003349{
3350 var template BSSMAP_IE_ChannelNeeded bssmap_chneed;
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003351 var template MobileIdentityV mi;
Harald Welte6f521d82017-12-11 19:52:02 +01003352 var RSL_Message rx_rsl;
3353 var integer paging_group := hex2int(imsi[lengthof(imsi)-1]);
Harald Welte5d1a2202017-12-13 19:51:29 +01003354 var integer i;
Harald Welte6f521d82017-12-11 19:52:02 +01003355
3356 f_init();
Harald Welte6f521d82017-12-11 19:52:02 +01003357
3358 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Harald Weltec3068592018-03-17 19:55:31 +01003359 for (i := 0; i < NUM_BTS; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003360 IPA_RSL[i][0].clear;
Harald Welte5d1a2202017-12-13 19:51:29 +01003361 }
Harald Welte6f521d82017-12-11 19:52:02 +01003362
3363 if (isvalue(rsl_chneed)) {
3364 /* The values of 08.08 3.2.2.36 and 08.58 9.3.40 are luckily identical */
3365 bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
3366 } else {
3367 bssmap_chneed := omit;
3368 }
3369
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003370 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own,
3371 ts_BSSMAP_Paging(imsi, cid_list, tmsi, bssmap_chneed)));
Harald Welte6f521d82017-12-11 19:52:02 +01003372
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003373 if (not istemplatekind(tmsi, "omit")) {
3374 mi := t_MI_TMSI(tmsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003375 } else {
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003376 mi := tr_MI_IMSI(imsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003377 }
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003378
Harald Welte5d1a2202017-12-13 19:51:29 +01003379 for (i := 0; i < sizeof(bts_ids); i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003380 rx_rsl := f_exp_ipa_rx(tr_RSL_PAGING_CMD(mi), idx := {bts_ids[i], 0});
Harald Welte5d1a2202017-12-13 19:51:29 +01003381 /* check channel type, paging group */
3382 if (rx_rsl.ies[1].body.paging_group != paging_group) {
3383 setverdict(fail, "Paging for wrong paging group");
3384 }
3385 if (ispresent(rsl_chneed) and
3386 rx_rsl.ies[3].body.chan_needed.chan_needed != valueof(rsl_chneed)) {
3387 setverdict(fail, "RSL Channel Needed != BSSMAP Channel Needed");
3388 }
Harald Welte6f521d82017-12-11 19:52:02 +01003389 }
Harald Welte2fccd982018-01-31 15:48:19 +01003390 f_sleep(2.0);
Harald Welte5d1a2202017-12-13 19:51:29 +01003391 /* do a quick check on all not-included BTSs if they received paging */
3392 for (i := 0; i < NUM_BTS; i := i + 1) {
3393 timer T := 0.1;
3394 if (f_bts_in_list(i, bts_ids)) {
3395 continue;
3396 }
3397 T.start;
3398 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003399 [] IPA_RSL[i][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(mi))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003400 setverdict(fail, "Paging on BTS ", i, " which is not part of ", bts_ids);
3401 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003402 [] IPA_RSL[i][0].receive { repeat; }
Harald Welte5d1a2202017-12-13 19:51:29 +01003403 [] T.timeout { }
3404 }
Harald Welte6f521d82017-12-11 19:52:02 +01003405 }
3406
3407 setverdict(pass);
3408}
3409
Harald Welte5d1a2202017-12-13 19:51:29 +01003410const BtsIdList c_BtsId_all := { 0, 1, 2 };
Harald Welte751d3eb2018-01-31 15:51:06 +01003411const BtsIdList c_BtsId_none := { };
Harald Welte5d1a2202017-12-13 19:51:29 +01003412const BtsIdList c_BtsId_LAC1 := { 0, 1 };
3413const BtsIdList c_BtsId_LAC2 := { 2 };
3414
Harald Welte6f521d82017-12-11 19:52:02 +01003415/* PAGING by IMSI + TMSI */
3416testcase TC_paging_imsi_nochan() runs on test_CT {
3417 var BSSMAP_FIELD_CellIdentificationList cid_list;
3418 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Philipp Maier8c04b0a2018-02-23 13:48:48 +01003419 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, omit);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003420 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003421}
3422
3423/* PAGING by IMSI + TMSI */
3424testcase TC_paging_tmsi_nochan() runs on test_CT {
3425 var BSSMAP_FIELD_CellIdentificationList cid_list;
3426 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003427 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, 'A1B2C301'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003428 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003429}
3430
3431/* Paging with different "channel needed' values */
3432testcase TC_paging_tmsi_any() runs on test_CT {
3433 var BSSMAP_FIELD_CellIdentificationList cid_list;
3434 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003435 f_pageing_helper('001010100000002'H, cid_list, c_BtsId_all, RSL_CHANNEED_ANY, 'A1B2C302'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003436 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003437}
3438testcase TC_paging_tmsi_sdcch() runs on test_CT {
3439 var BSSMAP_FIELD_CellIdentificationList cid_list;
3440 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003441 f_pageing_helper('001010100000003'H, cid_list, c_BtsId_all, RSL_CHANNEED_SDCCH, 'A1B2C303'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003442 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003443}
3444testcase TC_paging_tmsi_tch_f() runs on test_CT {
3445 var BSSMAP_FIELD_CellIdentificationList cid_list;
3446 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003447 f_pageing_helper('001010000000004'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_F, 'A1B2C304'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003448 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003449}
3450testcase TC_paging_tmsi_tch_hf() runs on test_CT {
3451 var BSSMAP_FIELD_CellIdentificationList cid_list;
3452 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003453 f_pageing_helper('001010000000005'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_ForH, 'A1B2C305'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003454 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003455}
3456
3457/* Paging by CGI */
3458testcase TC_paging_imsi_nochan_cgi() runs on test_CT {
3459 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3460 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(cid.mcc, cid.mnc, cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003461 f_pageing_helper('001010000000006'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003462 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003463}
3464
3465/* Paging by LAC+CI */
3466testcase TC_paging_imsi_nochan_lac_ci() runs on test_CT {
3467 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3468 cid_list := { cIl_LAC_CI := { ts_BSSMAP_CI_LAC_CI(cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003469 f_pageing_helper('001010000000007'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003470 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003471}
3472
3473/* Paging by CI */
3474testcase TC_paging_imsi_nochan_ci() runs on test_CT {
3475 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3476 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003477 f_pageing_helper('001010000000008'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003478 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003479}
3480
3481/* Paging by LAI */
3482testcase TC_paging_imsi_nochan_lai() runs on test_CT {
3483 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3484 cid_list := { cIl_LAI := { ts_BSSMAP_CI_LAI(cid.mcc, cid.mnc, cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003485 f_pageing_helper('001010000000009'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003486 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003487}
3488
3489/* Paging by LAC */
3490testcase TC_paging_imsi_nochan_lac() runs on test_CT {
3491 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3492 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003493 f_pageing_helper('001010000000010'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003494 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003495}
3496
3497/* Paging by "all in BSS" */
3498testcase TC_paging_imsi_nochan_all() runs on test_CT {
3499 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3500 cid_list := { cIl_allInBSS := ''O };
Harald Welte5d1a2202017-12-13 19:51:29 +01003501 f_pageing_helper('001010000000011'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003502 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003503}
3504
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003505/* Paging by PLMN+LAC+RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003506testcase TC_paging_imsi_nochan_plmn_lac_rnc() runs on test_CT {
3507 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3508 cid_list := { cIl_PLMN_LAC_RNC := { ts_BSSMAP_CI_PLMN_LAC_RNC(cid.mcc, cid.mnc, cid.lac, 12) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003509 f_pageing_helper('001010000000012'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003510 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003511}
Harald Welte6f521d82017-12-11 19:52:02 +01003512
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003513/* Paging by RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003514testcase TC_paging_imsi_nochan_rnc() runs on test_CT {
3515 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3516 cid_list := { cIl_RNC := { int2oct(13, 2) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003517 f_pageing_helper('001010000000013'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003518 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003519}
3520
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003521/* Paging by LAC+RNC; We do not implement; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003522testcase TC_paging_imsi_nochan_lac_rnc() runs on test_CT {
3523 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3524 cid_list := { cIl_LAC_RNC := { ts_BSSMAP_CI_LAC_RNC(cid.lac, 14) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003525 f_pageing_helper('001010000000014'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003526 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003527}
3528
Harald Welte6f521d82017-12-11 19:52:02 +01003529/* Paging on multiple cells (multiple entries in list): Verify all of them page */
Harald Welte751d3eb2018-01-31 15:51:06 +01003530testcase TC_paging_imsi_nochan_lacs() runs on test_CT {
3531 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3532 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(1), ts_BSSMAP_CI_LAC(2) } };
3533 f_pageing_helper('001010000000015'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003534 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003535}
3536
3537/* Paging on empty list: Verify none of them page */
3538testcase TC_paging_imsi_nochan_lacs_empty() runs on test_CT {
3539 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3540 cid_list := { cIl_LAC := { } };
3541 f_pageing_helper('001010000000016'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003542 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003543}
3544
Stefan Sperling049a86e2018-03-20 15:51:00 +01003545/* Paging by CGI with unknown MCC/MNC: Verify nothing is paged. */
3546testcase TC_paging_imsi_nochan_cgi_unknown_cid() runs on test_CT {
3547 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3548 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(unknown_cid.mcc, unknown_cid.mnc, unknown_cid.lac, unknown_cid.ci) } };
3549 f_pageing_helper('001010000000006'H, cid_list, c_BtsId_none);
3550 f_shutdown_helper();
3551}
3552
Pau Espin Pedrol07657ae2023-01-03 12:08:05 +01003553/* Send paging response containing invalid (wrongly formatted) MobileIdentity IE. */
3554testcase TC_paging_imsi_nochan_ci_resp_invalid_mi() runs on test_CT {
3555 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3556 var BSSAP_N_CONNECT_ind rx_c_ind;
3557 var DchanTuple dt;
3558 var octetstring rr_pag_resp := '06270003535992617965720000'O;
3559 /* { 06 27 } is { GSM48_PDISC_RR, GSM48_MT_RR_PAG_RESP }
3560 * see 3GPP TS 44.018, table 9.1.25.1
3561 * { 00 } or { 01 } is CKSN + Spare Half Octet, not important
3562 * { 03 53 59 92 } is Mobile Station Classmark
3563 * { 61 79 65 72 00 00 } is the invalid Mobile Identity IE (3GPP TS 24.008, 10.5.1.4),
3564 * Length is 0x61 (97 in decimal).
3565 */
3566
3567 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
3568 f_pageing_helper('001010000000008'H, cid_list, { 0 });
3569
3570 /* Send CHAN RQD and wait for allocation; acknowledge it */
3571 dt.rsl_chan_nr := f_chreq_act_ack();
3572 dt.idx := {0, 0};
3573
3574 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
3575 f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), rr_pag_resp));
3576
3577 /* Expevct a CR with a matching Paging response on the A-Interface */
3578 timer T := 5.0;
3579 T.start;
3580 alt {
3581 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
3582 setverdict(pass);
3583 dt.sccp_conn_id := rx_c_ind.connectionId;
3584 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
3585 }
3586 [] BSSAP.receive {
3587 setverdict(fail, "Received unexpected message on A-Interface!");
3588 }
3589 [] T.timeout {
3590 setverdict(fail, "Received nothing on A-Interface!");
3591 }
3592 }
3593
3594 f_perform_clear_test_ct(dt);
3595 f_shutdown_helper();
3596}
3597
Harald Welte6f521d82017-12-11 19:52:02 +01003598/* Verify paging retransmission interval + count */
3599/* Verify paging stops after channel establishment */
Harald Welte6f521d82017-12-11 19:52:02 +01003600/* Test behavior under paging overload */
Harald Welteae026692017-12-09 01:03:01 +01003601
Harald Weltee65d40e2017-12-13 00:09:06 +01003602/* Verify PCH load */
3603testcase TC_paging_imsi_load() runs on test_CT {
3604 var BSSMAP_FIELD_CellIdentificationList cid_list;
3605 timer T := 4.0;
Harald Welte2caa1062018-03-17 18:19:05 +01003606 timer T_retrans := 1.0;
Harald Weltee65d40e2017-12-13 00:09:06 +01003607 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003608 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Weltee65d40e2017-12-13 00:09:06 +01003609
3610 /* tell BSC there is no paging space anymore */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003611 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte3b57ab52018-03-17 18:01:10 +01003612 f_sleep(0.2);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003613 IPA_RSL[0][0].clear;
Harald Weltee65d40e2017-12-13 00:09:06 +01003614
3615 /* Wait for 4 seconds if any more PAGING CMD are received on RSL. Normally,
3616 * there would be 8 retransmissions during 4 seconds */
3617 T.start;
Harald Welte2caa1062018-03-17 18:19:05 +01003618 T_retrans.start;
Harald Weltee65d40e2017-12-13 00:09:06 +01003619 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003620 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Weltee65d40e2017-12-13 00:09:06 +01003621 setverdict(fail, "Received PAGING after LOAD_IND(0)");
Daniel Willmannafce8662018-07-06 23:11:32 +02003622 mtc.stop;
Harald Weltee65d40e2017-12-13 00:09:06 +01003623 }
Harald Welte2caa1062018-03-17 18:19:05 +01003624 [] T_retrans.timeout {
3625 /* re-trnsmit the zero-space LOAD IND to avoid BSC 'auto credit' */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003626 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte2caa1062018-03-17 18:19:05 +01003627 T_retrans.start;
3628 repeat;
3629 }
Harald Weltee65d40e2017-12-13 00:09:06 +01003630 [] T.timeout {
3631 setverdict(pass);
3632 }
3633 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003634
3635 f_shutdown_helper();
Harald Weltee65d40e2017-12-13 00:09:06 +01003636}
3637
Harald Welte235ebf12017-12-15 14:18:16 +01003638/* Verify Paging Counter */
Harald Welte1ff69992017-12-14 12:31:17 +01003639testcase TC_paging_counter() runs on test_CT {
3640 var BSSMAP_FIELD_CellIdentificationList cid_list;
3641 timer T := 4.0;
3642 var integer i;
3643 var integer paging_attempted_bsc;
3644 var integer paging_attempted_bts[NUM_BTS];
Oliver Smith8b343d32021-11-26 13:01:42 +01003645 var integer paging_expired_bsc;
Harald Welte1ff69992017-12-14 12:31:17 +01003646 var integer paging_expired_bts[NUM_BTS];
3647 cid_list := valueof(ts_BSSMAP_CIL_noCell);
3648
3649 f_init();
3650
3651 /* read counters before paging */
3652 paging_attempted_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted");
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01003653 paging_expired_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired");
Harald Welte1ff69992017-12-14 12:31:17 +01003654 for (i := 0; i < NUM_BTS; i := i+1) {
3655 paging_attempted_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted");
3656 paging_expired_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired");
3657 }
3658
3659 f_pageing_helper('001230000000001'H, cid_list, c_BtsId_all);
3660
3661 /* expect the attempted pages on BSC and each BTSs to have incremented by one */
3662 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", paging_attempted_bsc+1);
3663 for (i := 0; i < NUM_BTS; i := i+1) {
3664 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted",
3665 paging_attempted_bts[i]+1);
3666 }
3667
3668 /* assume that 12s later the paging on all BTSs have expired and hence incremented by 1 */
3669 f_sleep(12.0);
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01003670 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired", paging_expired_bsc+1);
Harald Welte1ff69992017-12-14 12:31:17 +01003671 for (i := 0; i < NUM_BTS; i := i+1) {
3672 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired",
3673 paging_expired_bts[i]+1);
3674 }
Harald Welte1ff69992017-12-14 12:31:17 +01003675
Philipp Maier282ca4b2018-02-27 17:17:00 +01003676 f_shutdown_helper();
Harald Welte1ff69992017-12-14 12:31:17 +01003677}
3678
3679
Harald Welte10985002017-12-12 09:29:15 +01003680/* Verify paging stops after A-RESET */
3681testcase TC_paging_imsi_a_reset() runs on test_CT {
3682 var BSSMAP_FIELD_CellIdentificationList cid_list;
3683 timer T := 3.0;
3684 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003685 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Welte10985002017-12-12 09:29:15 +01003686
3687 /* Perform a BSSMAP Reset and wait for ACK */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003688 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own, ts_BSSMAP_Reset(0, g_osmux_enabled_cn)));
Harald Welte10985002017-12-12 09:29:15 +01003689 alt {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003690 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(g_bssap[0].sccp_addr_own, g_bssap[0].sccp_addr_peer, tr_BSSMAP_ResetAck(g_osmux_enabled_cn))) { }
Harald Welte10985002017-12-12 09:29:15 +01003691 [] BSSAP.receive { repeat; }
3692 }
3693
Daniel Willmanncbef3982018-07-30 09:22:40 +02003694 /* Wait to avoid a possible race condition if a paging message is
3695 * received right before the reset ACK. */
3696 f_sleep(0.2);
3697
Harald Welte10985002017-12-12 09:29:15 +01003698 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Philipp Maier1e6b4422018-02-23 14:02:13 +01003699 for (var integer i := 0; i < sizeof(IPA_RSL); i := i+1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003700 IPA_RSL[i][0].clear;
Philipp Maier1e6b4422018-02-23 14:02:13 +01003701 }
Harald Welte10985002017-12-12 09:29:15 +01003702
3703 /* Wait for 3 seconds if any more PAGING CMD are received on RSL */
3704 T.start;
3705 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003706 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte10985002017-12-12 09:29:15 +01003707 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003708 mtc.stop;
Harald Welte10985002017-12-12 09:29:15 +01003709 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003710 [] IPA_RSL[1][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003711 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003712 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003713 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003714 [] IPA_RSL[2][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003715 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003716 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003717 }
Harald Welte10985002017-12-12 09:29:15 +01003718 [] T.timeout {
3719 setverdict(pass);
3720 }
3721 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003722
3723 f_shutdown_helper();
Harald Welte10985002017-12-12 09:29:15 +01003724}
Harald Welteae026692017-12-09 01:03:01 +01003725
Philipp Maierf45824a2019-08-14 14:44:10 +02003726/* Verify how we handle unsolicited Paging Response. In case of an unsolicit
3727 * paging response we can not know which MSC is in charge, so we will blindly
3728 * pick the first configured MSC. This behavior is required in order to make
3729 * MT-CSFB calls working because in those cases the BSC can not know that the
3730 * MSC has already paged the subscriver via SGs. So any MT-CSFB call will look
3731 * like an unsolicited Paging Response to the MSC.
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003732 */
3733testcase TC_paging_resp_unsol() runs on test_CT {
3734
3735 f_init(1);
Philipp Maierf45824a2019-08-14 14:44:10 +02003736 timer T := 5.0;
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003737
3738 var BSSAP_N_CONNECT_ind rx_c_ind;
3739 var DchanTuple dt;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02003740 var PDU_ML3_MS_NW l3 := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010008880018'H)));
Philipp Maierf45824a2019-08-14 14:44:10 +02003741 var octetstring rr_pag_resp := enc_PDU_ML3_MS_NW(l3);
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003742
3743 /* Send CHAN RQD and wait for allocation; acknowledge it */
3744 dt.rsl_chan_nr := f_chreq_act_ack();
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003745 dt.idx := {0, 0};
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003746
3747 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
Pau Espin Pedrole8a51012023-01-03 11:59:59 +01003748 f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), rr_pag_resp));
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003749
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003750
Philipp Maierf45824a2019-08-14 14:44:10 +02003751 /* Expevct a CR with a matching Paging response on the A-Interface */
3752 T.start;
3753 alt {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003754 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
Philipp Maierf45824a2019-08-14 14:44:10 +02003755 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003756 dt.sccp_conn_id := rx_c_ind.connectionId;
3757 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
Philipp Maierf45824a2019-08-14 14:44:10 +02003758 }
3759 [] BSSAP.receive {
3760 setverdict(fail, "Received unexpected message on A-Interface!");
3761 }
3762 [] T.timeout {
3763 setverdict(fail, "Received nothing on A-Interface!");
3764 }
3765 }
3766
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003767 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003768 f_shutdown_helper();
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003769}
3770
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003771/* Verify BSC can schedule N paging requests under one minute if BTS buffer is good enough */
3772function f_TC_paging_Nreq(integer num_subscribers, boolean send_pag_load_ind) runs on test_CT {
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003773 var ASP_RSL_Unitdata rx_rsl_ud;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003774 var Hexstrings imsis := {};
3775 var Booleans rx_paging_done := {};
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003776 var integer rx_paging_num := 0;
3777 var integer i;
3778 timer T_rx := 60.0;
3779 timer T_load_ind := 1.0;
3780
3781 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003782 imsis := imsis & {f_gen_imsi(i)};
3783 rx_paging_done := rx_paging_done & { false };
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003784 }
3785
3786 f_init(1, guard_timeout := 100.0);
3787
3788 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003789 IPA_RSL[0][0].clear;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003790 if (send_pag_load_ind) {
3791 /* Tell there's plenty of space at the BTS (UINT16_MAX): */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003792 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(65535));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003793 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003794
3795 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003796 /* Page on LAC-CI of BTS0: */
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003797 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own,
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003798 ts_BSSMAP_Paging(imsis[i], valueof(ts_BSSMAP_CIL_LAC_CI({ts_BSSMAP_CI_LAC_CI(1, 0)})),
3799 omit, omit)));
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003800 }
3801
3802 T_rx.start;
3803 T_load_ind.start;
3804 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003805 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?), IPAC_PROTO_RSL_TRX0)) -> value rx_rsl_ud {
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003806 var hexstring imsi := rx_rsl_ud.rsl.ies[2].body.ms_identity.mobileIdentityV.oddEvenInd_identity.imsi.digits;
3807 var hexstring imsi_suffix := substr(imsi, lengthof(imsi)-6, 6);
3808 var charstring imsi_str := hex2str(imsi_suffix);
3809 var integer imsi_idx := str2int(imsi_str);
3810 if (rx_paging_done[imsi_idx] == false) {
3811 rx_paging_done[imsi_idx] := true;
3812 rx_paging_num := rx_paging_num + 1;
Pau Espin Pedrolef7ef632022-04-25 13:34:57 +02003813 } else {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003814 setverdict(fail, "Retrans of ", imsi_str, " happened before Rx initial trans for all reqs. rx_paging_num=", rx_paging_num);
Pau Espin Pedrolef7ef632022-04-25 13:34:57 +02003815 mtc.stop;
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003816 }
3817 if (rx_paging_num < num_subscribers) {
3818 repeat;
3819 }
3820 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003821 [] IPA_RSL[0][0].receive { repeat; }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003822 [] T_load_ind.timeout {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003823 log("[CCH Load Ind timer] received paging requests so far: ", rx_paging_num);
3824 if (send_pag_load_ind) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003825 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(40));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003826 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003827 T_load_ind.start;
3828 repeat;
3829 }
3830 [] T_rx.timeout {
3831 setverdict(fail, "Timeout expecting paging requests, so far ", rx_paging_num);
3832 mtc.stop;
3833 }
3834 }
3835
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003836 /* Drop OML connection to have all paging requests flushed: */
3837 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
3838
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003839 f_shutdown_helper();
3840}
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003841/* Verify BSC can schedule 500 paging requests under one minute if BTS buffer is good enough */
3842testcase TC_paging_500req() runs on test_CT {
3843 f_TC_paging_Nreq(500, true);
3844}
3845/* Same as TC_paging_500req, but without sending CCCH Load Indication, which
3846 * means BTS is always under CCH Load Threshold, aka capable of sending tons of requests.
3847 * Since No CCCH Load Ind, BSC uses a conservative estimation of BTS load, which
3848 * for current config yields ~8req/sec, so 480req/min maximum. */
3849testcase TC_paging_450req_no_paging_load_ind() runs on test_CT {
3850 f_TC_paging_Nreq(450, false);
3851}
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003852
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003853/* Test RSL link drop causes counter increment */
3854testcase TC_rsl_drop_counter() runs on test_CT {
3855 var integer rsl_fail;
3856
Harald Welte89d42e82017-12-17 16:42:41 +01003857 f_init(1);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003858
3859 rsl_fail := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail");
3860
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003861 f_ipa_rsl_stop(bts[0][0].rsl);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003862
3863 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail", rsl_fail+1);
3864
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003865 f_shutdown_helper();
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003866}
3867
3868/* TODO: Test OML link drop causes counter increment */
3869
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003870/* The body of TC_rsl_unknown_unit_id() and TC_oml_unknown_unit_id() tests. */
3871function f_ipa_unknown_unit_id(integer mp_bsc_ipa_port) runs on test_CT return boolean {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003872 var IPA_Client client;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003873 timer T := 10.0;
3874
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003875 client.id := "IPA-BTS0-TRX0-RSL";
3876 client.vc_IPA := IPA_Emulation_CT.create(client.id & "-IPA") alive;
3877 client.ccm_pars := c_IPA_default_ccm_pars;
3878 client.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
3879 client.ccm_pars.unit_id := "99/0/0"; /* value which is unknown at BTS */
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003880
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01003881 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003882
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003883 f_init_mgcp(0, "VirtMGW");
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003884
3885 /* start RSL/OML connection (XXX re-uses RSL port/protocol definitions for OML) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003886 map(client.vc_IPA:IPA_PORT, system:IPA);
3887 connect(client.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[0][0]);
3888 client.vc_IPA.start(IPA_Emulation.main_client(mp_bsc_ip, mp_bsc_ipa_port, "", 10000, client.ccm_pars));
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003889
3890 /* wait for IPA OML link to connect and then disconnect */
3891 T.start;
3892 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003893 [] IPA_RSL[0][0].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_DOWN)) {
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003894 T.stop;
3895 return true;
3896 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003897 [] IPA_RSL[0][0].receive { repeat }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003898 [] T.timeout {
Daniel Willmannafce8662018-07-06 23:11:32 +02003899 return false;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003900 }
3901 }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003902 return false;
3903}
3904
3905/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3906testcase TC_rsl_unknown_unit_id() runs on test_CT {
3907 if (f_ipa_unknown_unit_id(mp_bsc_rsl_port)) {
3908 setverdict(pass);
3909 } else {
3910 setverdict(fail, "Timeout RSL waiting for connection to close");
3911 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003912 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003913}
3914
3915
3916/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3917testcase TC_oml_unknown_unit_id() runs on test_CT {
3918 if (f_ipa_unknown_unit_id(mp_bsc_oml_port)) {
3919 setverdict(pass);
3920 } else {
3921 setverdict(fail, "Timeout OML waiting for connection to close");
3922 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003923 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003924}
3925
3926
Harald Weltec1a2fff2017-12-17 11:06:19 +01003927/***********************************************************************
Harald Welte6811d102019-04-14 22:23:14 +02003928 * "New world" test cases using RSL_Emulation + RAN_Emulation
Harald Weltec1a2fff2017-12-17 11:06:19 +01003929 ***********************************************************************/
3930
Harald Welte6811d102019-04-14 22:23:14 +02003931import from RAN_Emulation all;
Harald Welte47cd0e32020-08-21 12:39:11 +02003932import from BSSAP_LE_Emulation all;
Harald Weltec1a2fff2017-12-17 11:06:19 +01003933import from RSL_Emulation all;
3934import from MSC_ConnectionHandler all;
3935
3936type function void_fn(charstring id) runs on MSC_ConnHdlr;
3937
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003938/* helper function to create and connect a MSC_ConnHdlr component
3939 * TODO: allow connecting to TRX1..N, not only TRX0 */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003940private function f_connect_handler(inout MSC_ConnHdlr vc_conn, integer bssap_idx := 0, integer mgwpool_idx := 0) runs on test_CT {
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003941 connect(vc_conn:RAN, g_bssap[bssap_idx].vc_RAN:PROC);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003942 connect(vc_conn:RSL, bts[0][0].rsl.vc_RSL:CLIENT_PT);
3943 connect(vc_conn:RSL_PROC, bts[0][0].rsl.vc_RSL:RSL_PROC);
3944 if (isvalue(bts[1][0])) {
3945 connect(vc_conn:RSL1, bts[1][0].rsl.vc_RSL:CLIENT_PT);
3946 connect(vc_conn:RSL1_PROC, bts[1][0].rsl.vc_RSL:RSL_PROC);
Philipp Maier956a92f2018-02-16 10:58:07 +01003947 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003948 if (isvalue(bts[2][0])) {
3949 connect(vc_conn:RSL2, bts[2][0].rsl.vc_RSL:CLIENT_PT);
3950 connect(vc_conn:RSL2_PROC, bts[2][0].rsl.vc_RSL:RSL_PROC);
Neels Hofmeyr91401012019-07-11 00:42:35 +02003951 }
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003952 connect(vc_conn:BSSAP, g_bssap[bssap_idx].vc_RAN:CLIENT);
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02003953 if (mp_enable_lcs_tests) {
3954 connect(vc_conn:BSSAP_LE, g_bssap_le.vc_BSSAP_LE:CLIENT);
3955 connect(vc_conn:BSSAP_LE_PROC, g_bssap_le.vc_BSSAP_LE:PROC);
3956 }
Daniel Willmannebdecc02020-08-12 15:30:17 +02003957 connect(vc_conn:STATSD_PROC, vc_STATSD:STATSD_PROC);
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003958 connect(vc_conn:MGCP_PROC, vc_MGCP[mgwpool_idx]:MGCP_PROC);
3959 connect(vc_conn:MGCP, vc_MGCP[mgwpool_idx]:MGCP_CLIENT);
3960 connect(vc_conn:MGCP_MULTI, vc_MGCP[mgwpool_idx]:MGCP_CLIENT_MULTI);
Harald Welte336820c2018-05-31 20:34:52 +02003961}
3962
Neels Hofmeyrda436782021-07-20 22:09:06 +02003963function f_start_handler_create(template (omit) TestHdlrParams pars := omit)
Harald Welte336820c2018-05-31 20:34:52 +02003964runs on test_CT return MSC_ConnHdlr {
3965 var charstring id := testcasename();
3966 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003967 var integer bssap_idx := 0;
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003968 var integer mgwpool_idx := 0;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003969 if (isvalue(pars)) {
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003970 var TestHdlrParams pars_val := valueof(pars);
3971 bssap_idx := pars_val.mscpool.bssap_idx;
3972 mgwpool_idx := pars_val.mgwpool_idx;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003973 }
Harald Welte336820c2018-05-31 20:34:52 +02003974 vc_conn := MSC_ConnHdlr.create(id);
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003975 f_connect_handler(vc_conn, bssap_idx, mgwpool_idx);
Neels Hofmeyrda436782021-07-20 22:09:06 +02003976 return vc_conn;
3977}
3978
3979function f_start_handler_run(MSC_ConnHdlr vc_conn, void_fn fn, template (omit) TestHdlrParams pars := omit)
3980runs on test_CT return MSC_ConnHdlr {
3981 var charstring id := testcasename();
Harald Weltea0630032018-03-20 21:09:55 +01003982 vc_conn.start(f_handler_init(fn, id, pars));
Harald Weltec1a2fff2017-12-17 11:06:19 +01003983 return vc_conn;
3984}
3985
Neels Hofmeyrda436782021-07-20 22:09:06 +02003986function f_start_handler(void_fn fn, template (omit) TestHdlrParams pars := omit)
3987runs on test_CT return MSC_ConnHdlr {
3988 return f_start_handler_run(f_start_handler_create(pars), fn, pars);
3989}
3990
Harald Weltea0630032018-03-20 21:09:55 +01003991/* first function inside ConnHdlr component; sets g_pars + starts function */
3992private function f_handler_init(void_fn fn, charstring id, template (omit) TestHdlrParams pars := omit)
3993runs on MSC_ConnHdlr {
3994 if (isvalue(pars)) {
3995 g_pars := valueof(pars);
3996 }
3997 fn.apply(id);
3998}
3999
Oliver Smith26a3db72021-07-09 13:51:29 +02004000private function f_vty_encryption_a5(charstring options) runs on test_CT {
4001 f_vty_transceive(BSCVTY, "configure terminal");
4002 f_vty_transceive(BSCVTY, "network");
4003 f_vty_transceive(BSCVTY, "encryption a5 " & options);
4004 f_vty_transceive(BSCVTY, "exit");
4005 f_vty_transceive(BSCVTY, "exit");
4006}
4007
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01004008const charstring VTY_A5_DEFAULT := "0 1 3";
4009
Oliver Smith26a3db72021-07-09 13:51:29 +02004010private function f_vty_encryption_a5_reset() runs on test_CT {
4011 /* keep in sync with docker-playground.git ttcn3-bsc-test/osmo-bsc.cfg */
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01004012 f_vty_encryption_a5(VTY_A5_DEFAULT);
Oliver Smith26a3db72021-07-09 13:51:29 +02004013}
4014
Harald Welte3c86ea02018-05-10 22:28:05 +02004015/* Establish signalling channel (non-assignment case) followed by cipher mode */
4016private function f_tc_ciph_mode_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02004017 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4018 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte3c86ea02018-05-10 22:28:05 +02004019 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Philipp Maier23000732018-05-18 11:25:37 +02004020 ass_cmd.pdu.bssmap.assignmentRequest.circuitIdentityCode := omit;
4021 ass_cmd.pdu.bssmap.assignmentRequest.aoIPTransportLayer := omit;
4022 exp_compl.pdu.bssmap.assignmentComplete.circuitIdentityCode := omit;
4023 exp_compl.pdu.bssmap.assignmentComplete.aoIPTransportLayer := omit;
Harald Welte3c86ea02018-05-10 22:28:05 +02004024
Philipp Maier23000732018-05-18 11:25:37 +02004025 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004026 f_perform_clear();
Harald Welte3c86ea02018-05-10 22:28:05 +02004027}
4028testcase TC_ciph_mode_a5_0() runs on test_CT {
4029 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004030 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004031 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
4032
4033 f_init(1, true);
4034 f_sleep(1.0);
4035 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4036 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004037 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004038}
4039testcase TC_ciph_mode_a5_1() runs on test_CT {
4040 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004041 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004042 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
4043
4044 f_init(1, true);
4045 f_sleep(1.0);
4046 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4047 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004048 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004049}
Oliver Smith50b98122021-07-09 15:00:28 +02004050/* OS#4975: verify that A5/2 is preferred over A5/0 */
4051testcase TC_ciph_mode_a5_2_0() runs on test_CT {
4052 var MSC_ConnHdlr vc_conn;
4053 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4054
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01004055 pars.encr := f_encr_params('05'O, '04'O); /* A5/0 and A5/2 (0x01|0x04)*/
Oliver Smith50b98122021-07-09 15:00:28 +02004056
4057 f_init(1, true);
4058 f_vty_encryption_a5("0 1 2 3");
4059 f_sleep(1.0);
4060 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4061 vc_conn.done;
4062 f_vty_encryption_a5_reset();
4063 f_shutdown_helper();
4064}
Oliver Smith1dff88d2021-07-09 08:45:51 +02004065/* OS#4975: verify that A5/1 is preferred over A5/2 */
4066testcase TC_ciph_mode_a5_2_1() runs on test_CT {
4067 var MSC_ConnHdlr vc_conn;
4068 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4069
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01004070 pars.encr := f_encr_params('06'O, '02'O); /* A5/1 and A5/2 (0x02|0x04)*/
Oliver Smith1dff88d2021-07-09 08:45:51 +02004071
4072 f_init(1, true);
4073 f_vty_encryption_a5("1 2");
4074 f_sleep(1.0);
4075 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4076 vc_conn.done;
4077 f_vty_encryption_a5_reset();
4078 f_shutdown_helper();
4079}
Harald Welte3c86ea02018-05-10 22:28:05 +02004080testcase TC_ciph_mode_a5_3() runs on test_CT {
4081 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004082 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004083 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
4084
4085 f_init(1, true);
4086 f_sleep(1.0);
4087 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4088 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004089 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004090}
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004091/* Establish a Signalling channel with A5/4 encryption. */
4092testcase TC_ciph_mode_a5_4() runs on test_CT {
4093 var MSC_ConnHdlr vc_conn;
4094 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4095 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Harald Welte3c86ea02018-05-10 22:28:05 +02004096
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004097 f_init(1, true);
Oliver Smith26a3db72021-07-09 13:51:29 +02004098 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004099 f_sleep(1.0);
4100 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4101 vc_conn.done;
Oliver Smith26a3db72021-07-09 13:51:29 +02004102 f_vty_encryption_a5_reset();
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004103 f_shutdown_helper();
4104}
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004105/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
4106private function f_tc_assignment_aoip_tla_v6(charstring id) runs on MSC_ConnHdlr {
4107 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4108 var PDU_BSSAP ass_cmd := f_gen_ass_req(aoip_tla := "::3");
4109 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4110 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4111
4112 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004113 f_perform_clear();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004114}
4115testcase TC_assignment_aoip_tla_v6() runs on test_CT {
4116 var MSC_ConnHdlr vc_conn;
4117 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4118
4119 f_init(1, true);
4120 f_sleep(1.0);
4121 vc_conn := f_start_handler(refers(f_tc_assignment_aoip_tla_v6), pars);
4122 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004123 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004124}
4125
Harald Welte3c86ea02018-05-10 22:28:05 +02004126
4127/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
Harald Welte651fcdc2018-05-10 20:23:16 +02004128private function f_tc_assignment_fr_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02004129 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4130 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004131
Harald Welte552620d2017-12-16 23:21:36 +01004132 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4133 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte73cd2712017-12-17 00:44:52 +01004134
Harald Weltea0630032018-03-20 21:09:55 +01004135 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004136 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004137}
Harald Welte552620d2017-12-16 23:21:36 +01004138testcase TC_assignment_fr_a5_0() runs on test_CT {
4139 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004140 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004141 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
Harald Welte552620d2017-12-16 23:21:36 +01004142
Harald Welte89d42e82017-12-17 16:42:41 +01004143 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004144 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004145 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004146 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004147 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004148}
Harald Welte552620d2017-12-16 23:21:36 +01004149testcase TC_assignment_fr_a5_1() runs on test_CT {
Harald Weltec1a2fff2017-12-17 11:06:19 +01004150 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004151 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004152 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004153
Harald Welte89d42e82017-12-17 16:42:41 +01004154 f_init(1, true);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004155 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004156 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4157 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004158 f_shutdown_helper();
Harald Welte651fcdc2018-05-10 20:23:16 +02004159}
4160testcase TC_assignment_fr_a5_3() runs on test_CT {
4161 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004162 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004163 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004164
Harald Welte651fcdc2018-05-10 20:23:16 +02004165 f_init(1, true);
4166 f_sleep(1.0);
4167 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004168 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004169 f_shutdown_helper();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004170}
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004171/* Establish a Signalling channel and re-assign to TCH/F with A5/4 encryption. */
4172testcase TC_assignment_fr_a5_4() runs on test_CT {
4173 var MSC_ConnHdlr vc_conn;
4174 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4175 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
4176
4177 f_init(1, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02004178 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004179 f_sleep(1.0);
4180 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4181 vc_conn.done;
Oliver Smith7eabd312021-07-12 14:18:56 +02004182 f_vty_encryption_a5_reset();
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004183 f_shutdown_helper();
4184}
Harald Weltec1a2fff2017-12-17 11:06:19 +01004185
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +02004186/* Allow only A5/4, but omit the Kc128 IE from MSC's msg. Expect Cipher Mode Reject. */
4187testcase TC_assignment_fr_a5_4_fail() runs on test_CT {
4188 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4189 var MSC_ConnHdlr vc_conn;
4190
4191 f_init(1, true);
4192 f_sleep(1.0);
4193
4194 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8))); // A5/4 support, but Kc128 missing!
4195 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
4196 vc_conn.done;
4197 f_shutdown_helper();
4198}
4199
Harald Welte552620d2017-12-16 23:21:36 +01004200/* Expect ASSIGNMENT FAIL if mandatory IE is missing */
4201private function f_tc_assignment_fr_a5_1_codec_missing(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004202 g_pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004203 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02004204 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004205
4206 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02004207 /* Omit: ass_cmd.pdu.bssmap.assignmentRequest.codecList */
4208
Harald Weltea0630032018-03-20 21:09:55 +01004209 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004210 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004211}
Harald Welte552620d2017-12-16 23:21:36 +01004212testcase TC_assignment_fr_a5_1_codec_missing() runs on test_CT {
4213 var MSC_ConnHdlr vc_conn;
4214
Harald Welte89d42e82017-12-17 16:42:41 +01004215 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004216 f_sleep(1.0);
4217
Harald Welte8863fa12018-05-10 20:15:27 +02004218 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5_1_codec_missing));
Harald Welte552620d2017-12-16 23:21:36 +01004219 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004220 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004221}
4222
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004223private function f_TC_assignment_a5_not_sup(charstring id) runs on MSC_ConnHdlr {
4224 var template PDU_BSSAP exp_ass_cpl := f_gen_exp_compl();
4225 var PDU_BSSAP exp_ass_req := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004226
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004227 exp_ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4228 exp_ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4229
4230 /* this is like the beginning of f_establish_fully(), but only up to ciphering reject */
4231
4232 var BSSMAP_FIELD_CodecType codecType;
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004233
4234 codecType := exp_ass_req.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType;
4235 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
4236
4237 f_create_chan_and_exp();
4238 /* we should now have a COMPL_L3 at the MSC */
4239
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004240 /* Start ciphering, expect Cipher Mode Reject */
Neels Hofmeyr6c388f22021-06-11 02:36:56 +02004241 f_cipher_mode(g_pars.encr, exp_fail := true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004242 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004243}
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004244testcase TC_assignment_fr_a5_not_sup() runs on test_CT {
4245 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004246 var MSC_ConnHdlr vc_conn;
4247
Harald Welte89d42e82017-12-17 16:42:41 +01004248 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004249 f_sleep(1.0);
4250
Neels Hofmeyr0588cad2021-06-11 01:38:18 +02004251 pars.encr := valueof(t_EncrParams('20'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004252 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004253 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004254 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004255}
4256
4257
Harald Welte4532e0a2017-12-23 02:05:44 +01004258private function f_tc_assignment_sign(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004259 g_pars := f_gen_test_hdlr_pars();
Harald Welte4532e0a2017-12-23 02:05:44 +01004260 var template PDU_BSSAP exp_compl := tr_BSSMAP_AssignmentComplete(omit, omit);
Philipp Maier48604732018-10-09 15:00:37 +02004261 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte4532e0a2017-12-23 02:05:44 +01004262 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004263
4264 f_statsd_reset();
Harald Weltea0630032018-03-20 21:09:55 +01004265 f_establish_fully(ass_cmd, exp_compl);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004266
4267 var StatsDExpects expect := {
Daniel Willmannc5398f72020-09-21 10:41:35 +02004268 { name := "TTCN3.bts.0.chreq.total", mtype := "c", min := 1, max := 1},
4269 { name := "TTCN3.bts.0.chreq.successful", mtype := "c", min := 1, max := 1},
Daniel Willmannebdecc02020-08-12 15:30:17 +02004270 { name := "TTCN3.bsc.0.assignment.attempted", mtype := "c", min := 1, max := 1},
4271 { name := "TTCN3.bsc.0.assignment.completed", mtype := "c", min := 1, max := 1}
4272 };
4273 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004274 f_perform_clear();
Harald Welte4532e0a2017-12-23 02:05:44 +01004275}
4276
4277testcase TC_assignment_sign() runs on test_CT {
4278 var MSC_ConnHdlr vc_conn;
4279
4280 f_init(1, true);
4281 f_sleep(1.0);
4282
Harald Welte8863fa12018-05-10 20:15:27 +02004283 vc_conn := f_start_handler(refers(f_tc_assignment_sign));
Harald Welte4532e0a2017-12-23 02:05:44 +01004284 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004285 f_shutdown_helper();
Harald Welte4532e0a2017-12-23 02:05:44 +01004286}
4287
Harald Welte60aa5762018-03-21 19:33:13 +01004288/***********************************************************************
4289 * Codec (list) testing
4290 ***********************************************************************/
4291
4292/* check if the given rsl_mode is compatible with the a_elem */
4293private function f_match_codec(BSSMAP_FIELD_CodecElement a_elem, RSL_IE_ChannelMode rsl_mode)
4294return boolean {
4295 select (a_elem.codecType) {
4296 case (GSM_FR) {
4297 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM1))) {
4298 return true;
4299 }
4300 }
4301 case (GSM_HR) {
4302 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM1))) {
4303 return true;
4304 }
4305 }
4306 case (GSM_EFR) {
4307 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM2))) {
4308 return true;
4309 }
4310 }
4311 case (FR_AMR) {
4312 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM3))) {
4313 return true;
4314 }
4315 }
4316 case (HR_AMR) {
4317 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM3))) {
4318 return true;
4319 }
4320 }
4321 case else { }
4322 }
4323 return false;
4324}
4325
4326/* check if the given rsl_mode is compatible with the a_list */
4327private function f_match_codecs(BSSMAP_IE_SpeechCodecList a_list, RSL_IE_ChannelMode rsl_mode)
4328return boolean {
4329 for (var integer i := 0; i < sizeof(a_list); i := i+1) {
4330 if (f_match_codec(a_list.codecElements[i], rsl_mode)) {
4331 return true;
4332 }
4333 }
4334 return false;
4335}
4336
4337/* determine BSSMAP_IE_ChannelType from *first* element of BSSMAP_FIELD_CodecElement */
Philipp Maier61f6b572018-07-06 14:03:38 +02004338function f_BSSMAP_chtype_from_codec(BSSMAP_FIELD_CodecElement a_elem)
Harald Welte60aa5762018-03-21 19:33:13 +01004339return BSSMAP_IE_ChannelType {
4340 /* FIXME: actually look at all elements of BSSMAP_IE_SpeechCodecList */
4341 var BSSMAP_IE_ChannelType ret := valueof(ts_BSSMAP_IE_ChannelType);
4342 select (a_elem.codecType) {
4343 case (GSM_FR) {
4344 ret.channelRateAndType := ChRate_TCHF;
4345 ret.speechId_DataIndicator := Spdi_TCHF_FR;
4346 }
4347 case (GSM_HR) {
4348 ret.channelRateAndType := ChRate_TCHH;
4349 ret.speechId_DataIndicator := Spdi_TCHH_HR;
4350 }
4351 case (GSM_EFR) {
4352 ret.channelRateAndType := ChRate_TCHF;
4353 ret.speechId_DataIndicator := Spdi_TCHF_EFR;
4354 }
4355 case (FR_AMR) {
4356 ret.channelRateAndType := ChRate_TCHF;
4357 ret.speechId_DataIndicator := Spdi_TCHF_AMR;
4358 }
4359 case (HR_AMR) {
4360 ret.channelRateAndType := ChRate_TCHH;
4361 ret.speechId_DataIndicator := Spdi_TCHH_AMR;
4362 }
4363 case else {
4364 setverdict(fail, "Unsupported codec ", a_elem);
Daniel Willmannafce8662018-07-06 23:11:32 +02004365 mtc.stop;
Harald Welte60aa5762018-03-21 19:33:13 +01004366 }
4367 }
4368 return ret;
4369}
4370
Harald Weltea63b9102018-03-22 20:36:16 +01004371private function f_rsl_chmod_tmpl_from_codec(BSSMAP_FIELD_CodecElement a_elem)
4372return template RSL_IE_Body {
4373 var template RSL_IE_Body mode_ie := {
4374 chan_mode := {
4375 len := ?,
4376 reserved := ?,
4377 dtx_d := ?,
4378 dtx_u := ?,
4379 spd_ind := RSL_SPDI_SPEECH,
4380 ch_rate_type := -,
Oliver Smith0033b122023-02-28 13:30:53 +01004381 u := { speech := - }
Harald Weltea63b9102018-03-22 20:36:16 +01004382 }
4383 }
4384
4385 select (a_elem.codecType) {
4386 case (GSM_FR) {
4387 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004388 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM1;
Harald Weltea63b9102018-03-22 20:36:16 +01004389 }
4390 case (GSM_HR) {
4391 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
Oliver Smith0033b122023-02-28 13:30:53 +01004392 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM1;
Harald Weltea63b9102018-03-22 20:36:16 +01004393 }
4394 case (GSM_EFR) {
4395 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004396 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM2;
Harald Weltea63b9102018-03-22 20:36:16 +01004397 }
4398 case (FR_AMR) {
4399 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004400 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM3;
Harald Weltea63b9102018-03-22 20:36:16 +01004401 }
4402 case (HR_AMR) {
4403 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
Oliver Smith0033b122023-02-28 13:30:53 +01004404 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM3;
Harald Weltea63b9102018-03-22 20:36:16 +01004405 }
4406 }
4407 return mode_ie;
4408}
4409
Harald Welte60aa5762018-03-21 19:33:13 +01004410type record CodecListTest {
4411 BSSMAP_IE_SpeechCodecList codec_list,
4412 charstring id
4413}
4414type record of CodecListTest CodecListTests
4415
4416private function f_TC_assignment_codec(charstring id) runs on MSC_ConnHdlr {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004417 f_assignment_codec(id);
4418}
4419
4420private function f_assignment_codec(charstring id, boolean do_perform_clear := true) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02004421 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02004422 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Harald Welte60aa5762018-03-21 19:33:13 +01004423
4424 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004425 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte79f3f542018-05-25 20:02:37 +02004426 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4427 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
4428 g_pars.ass_codec_list.codecElements[0];
Philipp Maierd0e64b02019-03-13 14:15:23 +01004429 if (isvalue(g_pars.expect_mr_s0_s7)) {
4430 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
4431 g_pars.expect_mr_s0_s7;
4432 }
Harald Welte79f3f542018-05-25 20:02:37 +02004433 }
Harald Welte60aa5762018-03-21 19:33:13 +01004434 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4435 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
Harald Welte60aa5762018-03-21 19:33:13 +01004436 log("expecting ASS COMPL like this: ", exp_compl);
4437
4438 f_establish_fully(ass_cmd, exp_compl);
Harald Weltea63b9102018-03-22 20:36:16 +01004439
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004440 if (not g_pars.expect_channel_mode_modify) {
4441 /* Verify that the RSL-side activation actually matches our expectations */
4442 var RSL_Message rsl := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
Harald Weltea63b9102018-03-22 20:36:16 +01004443
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004444 var RSL_IE_Body mode_ie;
4445 if (f_rsl_find_ie(rsl, RSL_IE_CHAN_MODE, mode_ie) == false) {
4446 setverdict(fail, "Couldn't find CHAN_MODE IE");
Daniel Willmannafce8662018-07-06 23:11:32 +02004447 mtc.stop;
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004448 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004449 var template RSL_IE_Body t_mode_ie := f_rsl_chmod_tmpl_from_codec(g_pars.ass_codec_list.codecElements[0]);
4450 if (not match(mode_ie, t_mode_ie)) {
4451 log("mode_ie ", mode_ie, " != t_mode_ie ", t_mode_ie);
4452 setverdict(fail, "RSL Channel Mode IE doesn't match expectation");
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004453 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004454
4455 var RSL_IE_Body mr_conf;
4456 if (g_pars.expect_mr_conf_ie != omit) {
4457 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == false) {
4458 setverdict(fail, "Missing MR CONFIG IE in RSL Chan Activ");
4459 mtc.stop;
4460 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004461 log("found RSL MR CONFIG IE: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004462
4463 if (not match(mr_conf, g_pars.expect_mr_conf_ie)) {
Vadim Yanitskiy8b189372022-09-14 17:31:17 +07004464 setverdict(fail, "RSL MR CONFIG IE does not match expectation. ",
4465 "Expected: ", g_pars.expect_mr_conf_ie, ", got: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004466 }
4467 } else {
4468 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == true) {
4469 log("found RSL MR CONFIG IE: ", mr_conf);
4470 setverdict(fail, "Found MR CONFIG IE in RSL Chan Activ, expecting omit");
4471 mtc.stop;
4472 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004473 }
4474 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004475
4476 if (do_perform_clear) {
4477 f_perform_clear();
4478 }
Harald Welte60aa5762018-03-21 19:33:13 +01004479}
4480
Philipp Maierd0e64b02019-03-13 14:15:23 +01004481private function f_TC_assignment_codec_fail(charstring id) runs on MSC_ConnHdlr {
4482
4483 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4484 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4485
4486 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004487 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maierd0e64b02019-03-13 14:15:23 +01004488 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4489 }
4490 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4491 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
4492 log("expecting ASS FAIL like this: ", exp_fail);
4493
4494 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004495 f_perform_clear();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004496}
4497
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004498const CounterNameVals counternames_bsc_bts_assignment := {
4499 { "assignment:attempted", 0 },
4500 { "assignment:completed", 0 },
4501 { "assignment:stopped", 0 },
4502 { "assignment:no_channel", 0 },
4503 { "assignment:timeout", 0 },
4504 { "assignment:failed", 0 },
4505 { "assignment:error", 0 }
4506};
4507
4508const CounterNameVals counternames_bts_assignment := {
4509 { "assignment:attempted_sign", 0 },
4510 { "assignment:attempted_speech", 0 },
4511 { "assignment:completed_sign", 0 },
4512 { "assignment:completed_speech", 0 },
4513 { "assignment:stopped_sign", 0 },
4514 { "assignment:stopped_speech", 0 },
4515 { "assignment:no_channel_sign", 0 },
4516 { "assignment:no_channel_speech", 0 },
4517 { "assignment:timeout_sign", 0 },
4518 { "assignment:timeout_speech", 0 },
4519 { "assignment:failed_sign", 0 },
4520 { "assignment:failed_speech", 0 },
4521 { "assignment:error_sign", 0 },
4522 { "assignment:error_speech", 0 }
4523};
4524
4525function f_ctrs_bsc_and_bts_assignment_init(integer bts_count := NUM_BTS) runs on test_CT {
4526 var CounterNameVals bts_names := counternames_bsc_bts_assignment & counternames_bts_assignment;
4527 f_ctrs_bts_init(bts_count, bts_names);
4528 f_ctrs_bsc_init(counternames_bsc_bts_assignment);
4529}
4530
Harald Welte60aa5762018-03-21 19:33:13 +01004531testcase TC_assignment_codec_fr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004532 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004533 var MSC_ConnHdlr vc_conn;
4534
4535 f_init(1, true);
4536 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004537 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004538
4539 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004540 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004541 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004542
4543 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4544 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4545 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4546 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4547 f_ctrs_bts_verify();
4548
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004549 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004550}
4551
4552testcase TC_assignment_codec_hr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004553 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004554 var MSC_ConnHdlr vc_conn;
4555
4556 f_init(1, true);
4557 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004558 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004559
4560 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004561 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004562 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004563
4564 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4565 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4566 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4567 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4568 f_ctrs_bts_verify();
4569
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004570 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004571}
4572
4573testcase TC_assignment_codec_efr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004574 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004575 var MSC_ConnHdlr vc_conn;
4576
4577 f_init(1, true);
4578 f_sleep(1.0);
4579
4580 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecEFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004581 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004582 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004583 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004584}
4585
Philipp Maierd0e64b02019-03-13 14:15:23 +01004586/* Allow 5,90k only (current default config) */
4587private function f_allow_amr_rate_5_90k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004588 f_vty_cfg_msc(BSCVTY, 0, {
4589 "amr-config 12_2k forbidden",
4590 "amr-config 10_2k forbidden",
4591 "amr-config 7_95k forbidden",
4592 "amr-config 7_40k forbidden",
4593 "amr-config 6_70k forbidden",
4594 "amr-config 5_90k allowed",
4595 "amr-config 5_15k forbidden",
4596 "amr-config 4_75k forbidden"
4597 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004598}
4599
4600/* Allow 4,75k, 5,90k, 4,70k and 12,2k, which are the most common rates
4601 * ("Config-NB-Code = 1") */
4602private function f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004603 f_vty_cfg_msc(BSCVTY, 0, {
4604 "amr-config 12_2k allowed",
4605 "amr-config 10_2k forbidden",
4606 "amr-config 7_95k forbidden",
4607 "amr-config 7_40k allowed",
4608 "amr-config 6_70k forbidden",
4609 "amr-config 5_90k allowed",
4610 "amr-config 5_15k forbidden",
4611 "amr-config 4_75k allowed"
4612 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004613}
4614
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004615private function f_vty_amr_start_mode_set(boolean fr, charstring startmode) runs on test_CT {
4616 var charstring tch;
4617 if (fr) {
4618 tch := "tch-f";
4619 } else {
4620 tch := "tch-h";
4621 }
4622 f_vty_cfg_bts(BSCVTY, 0, { "amr " & tch & " start-mode " & startmode });
4623}
4624
4625/* Set the AMR start-mode for this TCH back to the default configuration. */
4626private function f_vty_amr_start_mode_restore(boolean fr) runs on test_CT {
4627 f_vty_amr_start_mode_set(fr, "auto");
4628}
4629
Harald Welte60aa5762018-03-21 19:33:13 +01004630testcase TC_assignment_codec_amr_f() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004631 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004632 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004633
4634 /* Note: This setups the codec configuration. The parameter payload in
4635 * mr_conf must be consistant with the parameter codecElements in pars
4636 * and also must match the amr-config in osmo-bsc.cfg! */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004637 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004638 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004639 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004640 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004641
Harald Welte60aa5762018-03-21 19:33:13 +01004642 f_init(1, true);
4643 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004644 f_vty_amr_start_mode_set(true, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004645 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004646
Harald Welte8863fa12018-05-10 20:15:27 +02004647 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004648 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004649
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004650 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4651 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4652 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4653 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4654 f_ctrs_bts_verify();
4655
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004656 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004657 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004658}
4659
4660testcase TC_assignment_codec_amr_h() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004661 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004662 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004663
4664 /* See note above */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004665 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004666 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004667 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004668 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004669
Harald Welte60aa5762018-03-21 19:33:13 +01004670 f_init(1, true);
4671 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004672 f_vty_amr_start_mode_set(false, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004673 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004674
Harald Welte8863fa12018-05-10 20:15:27 +02004675 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004676 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004677
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004678 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4679 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4680 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4681 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4682 f_ctrs_bts_verify();
4683
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004684 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004685 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004686}
4687
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004688/* Establish signalling on a TCH/F lchan, and then switch to speech mode without a new Assignment. */
4689testcase TC_assignment_codec_fr_by_mode_modify() runs on test_CT {
4690 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4691 var MSC_ConnHdlr vc_conn;
4692
4693 f_init(1, true);
4694 f_sleep(1.0);
4695
4696 /* By disabling all SDCCH, the MS should be given a TCH/F for signalling. Then activating an FR codec should
4697 * merely do a Channel Mode Modify, and not assign to a new lchan. f_establish_fully() already accounts for
4698 * expecting a Channel Mode Modify if the channel type is compatible. */
4699 f_disable_all_sdcch();
4700 f_disable_all_tch_h();
4701
4702 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4703 pars.expect_channel_mode_modify := true;
4704 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4705 vc_conn.done;
4706
4707 f_enable_all_sdcch();
4708 f_enable_all_tch();
4709 f_shutdown_helper();
4710}
4711
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004712/* 'amr start-mode auto' should not keep the (unused) 'smod' bits from previous configuration */
4713testcase TC_assignment_codec_amr_startmode_cruft() runs on test_CT {
4714 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4715 var MSC_ConnHdlr vc_conn;
4716
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004717 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4718 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
4719 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy36fe9582022-09-14 15:25:04 +07004720 pars.expect_mr_conf_ie := c_mr_conf_5_90;
4721 pars.expect_mr_conf_ie.multirate_cfg.icmi := false; /* expect ICMI=0, smod=00: */
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004722
4723 f_init(1, true);
4724 f_sleep(1.0);
4725
4726 /* First set nonzero start mode bits */
4727 f_vty_amr_start_mode_set(true, "4");
4728 /* Now set to auto, and expect the startmode bits to be zero in the message, i.e. ensure that osmo-bsc does not
4729 * let the startmode bits stick around and has deterministic MultiRate config for 'start-mode auto'; that is
4730 * ensured by above '2004'O, where 'x0xx'O indicates ICMI = 0, spare = 0, smod = 00. */
4731 f_vty_amr_start_mode_set(true, "auto");
4732
4733 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4734 vc_conn.done;
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004735
4736 /* Clear the startmode bits to not affect subsequent tests, in case the bits should indeed stick around. */
4737 f_vty_amr_start_mode_set(true, "1");
4738 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004739 f_shutdown_helper();
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004740}
4741
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004742function f_TC_assignment_codec_amr(boolean fr, RSL_IE_MultirateCfg mr_cfg,
4743 bitstring s8_s0, bitstring exp_s8_s0,
4744 charstring start_mode := "1")
Philipp Maierd0e64b02019-03-13 14:15:23 +01004745runs on test_CT {
4746
4747 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4748 var MSC_ConnHdlr vc_conn;
4749
Philipp Maierd0e64b02019-03-13 14:15:23 +01004750 if (fr) {
4751 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4752 } else {
4753 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4754 }
4755 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4756 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004757 pars.expect_mr_conf_ie := { multirate_cfg := mr_cfg };
Philipp Maierd0e64b02019-03-13 14:15:23 +01004758 pars.expect_mr_s0_s7 := exp_s8_s0;
4759
4760 f_init(1, true);
4761 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004762 f_vty_amr_start_mode_set(fr, start_mode);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004763 f_sleep(1.0);
4764
4765 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4766 vc_conn.done;
4767 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004768 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004769}
4770
4771function f_TC_assignment_codec_amr_fail(boolean fr, bitstring s8_s0)
4772runs on test_CT {
4773
4774 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4775 var MSC_ConnHdlr vc_conn;
4776
4777 if (fr) {
4778 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4779 } else {
4780 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4781 }
4782 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4783 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
4784
4785 f_init(1, true);
4786 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004787 f_vty_amr_start_mode_set(fr, "1");
Philipp Maierd0e64b02019-03-13 14:15:23 +01004788 f_sleep(1.0);
4789
4790 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fail), pars);
4791 vc_conn.done;
4792 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004793 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004794}
4795
Philipp Maierd0e64b02019-03-13 14:15:23 +01004796/* Set S1, we expect an AMR multirate configuration IE with all four rates
4797 * set. */
4798testcase TC_assignment_codec_amr_f_S1() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004799 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4800 params := '20882208'O));
4801 f_TC_assignment_codec_amr(true, mr_cfg, '00000011'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004802 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004803}
4804
4805/* Set S1, we expect an AMR multirate configuration IE with the lower three
4806 * rates set. */
4807testcase TC_assignment_codec_amr_h_S1() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004808 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4809 params := '208820'O));
4810 f_TC_assignment_codec_amr(false, mr_cfg, '00000010'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004811 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004812}
4813
4814/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4815 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4816testcase TC_assignment_codec_amr_f_S124() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004817 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4818 params := '20882208'O));
4819 f_TC_assignment_codec_amr(true, mr_cfg, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004820 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004821}
4822
4823/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4824 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4825testcase TC_assignment_codec_amr_h_S124() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004826 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4827 params := '208820'O));
4828 f_TC_assignment_codec_amr(false, mr_cfg, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004829 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004830}
4831
4832/* The following block of tests selects more and more rates until all four
4833 * possible rates are in the active set (full rate) */
4834testcase TC_assignment_codec_amr_f_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004835 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4836 f_TC_assignment_codec_amr(true, mr_cfg, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004837 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004838}
4839
4840testcase TC_assignment_codec_amr_f_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004841 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4842 params := '2080'O));
4843 f_TC_assignment_codec_amr(true, mr_cfg, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004844 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004845}
4846
4847testcase TC_assignment_codec_amr_f_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004848 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4849 params := '208820'O));
4850 f_TC_assignment_codec_amr(true, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004851 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004852}
4853
4854testcase TC_assignment_codec_amr_f_S0247() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004855 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4856 params := '20882208'O));
4857 f_TC_assignment_codec_amr(true, mr_cfg, '10010101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004858 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004859}
4860
4861/* The following block of tests selects more and more rates until all three
4862 * possible rates are in the active set (half rate) */
4863testcase TC_assignment_codec_amr_h_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004864 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4865 f_TC_assignment_codec_amr(false, mr_cfg, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004866 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004867}
4868
4869testcase TC_assignment_codec_amr_h_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004870 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4871 params := '2080'O));
4872 f_TC_assignment_codec_amr(false, mr_cfg, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004873 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004874}
4875
4876testcase TC_assignment_codec_amr_h_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004877 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4878 params := '208820'O));
4879 f_TC_assignment_codec_amr(false, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004880 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004881}
4882
4883/* The following block tests what happens when the MSC does offer rate
4884 * configurations that are not supported by the BSC. Normally such situations
4885 * should not happen because the MSC gets informed by the BSC in advance via
4886 * the L3 COMPLETE message which rates are applicable. The MSC should not try
4887 * to offer rates that are not applicable anyway. */
4888
4889testcase TC_assignment_codec_amr_h_S0247() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004890 /* Try to include 12,2k in into the active set even though the channel
4891 * is half rate only. The BSC is expected to remove the 12,0k */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004892 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4893 params := '208820'O));
4894 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004895 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004896}
4897
4898testcase TC_assignment_codec_amr_f_S01234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004899 /* See what happens when all rates are selected at once. Since then
4900 * Also S1 is selected, this setting will be prefered and we should
4901 * get 12.2k, 7,40k, 5,90k, and 4,75k in the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004902 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4903 params := '20882208'O));
4904 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004905 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004906}
4907
4908testcase TC_assignment_codec_amr_f_S0234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004909 /* Same as above, but with S1 missing, the MSC is then expected to
4910 * select the currently supported rates, which are also 12.2k, 7,40k,
4911 * 5,90k, and 4,75k, into the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004912 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4913 params := '20882208'O));
4914 f_TC_assignment_codec_amr(true, mr_cfg, '11111101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004915 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004916}
4917
4918testcase TC_assignment_codec_amr_f_zero() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004919 /* Try to select no rates at all */
4920 f_TC_assignment_codec_amr_fail(true, '00000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004921 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004922}
4923
4924testcase TC_assignment_codec_amr_f_unsupp() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004925 /* Try to select only unsupported rates */
4926 f_TC_assignment_codec_amr_fail(true, '01101000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004927 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004928}
4929
4930testcase TC_assignment_codec_amr_h_S7() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004931 /* Try to select 12,2k for half rate */
4932 f_TC_assignment_codec_amr_fail(false, '10000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004933 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004934}
4935
Neels Hofmeyr21863562020-11-26 00:34:33 +00004936testcase TC_assignment_codec_amr_f_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004937 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
4938 codec_modes := '10010101'B,
4939 params := '20882208'O));
4940 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004941 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004942}
4943
4944testcase TC_assignment_codec_amr_h_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004945 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
4946 codec_modes := '00010101'B,
4947 params := '208820'O));
4948 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B,
Neels Hofmeyr21863562020-11-26 00:34:33 +00004949 start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004950 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004951}
4952
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004953testcase TC_assignment_codec_amr_f_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004954 /* "amr tch-f modes 0 2 4 7" => total 4 modes and start mode 4 => '11'B on the wire */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004955 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 3,
4956 codec_modes := '10010101'B,
4957 params := '20882208'O));
4958 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004959 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004960}
4961
4962testcase TC_assignment_codec_amr_h_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004963 /* "amr tch-h modes 0 2 4" => total 3 modes and start mode 4 => '10'B on the wire */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004964 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 2,
4965 codec_modes := '00010101'B,
4966 params := '208820'O));
4967 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004968 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004969}
4970
Philipp Maierac09bfc2019-01-08 13:41:39 +01004971private function f_disable_all_tch_f() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004972 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 borken");
4973 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 borken");
4974 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 borken");
4975 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004976}
4977
4978private function f_disable_all_tch_h() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004979 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 borken");
4980 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004981}
4982
4983private function f_enable_all_tch() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004984 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 unused");
4985 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 unused");
4986 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 unused");
4987 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 unused");
4988 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 unused");
4989 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 unused");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004990}
4991
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004992private function f_disable_all_sdcch() runs on test_CT {
4993 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 borken");
4994 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 borken");
4995 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 borken");
4996 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 borken");
4997}
4998
4999private function f_enable_all_sdcch() runs on test_CT {
5000 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 unused");
5001 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 unused");
5002 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 unused");
5003 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 unused");
5004}
5005
Philipp Maierac09bfc2019-01-08 13:41:39 +01005006/* Allow HR only */
5007private function f_TC_assignment_codec_xr_exhausted_req_hr(charstring id) runs on MSC_ConnHdlr {
5008 g_pars := f_gen_test_hdlr_pars();
5009 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5010 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5011 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5012 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
5013 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
5014 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5015 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005016 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005017}
5018
5019/* Allow FR only */
5020private function f_TC_assignment_codec_xr_exhausted_req_fr(charstring id) runs on MSC_ConnHdlr {
5021 g_pars := f_gen_test_hdlr_pars();
5022 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5023 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5024 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5025 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
5026 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
5027 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5028 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005029 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005030}
5031
5032/* Allow HR only (expect assignment failure) */
5033private function f_TC_assignment_codec_xr_exhausted_req_hr_fail(charstring id) runs on MSC_ConnHdlr {
5034 g_pars := f_gen_test_hdlr_pars();
5035 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5036 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
5037 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5038 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
5039 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
5040 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5041 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005042 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005043}
5044
5045/* Allow FR only (expect assignment failure) */
5046private function f_TC_assignment_codec_xr_exhausted_req_fr_fail(charstring id) runs on MSC_ConnHdlr {
5047 g_pars := f_gen_test_hdlr_pars();
5048 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5049 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
5050 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5051 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
5052 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
5053 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5054 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005055 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005056}
5057
5058/* Allow FR and HR, but prefer FR */
5059private function f_TC_assignment_codec_fr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5060 g_pars := f_gen_test_hdlr_pars();
5061 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5062 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5063 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5064 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5065 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5066 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5067 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5068 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005069 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005070}
5071
5072/* Allow FR and HR, but prefer HR */
5073private function f_TC_assignment_codec_fr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5074 g_pars := f_gen_test_hdlr_pars();
5075 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5076 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5077 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5078 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5079 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5080 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5081 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5082 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005083 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005084}
5085
5086/* Allow FR and HR, but prefer FR */
5087private function f_TC_assignment_codec_hr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5088 g_pars := f_gen_test_hdlr_pars();
5089 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5090 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5091 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5092 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5093 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5094 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5095 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5096 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005097 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005098}
5099
5100/* Allow FR and HR, but prefer HR */
5101private function f_TC_assignment_codec_hr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5102 g_pars := f_gen_test_hdlr_pars();
5103 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5104 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5105 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5106 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5107 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5108 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5109 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5110 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005111 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005112}
5113
5114/* Request a HR channel while all FR channels are exhausted, this is expected
5115 * to work without conflicts */
5116testcase TC_assignment_codec_fr_exhausted_req_hr() runs on test_CT {
5117 var MSC_ConnHdlr vc_conn;
5118 f_init(1, true);
5119 f_sleep(1.0);
5120 f_enable_all_tch();
5121 f_disable_all_tch_f();
5122 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr));
5123 vc_conn.done;
5124 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005125 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005126}
5127
5128/* Request a FR channel while all FR channels are exhausted, this is expected
5129 * to fail. */
5130testcase TC_assignment_codec_fr_exhausted_req_fr() runs on test_CT {
5131 var MSC_ConnHdlr vc_conn;
5132 f_init(1, true);
5133 f_sleep(1.0);
5134 f_enable_all_tch();
5135 f_disable_all_tch_f();
5136 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr_fail));
5137 vc_conn.done;
5138 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005139 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005140}
5141
5142/* Request a FR (prefered) or alternatively a HR channel while all FR channels
5143 * are exhausted, this is expected to be resolved by selecting a HR channel. */
5144testcase TC_assignment_codec_fr_exhausted_req_fr_hr() runs on test_CT {
5145 var MSC_ConnHdlr vc_conn;
5146 f_init(1, true);
5147 f_sleep(1.0);
5148 f_enable_all_tch();
5149 f_disable_all_tch_f();
5150 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_fr_hr));
5151 vc_conn.done;
5152 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005153 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005154}
5155
5156/* Request a HR (prefered) or alternatively a FR channel while all FR channels
5157 * are exhausted, this is expected to work without conflicts. */
5158testcase TC_assignment_codec_fr_exhausted_req_hr_fr() runs on test_CT {
5159 var MSC_ConnHdlr vc_conn;
5160 f_init(1, true);
5161 f_sleep(1.0);
5162 f_enable_all_tch();
5163 f_disable_all_tch_f();
5164 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_hr_fr));
5165 vc_conn.done;
5166 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005167 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005168}
5169
5170/* Request a FR channel while all HR channels are exhausted, this is expected
5171 * to work without conflicts */
5172testcase TC_assignment_codec_hr_exhausted_req_fr() runs on test_CT {
5173 var MSC_ConnHdlr vc_conn;
5174 f_init(1, true);
5175 f_sleep(1.0);
5176 f_enable_all_tch();
5177 f_disable_all_tch_h();
5178 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr));
5179 vc_conn.done;
5180 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005181 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005182}
5183
5184/* Request a HR channel while all HR channels are exhausted, this is expected
5185 * to fail. */
5186testcase TC_assignment_codec_hr_exhausted_req_hr() runs on test_CT {
5187 var MSC_ConnHdlr vc_conn;
5188 f_init(1, true);
5189 f_sleep(1.0);
5190 f_enable_all_tch();
5191 f_disable_all_tch_h();
5192 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr_fail));
5193 vc_conn.done;
5194 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005195 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005196}
5197
5198/* Request a HR (prefered) or alternatively a FR channel while all HR channels
5199 * are exhausted, this is expected to be resolved by selecting a FR channel. */
5200testcase TC_assignment_codec_hr_exhausted_req_hr_fr() runs on test_CT {
5201 var MSC_ConnHdlr vc_conn;
5202 f_init(1, true);
5203 f_sleep(1.0);
5204 f_enable_all_tch();
5205 f_disable_all_tch_h();
5206 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_hr_fr));
5207 vc_conn.done;
5208 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005209 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005210}
5211
5212/* Request a FR (prefered) or alternatively a HR channel while all HR channels
5213 * are exhausted, this is expected to work without conflicts. */
5214testcase TC_assignment_codec_hr_exhausted_req_fr_hr() runs on test_CT {
5215 var MSC_ConnHdlr vc_conn;
5216 f_init(1, true);
5217 f_sleep(1.0);
5218 f_enable_all_tch();
5219 f_disable_all_tch_h();
5220 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_fr_hr));
5221 vc_conn.done;
5222 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005223 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005224}
5225
5226/* Allow FR and HR, but prefer HR */
5227private function f_TC_assignment_codec_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5228 g_pars := f_gen_test_hdlr_pars();
5229 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5230 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5231 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5232 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5233 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5234 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5235 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5236 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005237 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005238}
5239
5240/* Allow FR and HR, but prefer FR */
5241private function f_TC_assignment_codec_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5242 g_pars := f_gen_test_hdlr_pars();
5243 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5244 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5245 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5246 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5247 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5248 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5249 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5250 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005251 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005252}
5253
5254/* Request a HR (prefered) or alternatively a FR channel, it is expected that
5255 * HR, which is the prefered type, is selected. */
5256testcase TC_assignment_codec_req_hr_fr() runs on test_CT {
5257 var MSC_ConnHdlr vc_conn;
5258 f_init(1, true);
5259 f_sleep(1.0);
5260 f_enable_all_tch();
5261 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_hr_fr));
5262 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005263 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005264}
5265
5266/* Request a FR (prefered) or alternatively a HR channel, it is expected that
5267 * FR, which is the prefered type, is selected. */
5268testcase TC_assignment_codec_req_fr_hr() runs on test_CT {
5269 var MSC_ConnHdlr vc_conn;
5270 f_init(1, true);
5271 f_sleep(1.0);
5272 f_enable_all_tch();
5273 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_fr_hr));
5274 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005275 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005276}
5277
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005278/* request a signalling channel with all SDCCH exhausted, it is expected that a TCH will be selected */
5279private function f_TC_assignment_sdcch_exhausted_req_signalling(charstring id) runs on MSC_ConnHdlr {
5280 g_pars := f_gen_test_hdlr_pars();
5281 g_pars.ra := '02'O; /* RA containing reason=LU */
5282
5283 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5284 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5285 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5286 var template uint3_t tsc := ?;
5287
5288 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5289 f_create_bssmap_exp(l3_enc);
5290 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5291 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5292
5293 /* we should now have a COMPL_L3 at the MSC */
5294 timer T := 10.0;
5295 T.start;
5296 alt {
5297 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5298 [] T.timeout {
5299 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5300 }
5301 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005302
5303 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005304}
5305testcase TC_assignment_sdcch_exhausted_req_signalling() runs on test_CT {
5306 var MSC_ConnHdlr vc_conn;
5307 f_init(1, true);
5308 f_sleep(1.0);
5309 f_disable_all_sdcch();
5310 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_signalling));
5311 vc_conn.done;
5312 f_enable_all_sdcch();
5313 f_shutdown_helper();
5314}
5315
5316/* Request a signalling channel with all SDCCH exhausted, it is
5317 expected that no TCH will be selected for signalling and assigment will fail
5318 because it's dictated by VTY config */
5319testcase TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() runs on test_CT {
5320 var RSL_Message rsl_unused, rsl_msg;
5321 var GsmRrMessage rr;
5322 f_init(1, false);
5323 f_sleep(1.0);
5324 f_vty_allow_tch_for_signalling(false, 0);
5325 f_disable_all_sdcch();
5326
5327 /* RA containing reason=LU */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005328 f_ipa_tx(ts_RSL_CHAN_RQD('02'O, 2342));
5329 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005330 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
5331 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
5332 setverdict(fail, "Expected reject");
5333 }
5334
5335 f_vty_allow_tch_for_signalling(true, 0);
5336 f_enable_all_sdcch();
5337 f_shutdown_helper();
5338}
5339
5340/* Request a voice channel with all SDCCH exhausted, it is
5341 * expected that TCH channel will be allocated since the VTY option is only
5342 * aimed at signalling requests */
5343private function f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden(charstring id) runs on MSC_ConnHdlr {
5344 g_pars := f_gen_test_hdlr_pars();
5345 g_pars.ra := '43'O; /* RA containing reason=originating speech call*/
5346
5347 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5348 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5349 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5350 var template uint3_t tsc := ?;
5351
5352 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5353 f_create_bssmap_exp(l3_enc);
5354 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5355 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5356
5357 /* we should now have a COMPL_L3 at the MSC */
5358 timer T := 10.0;
5359 T.start;
5360 alt {
5361 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5362 [] T.timeout {
5363 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5364 }
5365 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005366 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005367}
5368testcase TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() runs on test_CT {
5369 var MSC_ConnHdlr vc_conn;
5370 f_init(1, true);
5371 f_sleep(1.0);
5372 f_vty_allow_tch_for_signalling(false, 0);
5373 f_disable_all_sdcch();
5374
5375 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden));
5376 vc_conn.done;
5377
5378 f_vty_allow_tch_for_signalling(true, 0);
5379 f_enable_all_sdcch();
5380 f_shutdown_helper();
5381}
5382
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005383/* Test Osmux setup BSC<->MSC */
5384testcase TC_assignment_osmux_cn() runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005385 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5386 var MSC_ConnHdlr vc_conn;
5387
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005388 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5389 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5390 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiyb9bf00f2022-09-14 15:35:37 +07005391 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02005392 pars.use_osmux_cn := true;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005393
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02005394 g_osmux_enabled_cn := true;
5395 f_init(1, true);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005396 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005397 f_vty_amr_start_mode_set(false, "1");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005398
5399 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5400 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005401
5402 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01005403 f_shutdown_helper();
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005404}
5405
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005406/* Test Osmux setup BTS<->BSC */
5407testcase TC_assignment_osmux_bts() runs on test_CT {
5408 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5409 var MSC_ConnHdlr vc_conn;
5410
5411 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5412 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5413 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005414 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005415 pars.use_osmux_bts := true;
5416
5417 g_osmux_enabled_bts := true;
5418 f_init(1, true);
5419 f_sleep(1.0);
5420 f_vty_amr_start_mode_set(false, "1");
5421
5422 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5423 vc_conn.done;
5424
5425 f_vty_amr_start_mode_restore(false);
5426 f_shutdown_helper();
5427}
5428
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +02005429/* Test non-AMR codecs still work fine as RTP when Osmux is enabled BTS<->BSC<->MSC */
5430testcase TC_assignment_codec_hr_osmux_on() runs on test_CT {
5431 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5432 var MSC_ConnHdlr vc_conn;
5433
5434 g_osmux_enabled_cn := true;
5435 g_osmux_enabled_bts := true;
5436 f_init(1, true);
5437 f_sleep(1.0);
5438 f_ctrs_bsc_and_bts_assignment_init(1);
5439
5440 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5441 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5442 vc_conn.done;
5443
5444 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
5445 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
5446 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
5447 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
5448 f_ctrs_bts_verify();
5449
5450 f_shutdown_helper();
5451}
5452
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005453/* Test Osmux setup BTS<->BSC<->MSC */
5454testcase TC_assignment_osmux() runs on test_CT {
5455 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5456 var MSC_ConnHdlr vc_conn;
5457
5458 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5459 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5460 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005461 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005462 pars.use_osmux_cn := true;
5463 pars.use_osmux_bts := true;
5464
5465 g_osmux_enabled_cn := true;
5466 g_osmux_enabled_bts := true;
5467 f_init(1, true);
5468 f_sleep(1.0);
5469 f_vty_amr_start_mode_set(false, "1");
5470
5471 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5472 vc_conn.done;
5473
5474 f_vty_amr_start_mode_restore(false);
5475 f_shutdown_helper();
5476}
5477
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005478/* test the procedure of the MSC requesting a Classmark Update:
5479 * a) BSSMAP Classmark Request should result in RR CLASSMARK ENQUIRY,
5480 * b) L3 RR CLASSMARK CHANGE should result in BSSMAP CLASSMARK UPDATE */
Harald Welte898113b2018-01-31 18:32:21 +01005481private function f_tc_classmark(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005482 g_pars := f_gen_test_hdlr_pars();
5483
Harald Weltea0630032018-03-20 21:09:55 +01005484 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005485 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005486
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005487 BSSAP.send(ts_BSSMAP_ClassmarkRequest);
5488 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_CM_ENQUIRY));
5489
Harald Welte898113b2018-01-31 18:32:21 +01005490 f_rsl_send_l3(ts_RRM_CM_CHG(valueof(ts_CM2)));
5491 BSSAP.receive(tr_BSSMAP_ClassmarkUpd(?, omit));
5492 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005493
5494 f_perform_clear();
Harald Welte898113b2018-01-31 18:32:21 +01005495}
5496testcase TC_classmark() runs on test_CT {
5497 var MSC_ConnHdlr vc_conn;
5498 f_init(1, true);
5499 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005500 vc_conn := f_start_handler(refers(f_tc_classmark));
Harald Welte898113b2018-01-31 18:32:21 +01005501 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005502 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005503}
5504
Harald Welteeddf0e92020-06-21 19:42:15 +02005505/* Send a CommonID from the simulated MSC and verify that the information is used to
5506 * fill BSC-internal data structures (specifically, bsc_subscr associated with subscr_conn) */
5507private function f_tc_common_id(charstring id) runs on MSC_ConnHdlr {
5508 g_pars := f_gen_test_hdlr_pars();
5509 f_MscConnHdlr_init_vty();
5510
5511 f_create_chan_and_exp();
5512 /* we should now have a COMPL_L3 at the MSC */
Harald Welteeddf0e92020-06-21 19:42:15 +02005513
5514 /* Send CommonID */
5515 BSSAP.send(ts_BSSMAP_CommonId(g_pars.imsi));
5516
5517 /* Use VTY to verify that the IMSI of the subscr_conn is set */
5518 var charstring regex := "*(IMSI: " & hex2str(g_pars.imsi) & ")*";
5519 f_vty_transceive_match_regexp_retry(BSCVTY, "show conns", regex, 0, 4, 1.0);
5520
5521 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005522
5523 f_perform_clear();
Harald Welteeddf0e92020-06-21 19:42:15 +02005524}
5525testcase TC_common_id() runs on test_CT {
5526 var MSC_ConnHdlr vc_conn;
5527 f_init(1, true);
5528 f_sleep(1.0);
5529 vc_conn := f_start_handler(refers(f_tc_common_id));
5530 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005531 f_shutdown_helper();
Harald Welteeddf0e92020-06-21 19:42:15 +02005532}
5533
Harald Weltee3bd6582018-01-31 22:51:25 +01005534private function f_est_single_l3(template PDU_ML3_MS_NW l3) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005535 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005536 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005537 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005538
Harald Weltee3bd6582018-01-31 22:51:25 +01005539 /* send the single message we want to send */
5540 f_rsl_send_l3(l3);
5541}
5542
5543private function f_bssap_expect_nothing(float sec := 5.00) runs on MSC_ConnHdlr {
5544 timer T := sec;
5545 var PDU_BSSAP bssap;
Harald Welte898113b2018-01-31 18:32:21 +01005546 T.start;
5547 alt {
Harald Weltee3bd6582018-01-31 22:51:25 +01005548 [] BSSAP.receive(PDU_BSSAP:?) -> value bssap {
5549 setverdict(fail, "Unexpected BSSMAP ", bssap);
Daniel Willmannafce8662018-07-06 23:11:32 +02005550 mtc.stop;
Harald Welte898113b2018-01-31 18:32:21 +01005551 }
5552 [] T.timeout {
5553 setverdict(pass);
5554 }
5555 }
5556}
5557
Harald Weltee3bd6582018-01-31 22:51:25 +01005558/* unsolicited ASSIGNMENT FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5559private function f_tc_unsol_ass_fail(charstring id) runs on MSC_ConnHdlr {
5560 f_est_single_l3(ts_RRM_AssignmentFailure('00'O));
5561 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005562 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005563}
Harald Welte898113b2018-01-31 18:32:21 +01005564testcase TC_unsol_ass_fail() runs on test_CT {
5565 var MSC_ConnHdlr vc_conn;
5566 f_init(1, true);
5567 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005568 vc_conn := f_start_handler(refers(f_tc_unsol_ass_fail));
Harald Welte898113b2018-01-31 18:32:21 +01005569 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005570 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005571}
Harald Welte552620d2017-12-16 23:21:36 +01005572
Harald Welteea99a002018-01-31 20:46:43 +01005573
5574/* unsolicited ASSIGNMENT COMPLETE (without ASSIGN) from MS shouldn't bring BSC down */
5575private function f_tc_unsol_ass_compl(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005576 f_est_single_l3(ts_RRM_AssignmentComplete('00'O));
5577 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005578 f_perform_clear();
Harald Welteea99a002018-01-31 20:46:43 +01005579}
5580testcase TC_unsol_ass_compl() runs on test_CT {
5581 var MSC_ConnHdlr vc_conn;
5582 f_init(1, true);
5583 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005584 vc_conn := f_start_handler(refers(f_tc_unsol_ass_compl));
Harald Welteea99a002018-01-31 20:46:43 +01005585 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005586 f_shutdown_helper();
Harald Welteea99a002018-01-31 20:46:43 +01005587}
5588
5589
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005590/* unsolicited HANDOVER FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5591private function f_tc_unsol_ho_fail(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005592 f_est_single_l3(ts_RRM_HandoverFailure('00'O));
5593 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005594 f_perform_clear();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005595}
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005596testcase TC_unsol_ho_fail() runs on test_CT {
5597 var MSC_ConnHdlr vc_conn;
5598 f_init(1, true);
5599 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005600 vc_conn := f_start_handler(refers(f_tc_unsol_ho_fail));
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005601 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005602 f_shutdown_helper();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005603}
5604
5605
Harald Weltee3bd6582018-01-31 22:51:25 +01005606/* short message from MS should be ignored */
5607private function f_tc_err_82_short_msg(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005608 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005609 f_create_chan_and_exp();
Harald Weltee3bd6582018-01-31 22:51:25 +01005610 /* we should now have a COMPL_L3 at the MSC */
Harald Weltee3bd6582018-01-31 22:51:25 +01005611
5612 /* send short message */
5613 RSL.send(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), ''O));
5614 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005615 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005616}
5617testcase TC_err_82_short_msg() runs on test_CT {
5618 var MSC_ConnHdlr vc_conn;
5619 f_init(1, true);
5620 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005621 vc_conn := f_start_handler(refers(f_tc_err_82_short_msg));
Harald Weltee3bd6582018-01-31 22:51:25 +01005622 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005623 f_shutdown_helper();
Harald Weltee3bd6582018-01-31 22:51:25 +01005624}
5625
5626
Harald Weltee9e02e42018-01-31 23:36:25 +01005627/* 24.008 8.4 Unknown message must trigger RR STATUS */
5628private function f_tc_err_84_unknown_msg(charstring id) runs on MSC_ConnHdlr {
5629 f_est_single_l3(ts_RRM_UL_REL('00'O));
5630 timer T := 3.0
5631 alt {
5632 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_STATUS)) {
5633 setverdict(pass);
5634 }
5635 [] BSSAP.receive { setverdict(fail, "unexpected BSSAP"); }
Harald Welte458fd372018-03-21 11:26:23 +01005636 [] T.timeout { setverdict(fail, "Timeout waiting for RR STATUS"); }
Harald Weltee9e02e42018-01-31 23:36:25 +01005637 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005638 f_perform_clear();
Harald Weltee9e02e42018-01-31 23:36:25 +01005639}
5640testcase TC_err_84_unknown_msg() runs on test_CT {
5641 var MSC_ConnHdlr vc_conn;
5642 f_init(1, true);
5643 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005644 vc_conn := f_start_handler(refers(f_tc_err_84_unknown_msg));
Harald Weltee9e02e42018-01-31 23:36:25 +01005645 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005646 f_shutdown_helper();
Harald Weltee9e02e42018-01-31 23:36:25 +01005647}
5648
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005649/***********************************************************************
5650 * Handover
5651 ***********************************************************************/
5652
Harald Welte94e0c342018-04-07 11:33:23 +02005653/* execute a "bts <0-255> trx <0-255> timeslot <0-7> " command on given Dchan */
5654private function f_vty_ts_action(charstring suffix, integer bts_nr, integer trx_nr, integer ts_nr)
5655runs on test_CT {
5656 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5657 " timeslot "&int2str(ts_nr)&" ";
5658 f_vty_transceive(BSCVTY, cmd & suffix);
5659}
5660
Harald Welte261af4b2018-02-12 21:20:39 +01005661/* execute a "bts <0-255> trx <0-255> timeslot <0-7> sub-slot <0-7>" command on given Dchan */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005662private function f_vty_ss_action(TELNETasp_PT pt, charstring suffix,
5663 uint8_t bts_nr, uint8_t trx_nr,
5664 in RslChannelNr chan_nr)
5665{
Harald Welte261af4b2018-02-12 21:20:39 +01005666 /* FIXME: resolve those from component-global state */
5667 var integer ts_nr := chan_nr.tn;
5668 var integer ss_nr;
5669 if (ischosen(chan_nr.u.ch0)) {
5670 ss_nr := 0;
5671 } else if (ischosen(chan_nr.u.lm)) {
5672 ss_nr := chan_nr.u.lm.sub_chan;
5673 } else if (ischosen(chan_nr.u.sdcch4)) {
5674 ss_nr := chan_nr.u.sdcch4.sub_chan;
5675 } else if (ischosen(chan_nr.u.sdcch8)) {
5676 ss_nr := chan_nr.u.sdcch8.sub_chan;
5677 } else {
5678 setverdict(fail, "Invalid ChanNr ", chan_nr);
Daniel Willmannafce8662018-07-06 23:11:32 +02005679 mtc.stop;
Harald Welte261af4b2018-02-12 21:20:39 +01005680 }
5681
5682 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5683 " timeslot "&int2str(ts_nr)&" sub-slot "&int2str(ss_nr)&" ";
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005684 f_vty_transceive(pt, cmd & suffix);
Harald Welte261af4b2018-02-12 21:20:39 +01005685}
5686
Neels Hofmeyr91401012019-07-11 00:42:35 +02005687/* Even though the VTY command to trigger handover takes a new BTS number as argument, behind the scenes osmo-bsc always
5688 * translates that to a target ARFCN+BSIC first. See bsc_vty.c trigger_ho_or_as(), which puts the selected BTS' neighbor
5689 * ident key (ARFCN + BSIC) in the struct passed on to handover_request(). handover_start() then resolves that to a
5690 * viable actual neighbor cell. So from the internal osmo-bsc perspective, we always request handover to an ARFCN + BSIC
5691 * pair, not really to a specific BTS number. */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005692private function f_vty_handover(TELNETasp_PT pt, uint8_t bts_nr, uint8_t trx_nr,
5693 in RslChannelNr chan_nr, uint8_t new_bts_nr)
5694{
5695 f_vty_ss_action(pt, "handover " & int2str(new_bts_nr), bts_nr, trx_nr, chan_nr);
Harald Welte261af4b2018-02-12 21:20:39 +01005696}
5697
5698/* intra-BSC hand-over between BTS0 and BTS1 */
5699private function f_tc_ho_int(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02005700 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5701 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte261af4b2018-02-12 21:20:39 +01005702
5703 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5704 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5705
Harald Weltea0630032018-03-20 21:09:55 +01005706 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr666f0432020-07-04 00:53:07 +02005707 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Harald Welte261af4b2018-02-12 21:20:39 +01005708
5709 var HandoverState hs := {
5710 rr_ho_cmpl_seen := false,
5711 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005712 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005713 expect_target_tsc := c_BtsParams[1].tsc
Harald Welte261af4b2018-02-12 21:20:39 +01005714 };
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005715 /* issue hand-over command on VTY, from BTS 0 to BTS 1 */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005716 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
Harald Welte261af4b2018-02-12 21:20:39 +01005717 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5718 f_rslem_suspend(RSL1_PROC);
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005719
5720 /* From the MGW perspective, a handover is is characterized by
5721 * performing one MDCX operation with the MGW. So we expect to see
5722 * one more MDCX during handover. */
5723 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5724
Harald Welte261af4b2018-02-12 21:20:39 +01005725 alt {
5726 [] as_handover(hs);
Harald Welte261af4b2018-02-12 21:20:39 +01005727 }
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005728
Philipp Maier4dae0652018-11-12 12:03:26 +01005729 /* Since this is an internal handover we expect the BSC to inform the
5730 * MSC about the event */
5731 BSSAP.receive(tr_BSSMAP_HandoverPerformed);
5732
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005733 /* Check the amount of MGCP transactions is still consistant with the
5734 * test expectation */
5735 f_check_mgcp_expectations()
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005736
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005737 var RSL_Message chan_act := f_rslem_get_last_act(RSL1_PROC, 0, g_chan_nr);
5738
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005739 /* Ensure the Channel Activation for the new channel contained the right encryption params. as_handover() set
5740 * g_chan_nr to the new lchan that was handed over to. It lives in bts 1, so look it up at RSL1_PROC. */
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005741 f_verify_encr_info(chan_act);
5742
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005743 f_chan_act_verify_tsc(chan_act, c_BtsParams[1].tsc);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005744
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005745 f_perform_clear(RSL1, RSL1_PROC);
5746
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01005747 f_sleep(0.5);
Harald Welte261af4b2018-02-12 21:20:39 +01005748}
5749
5750testcase TC_ho_int() runs on test_CT {
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005751 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte261af4b2018-02-12 21:20:39 +01005752 var MSC_ConnHdlr vc_conn;
5753 f_init(2, true);
5754 f_sleep(1.0);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005755
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005756 pars.expect_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005757
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005758 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005759
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005760 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
Harald Welte261af4b2018-02-12 21:20:39 +01005761 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005762
5763 /* from f_establish_fully() */
5764 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5765 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5766 /* from handover */
5767 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5768 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5769 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5770 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005771 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5772 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005773 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02005774 f_shutdown_helper(ho := true);
Harald Welte261af4b2018-02-12 21:20:39 +01005775}
Harald Weltee9e02e42018-01-31 23:36:25 +01005776
Oliver Smith7eabd312021-07-12 14:18:56 +02005777function f_tc_ho_int_a5(OCT1 encr_alg, charstring enc_a5 := "0 1 3") runs on test_CT {
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005778 var MSC_ConnHdlr vc_conn;
5779 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5780 pars.encr := valueof(t_EncrParams(encr_alg, f_rnd_octstring(8), f_rnd_octstring(16)));
5781
5782 f_init(2, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02005783 f_vty_encryption_a5(enc_a5);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005784 f_sleep(1.0);
5785
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005786 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005787
5788 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
5789 vc_conn.done;
5790
5791 /* from f_establish_fully() */
5792 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5793 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5794 /* from handover */
5795 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5796 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5797 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5798 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005799 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5800 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005801 f_ctrs_bsc_and_bts_verify();
Oliver Smith7eabd312021-07-12 14:18:56 +02005802 f_vty_encryption_a5_reset();
Oliver Smith39f53072022-10-27 14:44:04 +02005803 f_shutdown_helper(ho := true);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005804}
5805
5806testcase TC_ho_int_a5_0() runs on test_CT {
5807 f_tc_ho_int_a5('01'O);
5808}
5809
5810testcase TC_ho_int_a5_1() runs on test_CT {
5811 f_tc_ho_int_a5('02'O);
5812}
5813
5814testcase TC_ho_int_a5_3() runs on test_CT {
5815 f_tc_ho_int_a5('08'O);
5816}
5817
5818testcase TC_ho_int_a5_4() runs on test_CT {
Oliver Smith7eabd312021-07-12 14:18:56 +02005819 f_tc_ho_int_a5('10'O, "0 1 3 4");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005820}
5821
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005822/* intra-BSC hand-over with CONNection FAILure and cause Radio Link Failure: check RR release cause */
5823private function f_tc_ho_int_radio_link_failure(charstring id) runs on MSC_ConnHdlr {
5824 g_pars := f_gen_test_hdlr_pars();
5825 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5826 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005827
5828 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5829 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5830
5831 f_establish_fully(ass_cmd, exp_compl);
5832 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
5833
5834 var HandoverState hs := {
5835 rr_ho_cmpl_seen := false,
5836 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005837 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005838 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005839 };
5840 /* issue hand-over command on VTY */
5841 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
5842 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5843 f_rslem_suspend(RSL1_PROC);
5844
5845 /* From the MGW perspective, a handover is is characterized by
5846 * performing one MDCX operation with the MGW. So we expect to see
5847 * one more MDCX during handover. */
5848 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5849
5850 var RSL_Message rsl;
5851 var PDU_ML3_NW_MS l3;
5852 var RslChannelNr new_chan_nr;
5853 var GsmArfcn arfcn;
5854 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
5855 l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
5856 if (not ischosen(l3.msgs.rrm.handoverCommand)) {
5857 setverdict(fail, "Expected handoverCommand");
5858 mtc.stop;
5859 }
5860 }
5861 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
5862 new_chan_nr, arfcn);
5863
5864 f_rslem_register(0, new_chan_nr, RSL1_PROC);
5865
5866 /* resume processing of RSL DChan messages, which was temporarily suspended
5867 * before performing a hand-over */
5868 f_rslem_resume(RSL1_PROC);
5869 RSL1.receive(tr_RSL_IPA_CRCX(new_chan_nr));
5870
5871 f_sleep(1.0);
5872
5873 /* Handover fails because no HANDO DET appears on the new lchan,
5874 * and the old lchan reports a Radio Link Failure. */
5875 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
5876
5877 var PDU_BSSAP rx_clear_request;
5878 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
5879 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
5880 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5881
5882 var RR_Cause rr_cause := GSM48_RR_CAUSE_ABNORMAL_UNSPEC;
5883
5884 var MgcpCommand mgcp;
5885 interleave {
5886 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE(int2oct(enum2int(rr_cause), 1)))) {}
5887 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005888 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005889 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005890 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005891 }
5892 [] RSL1.receive(tr_RSL_DEACT_SACCH(new_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005893 [] RSL1.receive(tr_RSL_RF_CHAN_REL(new_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005894 RSL1.send(ts_RSL_RF_CHAN_REL_ACK(new_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005895 f_rslem_unregister(0, g_chan_nr, PT := RSL1_PROC);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005896 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005897 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
5898 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
5899 }
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005900 }
5901
5902 f_sleep(0.5);
5903 setverdict(pass);
5904}
5905testcase TC_ho_int_radio_link_failure() runs on test_CT {
5906 var MSC_ConnHdlr vc_conn;
5907 f_init(2, true);
5908 f_sleep(1.0);
5909
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005910 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005911
5912 vc_conn := f_start_handler(refers(f_tc_ho_int_radio_link_failure));
5913 vc_conn.done;
5914
5915 /* from f_establish_fully() */
5916 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5917 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5918 /* from handover */
5919 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5920 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
5921 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5922 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:stopped");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005923 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5924 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:stopped");
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005925 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02005926 f_shutdown_helper(ho := true);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005927}
5928
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005929/* Expecting MGCP to DLCX the endpoint's two connections: towards BTS and towards MSC */
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005930private function f_expect_dlcx_conns() runs on MSC_ConnHdlr {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005931 var MgcpCommand mgcp;
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005932 var template MgcpResponse mgcp_resp;
5933 var MGCP_RecvFrom mrf;
5934 var template MgcpMessage msg_resp;
5935 var template MgcpMessage msg_dlcx := {
5936 command := tr_DLCX()
5937 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005938
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005939 if (g_pars.aoip) {
5940 MGCP.receive(tr_DLCX()) -> value mgcp {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005941 log("Got first DLCX: ", mgcp);
5942 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005943 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005944
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005945 MGCP.receive(tr_DLCX()) -> value mgcp {
5946 log("Got second DLCX: ", mgcp);
5947 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
5948 };
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005949 } else {
5950 /* For SCCPLite, BSC doesn't handle the MSC-side */
5951 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
5952 log("Got first DLCX: ", mrf.msg.command);
5953 msg_resp := {
5954 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
5955 }
5956 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, msg_resp));
5957 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005958 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005959}
5960
Oliver Smithc9a5f532022-10-21 11:32:23 +02005961private function f_ho_out_of_this_bsc(template (omit) BSSMAP_oldToNewBSSIEs exp_oldToNewBSSIEs := omit,
5962 boolean skip_meas_rep := false) runs on MSC_ConnHdlr {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005963
Oliver Smithc9a5f532022-10-21 11:32:23 +02005964 if (not skip_meas_rep) {
5965 var NcellReports neighbor_rep := {
5966 { rxlev := 20, bcch_freq := 0, bsic := 11 }
5967 };
5968 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
5969 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
5970 l3_mr, 0));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005971
Oliver Smithc9a5f532022-10-21 11:32:23 +02005972 BSSAP.receive(tr_BSSMAP_HandoverRequired(exp_oldToNewBSSIEs));
5973 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005974
5975 f_sleep(0.5);
5976 /* The MSC negotiates Handover Request and Handover Request Ack with
5977 * the other BSS and comes back with a BSSMAP Handover Command
5978 * containing an RR Handover Command coming from the target BSS... */
5979
5980 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
5981 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
5982 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
5983 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
5984 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
5985
5986 /* expect the Handover Command to go out on RR */
5987 var RSL_Message rsl_ho_cmd
5988 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
5989 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
5990 var RSL_IE_Body rsl_ho_cmd_l3;
5991 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
5992 log("RSL message contains no L3 Info IE, expected RR Handover Command");
5993 setverdict(fail);
5994 } else {
5995 log("Found L3 Info: ", rsl_ho_cmd_l3);
5996 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
5997 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
5998 setverdict(fail);
5999 } else {
6000 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6001 setverdict(pass);
6002 }
6003 }
6004
6005 /* When the other BSS has reported a completed handover, this side is
6006 * torn down. */
6007
6008 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_HANDOVER_SUCCESSFUL;
6009 var BssmapCause cause := enum2int(cause_val);
6010 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6011
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006012 f_expect_dlcx_conns();
Pau Espin Pedrol06199952021-06-15 11:30:00 +02006013
6014 interleave {
6015 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE));
6016 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr));
6017 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006018 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
6019 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
6020 }
Pau Espin Pedrol06199952021-06-15 11:30:00 +02006021 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006022 setverdict(pass);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006023}
6024
6025private function f_tc_ho_out_of_this_bsc(charstring id) runs on MSC_ConnHdlr {
6026 g_pars := f_gen_test_hdlr_pars();
6027 var PDU_BSSAP ass_req := f_gen_ass_req();
6028 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6029 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6030 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6031 f_establish_fully(ass_req, exp_compl);
6032
6033 f_ho_out_of_this_bsc();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006034}
6035testcase TC_ho_out_of_this_bsc() runs on test_CT {
6036 var MSC_ConnHdlr vc_conn;
6037
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01006038 f_init_vty();
6039 f_bts_0_cfg(BSCVTY,
6040 {"neighbor-list mode automatic",
6041 "handover 1",
6042 "handover algorithm 2",
6043 "handover2 window rxlev averaging 1",
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006044 "no neighbors",
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01006045 "neighbor lac 99 arfcn 123 bsic any"});
6046 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6047
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006048 f_init(1, true);
6049 f_sleep(1.0);
6050
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006051 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006052
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006053 vc_conn := f_start_handler(refers(f_tc_ho_out_of_this_bsc));
6054 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006055
6056 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6057 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6058 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6059 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6060 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6061 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
6062 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006063 f_shutdown_helper(ho := true);
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006064}
6065
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006066private function f_mo_l3_transceive(RSL_DCHAN_PT rsl := RSL,
6067 template (value) RslLinkId link_id := ts_RslLinkID_DCCH(0),
Vadim Yanitskiy2ef6a2f2020-10-08 23:17:32 +07006068 template (present) OCT1 dlci := ?,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07006069 octetstring l3 := '0123456789'O)
6070runs on MSC_ConnHdlr {
Neels Hofmeyr43654812020-09-25 01:35:35 +02006071 /* The old lchan and conn should still be active. See that arbitrary L3
6072 * is still going through. */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006073 rsl.send(ts_RSL_DATA_IND(g_chan_nr, link_id, l3));
Neels Hofmeyr43654812020-09-25 01:35:35 +02006074 var template PDU_BSSAP exp_data := {
6075 discriminator := '1'B,
6076 spare := '0000000'B,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07006077 dlci := dlci,
6078 lengthIndicator := lengthof(l3),
Neels Hofmeyr43654812020-09-25 01:35:35 +02006079 pdu := {
6080 dtap := l3
6081 }
6082 };
6083 BSSAP.receive(exp_data);
6084 setverdict(pass);
6085}
6086
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006087private function f_mt_l3_transceive(RSL_DCHAN_PT rsl := RSL,
6088 template (present) RslLinkId link_id := tr_RslLinkID_DCCH(0),
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07006089 template (value) OCT1 dlci := '00'O,
6090 octetstring l3 := '0123456789'O)
6091runs on MSC_ConnHdlr {
6092 BSSAP.send(PDU_BSSAP:{
6093 discriminator := '1'B,
6094 spare := '0000000'B,
6095 dlci := dlci,
6096 lengthIndicator := lengthof(l3),
6097 pdu := {
6098 dtap := l3
6099 }
6100 });
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006101 rsl.receive(tr_RSL_DATA_REQ(g_chan_nr, link_id, l3));
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07006102 setverdict(pass);
6103}
6104
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006105/* BSC asks for inter-BSC HO, but the MSC decides that it won't happen and
6106 * simply never sends a BSSMAP Handover Command. */
6107private function f_tc_ho_out_fail_no_msc_response(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006108 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006109
6110 var PDU_BSSAP ass_req := f_gen_ass_req();
6111 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6112 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6113 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6114 f_establish_fully(ass_req, exp_compl);
6115
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006116 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006117 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6118
6119 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6120
6121 /* osmo-bsc should time out 10 seconds after the handover started.
6122 * Let's give it a bit extra. */
6123 f_sleep(15.0);
6124
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006125 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006126 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006127 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006128}
6129testcase TC_ho_out_fail_no_msc_response() runs on test_CT {
6130 var MSC_ConnHdlr vc_conn;
6131
6132 f_init(1, true);
6133 f_sleep(1.0);
6134
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006135 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006136
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006137 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_msc_response));
6138 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006139
6140 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6141 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6142 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6143 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6144 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6145 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6146 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006147 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006148}
6149
6150/* BSC asks for inter-BSC HO, receives BSSMAP Handover Command, but MS reports
6151 * RR Handover Failure. */
6152private function f_tc_ho_out_fail_rr_ho_failure(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006153 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006154
6155 var PDU_BSSAP ass_req := f_gen_ass_req();
6156 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6157 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6158 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6159 f_establish_fully(ass_req, exp_compl);
6160
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006161 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006162 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6163
6164 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6165
6166 f_sleep(0.5);
6167 /* The MSC negotiates Handover Request and Handover Request Ack with
6168 * the other BSS and comes back with a BSSMAP Handover Command
6169 * containing an RR Handover Command coming from the target BSS... */
6170
6171 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6172 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6173 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6174 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6175 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6176
6177 /* expect the Handover Command to go out on RR */
6178 var RSL_Message rsl_ho_cmd
6179 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6180 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6181 var RSL_IE_Body rsl_ho_cmd_l3;
6182 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6183 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6184 setverdict(fail);
6185 } else {
6186 log("Found L3 Info: ", rsl_ho_cmd_l3);
6187 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6188 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6189 setverdict(fail);
6190 } else {
6191 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6192 setverdict(pass);
6193 }
6194 }
6195
6196 f_sleep(0.2);
6197 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
6198
6199 /* Should tell the MSC about the failure */
6200 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6201
6202 f_sleep(1.0);
6203
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006204 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006205 f_sleep(1.0);
6206
6207 setverdict(pass);
6208 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006209 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006210}
6211testcase TC_ho_out_fail_rr_ho_failure() runs on test_CT {
6212 var MSC_ConnHdlr vc_conn;
6213
6214 f_init(1, true);
6215 f_sleep(1.0);
6216
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006217 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006218
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006219 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_rr_ho_failure));
6220 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006221
6222 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6223 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6224 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6225 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6226 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6227 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:failed");
6228 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006229 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006230}
6231
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006232/* BSC asks for inter-BSC-out HO, receives BSSMAP Handover Command, but then no reply is received about HO outcome
6233 * (neither BSSMAP Clear Command for success nor RR Handover Failure). 48.008 3.1.5.3.3 "Abnormal Conditions" applies
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006234 * and the lchan is released. */
6235private function f_tc_ho_out_fail_no_result_after_ho_cmd(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006236 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006237
6238 var PDU_BSSAP ass_req := f_gen_ass_req();
6239 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6240 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6241 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6242 f_establish_fully(ass_req, exp_compl);
6243
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006244 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006245 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6246
6247 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6248
6249 f_sleep(0.5);
6250 /* The MSC negotiates Handover Request and Handover Request Ack with
6251 * the other BSS and comes back with a BSSMAP Handover Command
6252 * containing an RR Handover Command coming from the target BSS... */
6253
6254 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6255 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6256 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6257 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6258 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6259
6260 /* expect the Handover Command to go out on RR */
6261 var RSL_Message rsl_ho_cmd
6262 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6263 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6264 var RSL_IE_Body rsl_ho_cmd_l3;
6265 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6266 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6267 setverdict(fail);
6268 } else {
6269 log("Found L3 Info: ", rsl_ho_cmd_l3);
6270 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6271 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6272 setverdict(fail);
6273 } else {
6274 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6275 setverdict(pass);
6276 }
6277 }
6278
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006279 /* We get neither success nor failure report from the remote BSS. Eventually T8 times out and we run into 3GPP
6280 * TS 48.008 3.1.5.3.3 "Abnormal Conditions": Clear Request should go to the MSC, and RR should be released
6281 * after Clear Command */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006282
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006283 var PDU_BSSAP rx_clear_request;
Neels Hofmeyre1797aa2019-07-09 19:34:04 +02006284 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
6285 log("Got BSSMAP Clear Request");
6286 /* Instruct BSC to clear channel */
6287 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
6288 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6289
6290 var MgcpCommand mgcp;
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006291 interleave {
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01006292 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
6293 log("Got Deact SACCH");
6294 }
Harald Welte924b6ea2019-02-04 01:05:34 +01006295 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
Neels Hofmeyr211169d2018-11-07 00:37:29 +01006296 log("Got RR Release");
6297 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02006298 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006299 log("Got RF Chan Rel");
6300 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02006301 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006302 }
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006303 }
6304
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006305 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006306 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006307 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006308
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006309 setverdict(pass);
6310 f_sleep(1.0);
6311}
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006312testcase TC_ho_out_fail_no_result_after_ho_cmd() runs on test_CT {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006313 var MSC_ConnHdlr vc_conn;
6314
6315 f_init(1, true);
6316 f_sleep(1.0);
6317
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006318 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006319
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006320 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_result_after_ho_cmd));
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006321 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006322
6323 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6324 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6325 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6326 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6327 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6328 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6329 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006330 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006331}
6332
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006333private function f_ho_into_this_bsc(charstring id, template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit) runs on MSC_ConnHdlr {
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006334 var PDU_BSSAP rx_bssap;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006335 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6336 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6337 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6338 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6339 * before we get started. */
6340 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6341 f_rslem_register(0, new_chan_nr);
6342 g_chan_nr := new_chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06006343 var uint3_t expect_target_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006344 f_sleep(1.0);
6345
6346 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6347 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006348 var default as_media := activate(as_Media());
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006349
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01006350 var PDU_BSSAP ho_req := f_gen_handover_req(aoip_tla := g_pars.host_aoip_tla,
6351 cell_id_source := g_pars.cell_id_source,
6352 oldToNewBSSIEs := oldToNewBSSIEs,
6353 enc := g_pars.encr);
6354 if (g_pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr) {
6355 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, ho_req));
6356 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6357 } else {
6358 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, omit));
6359 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6360 BSSAP.send(ho_req);
6361 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006362
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006363 alt {
6364 [] BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap {
6365 if (g_pars.expect_ho_fail) {
6366 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6367 "Expected Handover Request to fail, but got Handover Request Ack")
6368 }
6369 }
6370 [] BSSAP.receive(tr_BSSMAP_HandoverFailure) -> value rx_bssap {
6371 if (not g_pars.expect_ho_fail) {
6372 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6373 "Expected Handover Request to succeed, but got Handover Failure")
6374 }
6375 // TODO: evaluate correct cause value. But osmo-bsc doesn't seem to send meaningful causes yet!
6376 // For now just accept any cause.
6377 BSSAP.receive(tr_BSSMAP_ClearRequest);
6378 setverdict(pass);
6379 return;
6380 }
6381 }
6382
Oliver Smith7a8594a2023-02-13 14:30:49 +01006383 if (g_pars.expect_ho_fail_lchan_est) {
6384 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6385 setverdict(pass);
Oliver Smitha1cbec52023-02-21 12:44:12 +01006386
6387 /* When we let MGCP MDCX run into a timeout, it's still in the
6388 * queue and additionally after BSSAP HandoverFailure, two DLCX
Oliver Smith30eb8822023-03-06 12:31:53 +01006389 * get sent (for AoIP, for SCCPlite one DLCX). */
Oliver Smitha1cbec52023-02-21 12:44:12 +01006390 if (g_pars.ignore_mgw_mdcx) {
Oliver Smith30eb8822023-03-06 12:31:53 +01006391 if (g_pars.aoip) {
6392 MGCP.receive(tr_MDCX);
6393 MGCP.receive(tr_DLCX);
6394 MGCP.receive(tr_DLCX);
6395 } else {
6396 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any({command := tr_MDCX}));
6397 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any({command := tr_DLCX}));
6398 }
Oliver Smitha1cbec52023-02-21 12:44:12 +01006399 }
Oliver Smith7a8594a2023-02-13 14:30:49 +01006400 return;
6401 }
6402
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006403 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6404
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006405 /* we're sure that the channel activation is done now, verify the parameters in it */
6406 var RSL_Message chan_act := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
6407 f_verify_encr_info(chan_act);
6408 f_chan_act_verify_tsc(chan_act, expect_target_tsc);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006409
Neels Hofmeyr46e16e52022-02-23 17:04:00 +01006410 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.codecList)) {
6411 if (not g_pars.aoip) {
6412 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6413 "handoverRequestAck: Expected no Speech Codec List (BSS Supported), because this is not AoIP");
6414 }
6415 /* TODO: check actual codecs? */
6416 } else {
6417 if (g_pars.aoip) {
6418 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6419 "handoverRequestAck: Expected Speech Codec List (BSS Supported), but none found");
6420 }
6421 }
6422
6423 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.speechCodec)) {
6424 if (not g_pars.aoip) {
6425 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6426 "handoverRequestAck: Expected no Speech Codec (Chosen), because this is not AoIP");
6427 }
6428 /* TODO: check actual codec? */
6429 } else {
6430 if (g_pars.aoip) {
6431 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6432 "handoverRequestAck: Expected Speech Codec (Chosen), but none found");
6433 }
6434 }
6435
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006436 var octetstring ho_command_str;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006437 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6438 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6439 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6440 log("L3 Info in HO Request Ack is ", ho_command);
6441
6442 var GsmArfcn arfcn;
6443 var RslChannelNr actual_new_chan_nr;
6444 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6445 actual_new_chan_nr, arfcn);
6446
6447 if (actual_new_chan_nr != new_chan_nr) {
6448 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6449 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6450 setverdict(fail);
6451 return;
6452 }
6453 log("Handover Command chan_nr is", actual_new_chan_nr);
6454
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006455 var uint3_t got_tsc := rr_chan_desc_tsc(ho_command.msgs.rrm.handoverCommand.channelDescription2);
6456 if (not match(got_tsc, expect_target_tsc)) {
6457 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
6458 expect_target_tsc, " got ", got_tsc);
6459 mtc.stop;
6460 } else {
6461 log("handoverCommand: verified TSC = ", got_tsc);
6462 }
6463
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006464 /* Check the Cipher Mode Setting IE (shall be present during inter-RAT handover) */
6465 if (ispresent(ho_command.msgs.rrm.handoverCommand.cipherModeSetting)) {
6466 var CipherModeSetting_TV cms := ho_command.msgs.rrm.handoverCommand.cipherModeSetting;
6467 var template (present) CipherModeSetting_TV tr_cms := {
6468 sC := '0'B, /* no ciphering by default */
6469 algorithmIdentifier := '000'B,
6470 elementIdentifier := ?
6471 };
6472 if (ispresent(g_pars.encr) and g_pars.encr.enc_alg_expect != '01'O) { /* A5/N */
6473 tr_cms.algorithmIdentifier := f_cipher_mode_bssmap_to_rr(g_pars.encr.enc_alg_expect);
6474 tr_cms.sC := '1'B;
6475 }
6476 if (not match(cms, tr_cms)) {
6477 setverdict(fail, "RR Handover Command: unexpected Cipher Mode Setting IE: ",
6478 cms, ", expected: ", tr_cms);
6479 }
6480 } else {
6481 setverdict(fail, "RR Handover Command: Cipher Mode Setting IE is not present");
6482 }
6483
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006484 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6485 * tells the MS to handover to the new lchan. Here comes the new MS on
6486 * the new lchan with a Handover RACH: */
6487
6488 /* send handover detect */
6489
6490 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6491
6492 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6493
6494 /* send handover complete over the new channel */
6495
6496 var PDU_ML3_MS_NW l3_tx := valueof(ts_RRM_HandoverComplete('00'O));
6497 RSL.send(ts_RSL_EST_IND(new_chan_nr, valueof(ts_RslLinkID_DCCH(0)),
6498 enc_PDU_ML3_MS_NW(l3_tx)));
6499
6500 BSSAP.receive(tr_BSSMAP_HandoverComplete);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006501 deactivate(as_media);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006502 setverdict(pass);
6503}
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006504
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006505private function f_tc_ho_into_this_bsc(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006506 var template PDU_ML3_NW_MS exp_rr_rel_tmpl;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006507 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit;
6508 if (not istemplatekind(g_pars.last_used_eutran_plmn, "omit")) {
6509 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006510 }
6511 if (g_pars.exp_fast_return) {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006512 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE_CellSelectInd;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006513 } else {
6514 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006515 }
6516 f_ho_into_this_bsc(id, oldToNewBSSIEs);
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006517 if (g_pars.expect_ho_fail) {
6518 f_perform_clear_no_lchan();
Oliver Smith7a8594a2023-02-13 14:30:49 +01006519 } else if (g_pars.expect_ho_fail_lchan_est) {
6520 BSSAP.receive(tr_BSSMAP_ClearRequest);
6521 f_perform_clear_no_lchan();
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006522 } else {
6523 f_perform_clear(exp_rr_rel_tmpl := exp_rr_rel_tmpl);
6524 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006525 setverdict(pass);
6526}
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006527function f_tc_ho_into_this_bsc_main(TestHdlrParams pars, charstring vty_a5_cfg := VTY_A5_DEFAULT) runs on test_CT {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006528 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006529
6530 f_init(1, true);
6531 f_sleep(1.0);
6532
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006533 f_vty_encryption_a5(vty_a5_cfg);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006534 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006535
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006536 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6537 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006538
6539 vc_conn := f_start_handler(refers(f_tc_ho_into_this_bsc), pars);
6540 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006541
6542 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006543 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006544 if (pars.expect_ho_fail) {
6545 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6546 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:failed");
Oliver Smith7a8594a2023-02-13 14:30:49 +01006547 } else if (pars.expect_ho_fail_lchan_est) {
6548 f_ctrs_bsc_and_bts_add(0, "handover:error");
6549 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006550 } else {
6551 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6552 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed");
6553 }
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006554 f_ctrs_bsc_and_bts_verify();
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006555
6556 f_vty_encryption_a5_reset();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006557}
6558
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006559testcase TC_ho_into_this_bsc() runs on test_CT {
6560 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6561 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02006562 f_shutdown_helper(ho := true);
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006563}
6564
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006565function f_tc_ho_into_this_bsc_a5(TestHdlrEncrParams encr, charstring vty_a5_cfg := VTY_A5_DEFAULT,
6566 boolean expect_fail := false) runs on test_CT {
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006567 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006568 pars.encr := encr;
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006569 pars.expect_ho_fail := expect_fail;
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006570 f_tc_ho_into_this_bsc_main(pars, vty_a5_cfg);
Oliver Smith39f53072022-10-27 14:44:04 +02006571 f_shutdown_helper(ho := true);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006572}
6573
6574testcase TC_ho_into_this_bsc_a5_0() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006575 f_tc_ho_into_this_bsc_a5(f_encr_params('01'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006576}
6577
6578testcase TC_ho_into_this_bsc_a5_1() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006579 f_tc_ho_into_this_bsc_a5(f_encr_params('02'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006580}
6581
6582testcase TC_ho_into_this_bsc_a5_3() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006583 f_tc_ho_into_this_bsc_a5(f_encr_params('08'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006584}
6585
6586testcase TC_ho_into_this_bsc_a5_4() runs on test_CT {
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006587 f_tc_ho_into_this_bsc_a5(f_encr_params('10'O, kc128 := true), "3 4");
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006588}
6589
Neels Hofmeyr1951be22022-02-16 16:21:07 +01006590/* Report: in inter-BSC incoming handover, when the MSC omits the Chosen Encryption Algorithm IE in the Handover Request
6591 * message, then osmo-bsc starts an unencrypted lchan even if A5/0 is not permitted.
6592 *
6593 * This test verifies that the Encryption Information is present in the Channel Activation when the Chosen Enc Alg is
6594 * omitted.
6595 *
6596 * Related: SYS#5839
6597 */
6598testcase TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() runs on test_CT {
6599 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O, alg_chosen := omit));
6600}
6601
6602testcase TC_ho_into_this_bsc_a5_1_3() runs on test_CT {
6603 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O));
6604}
6605
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006606/* Send a permitted algo mask that does not intersect with osmo-bsc.cfg */
6607testcase TC_ho_into_this_bsc_a5_mismatch() runs on test_CT {
6608 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '18'O, alg_expect := '10'O), "0 1",
6609 expect_fail := true); // 0x18 = A5/3 and A5/4
6610}
6611
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006612testcase TC_ho_into_this_bsc_tla_v6() runs on test_CT {
6613 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6614 pars.host_aoip_tla := "::6";
6615 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02006616 f_shutdown_helper(ho := true);
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006617}
6618
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006619/* Similar to TC_ho_into_this_bsc, but when in SRVCC, HO Req contains "Old BSS
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006620 to New BSS Information" IE with "Last Used E-UTRAN PLMN Id", which, when the
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006621 channel is later released (RR CHannel Release), should trigger inclusion of
6622 IE "Cell Selection Indicator after Release of all TCH and SDCCH" with E-UTRAN
6623 neighbors. */
6624testcase TC_srvcc_eutran_to_geran() runs on test_CT {
6625 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6626 pars.last_used_eutran_plmn := '323454'O;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006627 pars.exp_fast_return := true;
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006628 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006629
6630 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6631 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6632 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006633 f_shutdown_helper(ho := true);
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006634}
6635
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006636/* Same as TC_srvcc_eutran_to_geran, but enables ciphering on the target channel. */
6637testcase TC_srvcc_eutran_to_geran_a5_3() runs on test_CT {
6638 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6639 pars.encr := f_encr_params('08'O); /* only A5/3 */
6640 pars.last_used_eutran_plmn := '323454'O;
6641 pars.exp_fast_return := true;
6642 f_tc_ho_into_this_bsc_main(pars);
6643
6644 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6645 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6646 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006647 f_shutdown_helper(ho := true);
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006648}
6649
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006650/* Same as TC_srvcc_eutran_to_geran, but test explicitly forbiding fast return
6651 on the BTS. As a result, RR Release shouldn't contain the EUTRAN neighbor
6652 list when the channel is released. */
6653testcase TC_srvcc_eutran_to_geran_forbid_fast_return() runs on test_CT {
6654 f_init_vty();
6655 f_vty_allow_srvcc_fast_return(true, 0)
6656
6657 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6658 pars.last_used_eutran_plmn := '323454'O;
6659 pars.exp_fast_return := false;
6660 f_tc_ho_into_this_bsc_main(pars);
6661 f_vty_allow_srvcc_fast_return(false, 0);
6662 f_shutdown_helper();
6663}
6664
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01006665/* Same as TC_srvcc_eutran_to_geran, but using SAI as serving Cell Identifier. SYS#5838 */
6666testcase TC_srvcc_eutran_to_geran_src_sai() runs on test_CT {
6667 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6668 pars.last_used_eutran_plmn := '323454'O;
6669 pars.cell_id_source := valueof(ts_CellID_SAI('123456'O, 300, 444));
6670 f_tc_ho_into_this_bsc_main(pars);
6671
6672 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6673 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6674 f_ctrs_bsc_and_bts_verify();
6675 f_shutdown_helper();
6676}
6677
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006678private function f_tc_srvcc_eutran_to_geran_ho_out(charstring id) runs on MSC_ConnHdlr {
6679 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs;
6680 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
6681 f_ho_into_this_bsc(id, oldToNewBSSIEs);
6682 f_ho_out_of_this_bsc(oldToNewBSSIEs);
6683 setverdict(pass);
6684}
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006685
6686private function f_tc_srvcc_eutran_to_geran_ho_out_main(boolean disable_fast_return)
6687 runs on test_CT {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006688 var MSC_ConnHdlr vc_conn;
6689 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6690
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006691 f_init_vty();
6692 f_bts_0_cfg(BSCVTY,
6693 {"neighbor-list mode automatic",
6694 "handover 1",
6695 "handover algorithm 2",
6696 "handover2 window rxlev averaging 1",
6697 "no neighbors",
6698 "neighbor lac 99 arfcn 123 bsic any"});
6699 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6700
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006701 f_init(1, true);
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006702 if (disable_fast_return) {
6703 f_vty_allow_srvcc_fast_return(true, 0);
6704 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006705 f_sleep(1.0);
6706
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006707 f_ctrs_bsc_and_bts_handover_init();
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006708
6709 pars.last_used_eutran_plmn := '323454'O;
6710 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6711 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
6712
6713 vc_conn := f_start_handler(refers(f_tc_srvcc_eutran_to_geran_ho_out), pars);
6714 vc_conn.done;
6715
6716 f_ctrs_bsc_and_bts_add(0, "handover:attempted", 2);
6717 f_ctrs_bsc_and_bts_add(0, "handover:completed", 2);
6718 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted", 1);
6719 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed", 1);
6720 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted", 1);
6721 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed", 1);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006722
6723 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted", 1);
6724 f_ctrs_bsc_and_bts_add(0, "srvcc:completed", 1);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006725 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006726
6727 if (disable_fast_return) {
6728 f_vty_allow_srvcc_fast_return(false, 0);
6729 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006730 f_shutdown_helper();
6731}
6732
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006733/* First, HO into BSC from EUTRAN (SRVCC): HO Request contains "Old BSS to New
6734 BSS Information" IE with "Last Used E-UTRAN PLMN Id".
6735 Second, HO to another BSC: HO Required contains "Old BSS to New BSS Information"
6736 IE with "Last Used E-UTRAN PLMN Id" from first step. */
6737testcase TC_srvcc_eutran_to_geran_ho_out() runs on test_CT {
6738 f_tc_srvcc_eutran_to_geran_ho_out_main(false);
6739}
6740/* Validate subsequent intra-GSM-HO works the same (with OldBSSToNewBSSInfo IE)
6741 * independently of fast-reture allowed/forbidden in local BTS */
6742testcase TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() runs on test_CT {
6743 f_tc_srvcc_eutran_to_geran_ho_out_main(true);
6744}
6745
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006746private function f_tc_ho_in_fail_msc_clears(charstring id) runs on MSC_ConnHdlr {
6747 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6748 f_rslem_register(0, new_chan_nr);
6749 g_chan_nr := new_chan_nr;
6750 f_sleep(1.0);
6751
6752 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6753 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6754 activate(as_Media());
6755
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006756 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006757 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006758 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006759
6760 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6761
6762 var PDU_BSSAP rx_bssap;
6763 var octetstring ho_command_str;
6764
6765 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6766
6767 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6768 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6769 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6770 log("L3 Info in HO Request Ack is ", ho_command);
6771
6772 var GsmArfcn arfcn;
6773 var RslChannelNr actual_new_chan_nr;
6774 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6775 actual_new_chan_nr, arfcn);
6776
6777 if (actual_new_chan_nr != new_chan_nr) {
6778 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6779 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6780 setverdict(fail);
6781 return;
6782 }
6783 log("Handover Command chan_nr is", actual_new_chan_nr);
6784
Neels Hofmeyr61ca08d2019-05-06 23:52:22 +02006785 /* For deterministic test results, give some time for the MGW endpoint to be configured */
6786 f_sleep(1.0);
6787
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006788 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6789 * tells the MS to handover to the new lchan. In this case, the MS
6790 * reports a Handover Failure to the old BSS, which forwards a BSSMAP
6791 * Handover Failure to the MSC. The procedure according to 3GPP TS
6792 * 48.008 3.1.5.3.2 "Handover Failure" is then that the MSC sends a
6793 * BSSMAP Clear Command: */
6794
6795 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6796 var BssmapCause cause := enum2int(cause_val);
6797 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6798
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006799 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006800 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006801 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006802
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006803 setverdict(pass);
6804 f_sleep(1.0);
6805
6806 setverdict(pass);
6807}
6808testcase TC_ho_in_fail_msc_clears() runs on test_CT {
6809 var MSC_ConnHdlr vc_conn;
6810 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6811
6812 f_init(1, true);
6813 f_sleep(1.0);
6814
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006815 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006816
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006817 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6818 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006819
6820 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears), pars);
6821 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006822
6823 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6824 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6825 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6826 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6827 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006828 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006829}
6830
6831private function f_tc_ho_in_fail_msc_clears_after_ho_detect(charstring id) runs on MSC_ConnHdlr {
6832 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6833 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6834 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6835 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6836 * before we get started. */
6837 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6838 f_rslem_register(0, new_chan_nr);
6839 g_chan_nr := new_chan_nr;
6840 f_sleep(1.0);
6841
6842 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6843 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6844 activate(as_Media());
6845
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006846 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006847 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006848 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006849
6850 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6851
6852 var PDU_BSSAP rx_bssap;
6853 var octetstring ho_command_str;
6854
6855 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6856
6857 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6858 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6859 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6860 log("L3 Info in HO Request Ack is ", ho_command);
6861
6862 var GsmArfcn arfcn;
6863 var RslChannelNr actual_new_chan_nr;
6864 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6865 actual_new_chan_nr, arfcn);
6866
6867 if (actual_new_chan_nr != new_chan_nr) {
6868 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6869 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6870 setverdict(fail);
6871 return;
6872 }
6873 log("Handover Command chan_nr is", actual_new_chan_nr);
6874
6875 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6876 * tells the MS to handover to the new lchan. Here comes the new MS on
6877 * the new lchan with a Handover RACH: */
6878
6879 /* send handover detect */
6880
6881 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6882
6883 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6884
6885 /* The MSC chooses to clear the connection now, maybe we got the
6886 * Handover RACH on the new cell but the MS still signaled Handover
6887 * Failure to the old BSS? */
6888
6889 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6890 var BssmapCause cause := enum2int(cause_val);
6891 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6892
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006893 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006894 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006895 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006896
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006897 f_sleep(1.0);
6898}
6899testcase TC_ho_in_fail_msc_clears_after_ho_detect() runs on test_CT {
6900 var MSC_ConnHdlr vc_conn;
6901 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6902
6903 f_init(1, true);
6904 f_sleep(1.0);
6905
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006906 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006907
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006908 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6909 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006910
6911 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears_after_ho_detect), pars);
6912 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006913
6914 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6915 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6916 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6917 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6918 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006919 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006920}
6921
6922/* The new BSS's lchan times out before the MSC decides that handover failed. */
6923private function f_tc_ho_in_fail_no_detect(charstring id) runs on MSC_ConnHdlr {
6924 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6925 f_rslem_register(0, new_chan_nr);
6926 g_chan_nr := new_chan_nr;
6927 f_sleep(1.0);
6928
6929 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6930 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Oliver Smith735b47c2023-02-15 16:03:54 +01006931 activate(as_Media());
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006932
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006933 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006934 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006935 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006936
6937 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6938
6939 var PDU_BSSAP rx_bssap;
6940 var octetstring ho_command_str;
6941
6942 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6943
6944 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6945 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6946 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6947 log("L3 Info in HO Request Ack is ", ho_command);
6948
6949 var GsmArfcn arfcn;
6950 var RslChannelNr actual_new_chan_nr;
6951 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6952 actual_new_chan_nr, arfcn);
6953
6954 if (actual_new_chan_nr != new_chan_nr) {
6955 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6956 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6957 setverdict(fail);
6958 return;
6959 }
6960 log("Handover Command chan_nr is", actual_new_chan_nr);
6961
6962 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6963 * tells the MS to handover to the new lchan. But the MS never shows up
6964 * on the new lchan. */
6965
6966 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6967
6968 /* Did osmo-bsc also send a Clear Request? */
6969 timer T := 0.5;
6970 T.start;
6971 alt {
6972 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
6973 [] T.timeout { }
6974 }
6975
6976 /* MSC plays along with a Clear Command (no matter whether osmo-bsc
6977 * asked for it, this is a Handover Failure after all). */
6978
6979 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6980 var BssmapCause cause := enum2int(cause_val);
6981 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6982
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006983 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006984 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006985 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006986
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006987 f_sleep(1.0);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006988}
6989testcase TC_ho_in_fail_no_detect() runs on test_CT {
6990 var MSC_ConnHdlr vc_conn;
6991 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6992
Oliver Smithd49f46d2023-03-08 12:23:13 +01006993 pars.fail_on_dlcx := false;
6994
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006995 f_init(1, true);
6996 f_sleep(1.0);
6997
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006998 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006999
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007000 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
7001 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007002
7003 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect), pars);
7004 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007005
7006 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7007 f_ctrs_bsc_and_bts_add(0, "handover:error");
7008 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
7009 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
7010 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007011 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007012}
7013
7014/* Same as f_tc_ho_in_fail_no_detect, but MSC fails to send a Clear Command */
7015private function f_tc_ho_in_fail_no_detect2(charstring id) runs on MSC_ConnHdlr {
7016 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
7017 f_rslem_register(0, new_chan_nr);
7018 g_chan_nr := new_chan_nr;
7019 f_sleep(1.0);
7020
7021 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
7022 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Oliver Smith735b47c2023-02-15 16:03:54 +01007023 activate(as_Media());
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007024
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007025 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007026 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02007027 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007028
7029 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
7030
7031 var PDU_BSSAP rx_bssap;
7032 var octetstring ho_command_str;
7033
7034 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
7035
7036 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
7037 log("Received L3 Info in HO Request Ack: ", ho_command_str);
7038 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
7039 log("L3 Info in HO Request Ack is ", ho_command);
7040
7041 var GsmArfcn arfcn;
7042 var RslChannelNr actual_new_chan_nr;
7043 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
7044 actual_new_chan_nr, arfcn);
7045
7046 if (actual_new_chan_nr != new_chan_nr) {
7047 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
7048 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
7049 setverdict(fail);
7050 return;
7051 }
7052 log("Handover Command chan_nr is", actual_new_chan_nr);
7053
7054 /* Now the MSC forwards the RR Handover Command to the other BSC, which
7055 * tells the MS to handover to the new lchan. But the MS never shows up
7056 * on the new lchan. */
7057
7058 BSSAP.receive(tr_BSSMAP_HandoverFailure);
7059
7060 /* MSC plays dumb and sends no Clear Command */
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007061 var PDU_BSSAP rx_clear_request;
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02007062
7063 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request {
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007064 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
7065 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
7066 };
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02007067 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007068 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007069 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007070
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007071 f_sleep(1.0);
7072}
7073testcase TC_ho_in_fail_no_detect2() runs on test_CT {
7074 var MSC_ConnHdlr vc_conn;
7075 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7076
Oliver Smith735b47c2023-02-15 16:03:54 +01007077 pars.fail_on_dlcx := false;
7078
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007079 f_init(1, true);
7080 f_sleep(1.0);
7081
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007082 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007083
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007084 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
7085 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007086
7087 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect2), pars);
7088 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007089
7090 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7091 f_ctrs_bsc_and_bts_add(0, "handover:error");
7092 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
7093 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
7094 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007095 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007096}
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01007097
Oliver Smith7a8594a2023-02-13 14:30:49 +01007098testcase TC_ho_in_fail_mgw_mdcx_timeout() runs on test_CT {
7099 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7100
7101 pars.ignore_mgw_mdcx := true;
7102 pars.expect_ho_fail_lchan_est := true;
7103
7104 f_tc_ho_into_this_bsc_main(pars);
7105 f_shutdown_helper(ho := true);
7106}
7107
Oliver Smith4eed06f2023-02-15 15:43:19 +01007108testcase TC_ho_in_fail_ipa_crcx_timeout() runs on test_CT {
7109 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7110
7111 pars.ignore_ipa_media := true;
7112 pars.expect_ho_fail_lchan_est := true;
7113 pars.fail_on_dlcx := false;
7114
7115 f_tc_ho_into_this_bsc_main(pars);
7116 f_shutdown_helper(ho := true);
7117}
7118
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01007119/* An incoming inter-BSC HO can either issue the Handover Request message attached to the initial SCCP N-Connect (as in
7120 * the other tests we have so far), or the first CR can be "empty" with the BSSAP request following later. Test the
7121 * empty N-Connect case. */
7122testcase TC_ho_into_this_bsc_sccp_cr_without_bssap() runs on test_CT {
7123 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7124 pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr := false;
7125 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02007126 f_shutdown_helper(ho := true);
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01007127}
7128
Neels Hofmeyr91401012019-07-11 00:42:35 +02007129type record of charstring Commands;
7130
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007131private function f_bts_0_cfg(TELNETasp_PT pt, Commands cmds := {})
Neels Hofmeyr91401012019-07-11 00:42:35 +02007132{
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007133 f_vty_enter_cfg_bts(pt, 0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007134 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007135 f_vty_transceive(pt, cmds[i]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007136 }
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007137 f_vty_transceive(pt, "end");
Neels Hofmeyr91401012019-07-11 00:42:35 +02007138}
7139
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01007140private function f_cs7_inst_0_cfg(TELNETasp_PT pt, Commands cmds := {})
7141{
7142 f_vty_enter_cfg_cs7_inst(pt, 0);
7143 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
7144 f_vty_transceive(pt, cmds[i]);
7145 }
7146 f_vty_transceive(pt, "end");
7147}
7148
Neels Hofmeyr91401012019-07-11 00:42:35 +02007149private function f_probe_for_handover(charstring log_label,
7150 charstring log_descr,
7151 charstring handover_vty_cmd,
7152 boolean expect_handover,
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007153 boolean is_inter_bsc_handover := false,
7154 template uint3_t expect_target_tsc := ?)
Neels Hofmeyr91401012019-07-11 00:42:35 +02007155runs on MSC_ConnHdlr
7156{
Neels Hofmeyrb3fc8982020-05-11 00:16:42 +02007157 /* We're going to thwart any and all handover attempts, just be ready to handle (and ignore) handover target
7158 * lchans to be established on bts 1 or bts 2. */
7159 f_rslem_suspend(RSL1_PROC);
7160 f_rslem_suspend(RSL2_PROC);
7161
Neels Hofmeyr91401012019-07-11 00:42:35 +02007162 var RSL_Message rsl;
7163
7164 var charstring log_msg := " (expecting handover)"
7165 if (not expect_handover) {
7166 log_msg := " (expecting NO handover)";
7167 }
7168 log("f_probe_for_handover starting: " & log_label & ": " & log_descr & log_msg);
7169 f_vty_transceive(BSCVTY, handover_vty_cmd);
7170
Neels Hofmeyr91401012019-07-11 00:42:35 +02007171 timer T := 2.0;
7172 T.start;
7173
7174 alt {
7175 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
7176 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
7177 log("Rx L3 from net: ", l3);
7178 if (ischosen(l3.msgs.rrm.handoverCommand)) {
7179 var RslChannelNr new_chan_nr;
7180 var GsmArfcn arfcn;
7181 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
7182 new_chan_nr, arfcn);
7183 log("Handover to new chan ", new_chan_nr, " on ARFCN ", arfcn);
7184 log(l3.msgs.rrm.handoverCommand);
7185
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007186 /* Verify correct TSC in handoverCommand */
7187 var uint3_t got_tsc := rr_chan_desc_tsc(l3.msgs.rrm.handoverCommand.channelDescription2);
7188 if (not match(got_tsc, expect_target_tsc)) {
7189 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
7190 expect_target_tsc, " got ", got_tsc);
7191 mtc.stop;
7192 } else {
7193 log("handoverCommand: verified TSC = ", got_tsc, " (matches ",
7194 expect_target_tsc, ")");
7195 }
7196
Neels Hofmeyr91401012019-07-11 00:42:35 +02007197 /* Need to register for new lchan on new BTS -- it's either bts 1 or bts 2. It doesn't really
7198 * matter on which BTS it really is, we're not going to follow through an entire handover
7199 * anyway. */
7200 f_rslem_register(0, new_chan_nr, RSL1_PROC);
7201 f_rslem_resume(RSL1_PROC);
7202 f_rslem_register(0, new_chan_nr, RSL2_PROC);
7203 f_rslem_resume(RSL2_PROC);
7204
7205 if (expect_handover and not is_inter_bsc_handover) {
7206 setverdict(pass);
7207 log("f_probe_for_handover(" & log_label & "): Got RSL Handover Command as expected.");
7208 } else {
7209 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got RSL Handover Command. "
7210 & log_label & ": " & log_descr);
7211 }
7212
7213 log("f_probe_for_handover(" & log_label & "): Ending the test: Handover Failure stops the procedure.");
7214 /* osmo-bsc has triggered Handover. That's all we need to know for this test, reply with
7215 * Handover Failure. */
7216 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
7217
7218 /* target BTS is told to release lchan again; don't care which BTS nor what messages. */
7219 f_sleep(0.5);
7220 RSL1.clear;
7221 RSL2.clear;
7222 log("f_probe_for_handover(" & log_label & "): done (got RSL Handover Command)");
7223 break;
7224 } else {
7225 repeat;
7226 }
7227 }
7228 [] BSSAP.receive(tr_BSSMAP_HandoverRequired) {
7229 if (expect_handover and is_inter_bsc_handover) {
7230 setverdict(pass);
7231 log("f_probe_for_handover(" & log_label & "): Got BSSMAP Handover Required as expected.");
7232 } else {
7233 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got BSSMAP Handover Required. "
7234 & log_label & ": " & log_descr);
7235 }
7236
7237 log("f_probe_for_handover(" & log_label & "): done (got BSSMAP Handover Required)");
7238
7239 /* Note: f_tc_ho_neighbor_config_start() sets T7, the timeout for BSSMAP Handover Required, to
7240 * 1 second. There is no legal way to quickly abort a handover after a BSSMAP Handover Required,
7241 * setting a short timeout and waiting is the only way. */
7242 log("f_probe_for_handover(" & log_label & "): waiting for inter-BSC HO to time out...");
7243 f_sleep(1.5);
7244 log("f_probe_for_handover(" & log_label & "): ...done");
7245
7246 break;
7247 }
7248 [] T.timeout {
7249 if (expect_handover) {
7250 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected Handover, but got none. "
7251 & log_label & ": " & log_descr);
7252 } else {
7253 setverdict(pass);
7254 log("f_probe_for_handover(" & log_label & "): Got no Handover, as expected.");
7255 }
7256 log("f_probe_for_handover(" & log_label & "): done (got no Handover)");
7257 break;
7258 }
7259 }
7260
7261 f_rslem_resume(RSL1_PROC);
7262 f_rslem_resume(RSL2_PROC);
7263 f_sleep(3.0);
7264 RSL.clear;
7265
7266 log("f_probe_for_handover(" & log_label & "): done clearing");
7267}
7268
7269/* Test the effect of various neighbor configuration scenarios:
7270 *
7271 * To avoid complexity, block off any actual handover operation, and always remain on the lchan at bts 0.
7272 * Reconfigure the neighbors for bts 0, trigger a Handover, and probe whether osmo-bsc does or doesn't start HO.
7273 */
7274private function f_tc_ho_neighbor_config_start() runs on MSC_ConnHdlr {
7275 g_pars := f_gen_test_hdlr_pars();
7276 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
7277 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007278
7279 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
7280 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
7281
7282 /* Establish lchan at bts 0 */
7283 f_establish_fully(ass_cmd, exp_compl);
7284
7285 /* Shorten the inter-BSC Handover timeout, to not wait so long for inter-BSC Handovers */
7286 f_vty_enter_cfg_network(BSCVTY);
7287 f_vty_transceive(BSCVTY, "timer T7 1");
7288 f_vty_transceive(BSCVTY, "end");
7289}
7290
7291private function f_tc_ho_neighbor_config_1(charstring id) runs on MSC_ConnHdlr {
7292 f_tc_ho_neighbor_config_start();
7293
7294 /*
7295 * bts 0 ARFCN 871 BSIC 10
7296 * bts 1 ARFCN 871 BSIC 11
7297 * bts 2 ARFCN 871 BSIC 12
7298 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7299 */
7300
7301 log("f_tc_ho_neighbor_config: 1. No 'neighbor' config");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007302 f_bts_0_cfg(BSCVTY, {"no neighbors"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007303 f_probe_for_handover("1.a", "HO to bts 1 works, implicitly listed as neighbor (legacy behavior when none are configured)",
7304 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007305 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007306
7307 f_probe_for_handover("1.b", "HO to unknown cell does not start",
7308 "handover any to arfcn 13 bsic 39",
7309 false);
7310
7311 f_probe_for_handover("1.c", "HO to 871-12 is ambiguous = error",
7312 "handover any to arfcn 871 bsic 12",
7313 false);
7314
7315 f_probe_for_handover("1.d", "HO to 871-11 still works (verify that this test properly cleans up)",
7316 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007317 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007318
7319 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007320}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007321testcase TC_ho_neighbor_config_1() runs on test_CT {
7322 var MSC_ConnHdlr vc_conn;
7323 f_init(3, true, guard_timeout := 60.0);
7324 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007325 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007326 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_1));
7327 vc_conn.done;
7328
7329 /* f_tc_ho_neighbor_config_start() */
7330 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7331 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7332
7333 /* 1.a */
7334 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7335 * handover quickly by sending a Handover Failure message. */
7336 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7337 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7338 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7339 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007340 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7341 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007342
7343 /* 1.b */
7344 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7345 f_ctrs_bsc_and_bts_add(0, "handover:error");
7346
7347 /* 1.c */
7348 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7349 f_ctrs_bsc_and_bts_add(0, "handover:error");
7350
7351 /* 1.d */
7352 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7353 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7354 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7355 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007356 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7357 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007358
7359 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007360 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007361}
7362
Neels Hofmeyr91401012019-07-11 00:42:35 +02007363private function f_tc_ho_neighbor_config_2(charstring id) runs on MSC_ConnHdlr {
7364 f_tc_ho_neighbor_config_start();
7365
7366 /*
7367 * bts 0 ARFCN 871 BSIC 10
7368 * bts 1 ARFCN 871 BSIC 11
7369 * bts 2 ARFCN 871 BSIC 12
7370 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7371 */
7372
7373 log("f_tc_ho_neighbor_config: 2. explicit local neighbor: 'neighbor bts 1'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007374 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007375 f_sleep(0.5);
7376
7377 f_probe_for_handover("2.a", "HO to bts 1 works, explicitly listed as neighbor",
7378 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007379 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007380
7381 f_probe_for_handover("2.b", "HO to bts 2 doesn't work, not listed as neighbor",
7382 "handover any to arfcn 871 bsic 12",
7383 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007384 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007385}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007386testcase TC_ho_neighbor_config_2() runs on test_CT {
7387 var MSC_ConnHdlr vc_conn;
7388 f_init(3, true, guard_timeout := 50.0);
7389 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007390 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007391 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_2));
7392 vc_conn.done;
7393
7394 /* f_tc_ho_neighbor_config_start() */
7395 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7396 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7397
7398 /* 2.a */
7399 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7400 * handover quickly by sending a Handover Failure message. */
7401 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7402 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7403 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7404 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007405 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7406 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007407
7408 /* 2.b */
7409 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7410 f_ctrs_bsc_and_bts_add(0, "handover:error");
7411
7412 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007413 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007414}
7415
Neels Hofmeyr91401012019-07-11 00:42:35 +02007416private function f_tc_ho_neighbor_config_3(charstring id) runs on MSC_ConnHdlr {
7417 f_tc_ho_neighbor_config_start();
7418
7419 /*
7420 * bts 0 ARFCN 871 BSIC 10
7421 * bts 1 ARFCN 871 BSIC 11
7422 * bts 2 ARFCN 871 BSIC 12
7423 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7424 */
7425
7426 log("f_tc_ho_neighbor_config: 3. explicit local neighbor: 'neighbor bts 2'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007427 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007428 f_sleep(0.5);
7429
7430 f_probe_for_handover("3.a", "HO to bts 1 doesn't work, not listed as neighbor",
7431 "handover any to arfcn 871 bsic 11",
7432 false);
7433 f_probe_for_handover("3.b", "HO to bts 2 works, explicitly listed as neighbor; no ambiguity because bts 3 is not listed as neighbor",
7434 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007435 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007436 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007437}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007438testcase TC_ho_neighbor_config_3() runs on test_CT {
7439 var MSC_ConnHdlr vc_conn;
7440 f_init(3, true, guard_timeout := 50.0);
7441 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007442 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007443 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_3));
7444 vc_conn.done;
7445
7446 /* f_tc_ho_neighbor_config_start() */
7447 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7448 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7449
7450 /* 3.a */
7451 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7452 f_ctrs_bsc_and_bts_add(0, "handover:error");
7453
7454 /* 3.b */
7455 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7456 * handover quickly by sending a Handover Failure message. */
7457 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7458 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7459 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7460 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007461 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7462 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007463
7464 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007465 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007466}
7467
Neels Hofmeyr91401012019-07-11 00:42:35 +02007468private function f_tc_ho_neighbor_config_4(charstring id) runs on MSC_ConnHdlr {
7469 f_tc_ho_neighbor_config_start();
7470
7471 /*
7472 * bts 0 ARFCN 871 BSIC 10
7473 * bts 1 ARFCN 871 BSIC 11
7474 * bts 2 ARFCN 871 BSIC 12
7475 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7476 */
7477
7478 log("f_tc_ho_neighbor_config: 4. explicit remote neighbor: 'neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007479 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007480 f_sleep(0.5);
7481
7482 f_probe_for_handover("4.a", "HO to bts 1 doesn't work, not listed as neighbor",
7483 "handover any to arfcn 871 bsic 11",
7484 false);
7485 f_probe_for_handover("4.b", "HO to bts 2 doesn't work, not listed as neighbor",
7486 "handover any to arfcn 871 bsic 12",
7487 false);
7488 f_probe_for_handover("4.c", "HO to 123-45 triggers inter-BSC HO",
7489 "handover any to arfcn 123 bsic 45",
7490 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007491 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007492}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007493testcase TC_ho_neighbor_config_4() runs on test_CT {
7494 var MSC_ConnHdlr vc_conn;
7495 f_init(3, true, guard_timeout := 50.0);
7496 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007497 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007498 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_4));
7499 vc_conn.done;
7500
7501 /* f_tc_ho_neighbor_config_start() */
7502 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7503 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7504
7505 /* 4.a */
7506 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7507 f_ctrs_bsc_and_bts_add(0, "handover:error");
7508
7509 /* 4.b */
7510 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7511 f_ctrs_bsc_and_bts_add(0, "handover:error");
7512
7513 /* 4.c */
7514 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7515 * handover quickly by timing out after the Handover Required message */
7516 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7517 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7518 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7519 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7520
7521 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007522 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007523}
7524
Neels Hofmeyr91401012019-07-11 00:42:35 +02007525private function f_tc_ho_neighbor_config_5(charstring id) runs on MSC_ConnHdlr {
7526 f_tc_ho_neighbor_config_start();
7527
7528 /*
7529 * bts 0 ARFCN 871 BSIC 10
7530 * bts 1 ARFCN 871 BSIC 11
7531 * bts 2 ARFCN 871 BSIC 12
7532 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7533 */
7534
7535 log("f_tc_ho_neighbor_config: 5. explicit remote neighbor re-using ARFCN+BSIC: 'neighbor lac 99 arfcn 871 bsic 12'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007536 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007537 f_sleep(0.5);
7538
7539 f_probe_for_handover("5.a", "HO to 871-12 triggers inter-BSC HO (ignoring local cells with same ARFCN+BSIC)",
7540 "handover any to arfcn 871 bsic 12",
7541 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007542 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007543}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007544testcase TC_ho_neighbor_config_5() runs on test_CT {
7545 var MSC_ConnHdlr vc_conn;
7546 f_init(3, true);
7547 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007548 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007549 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_5));
7550 vc_conn.done;
7551
7552 /* f_tc_ho_neighbor_config_start() */
7553 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7554 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7555
7556 /* 5 */
7557 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7558 * handover quickly by timing out after the Handover Required message */
7559 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7560 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7561 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7562 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7563
7564 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007565 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007566}
7567
Neels Hofmeyr91401012019-07-11 00:42:35 +02007568private function f_tc_ho_neighbor_config_6(charstring id) runs on MSC_ConnHdlr {
7569 f_tc_ho_neighbor_config_start();
7570
7571 /*
7572 * bts 0 ARFCN 871 BSIC 10
7573 * bts 1 ARFCN 871 BSIC 11
7574 * bts 2 ARFCN 871 BSIC 12
7575 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7576 */
7577
7578 log("f_tc_ho_neighbor_config: 6. config error: explicit local and remote neighbors with ambiguous ARFCN+BSIC:"
7579 & " 'neighbor bts 2; neighbor lac 99 arfcn 871 bsic 12'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007580 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007581 f_sleep(0.5);
7582
7583 f_probe_for_handover("6.a", "HO to 871-12 is ambiguous = error",
7584 "handover any to arfcn 871 bsic 12",
7585 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007586 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007587}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007588testcase TC_ho_neighbor_config_6() runs on test_CT {
7589 var MSC_ConnHdlr vc_conn;
7590 f_init(3, true);
7591 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007592 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007593 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_6));
7594 vc_conn.done;
7595
7596 /* f_tc_ho_neighbor_config_start() */
7597 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7598 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7599
7600 /* 6.a */
7601 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7602 * handover quickly by timing out after the Handover Required message */
7603 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7604 f_ctrs_bsc_and_bts_add(0, "handover:error");
7605
7606 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007607 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007608}
7609
Neels Hofmeyr91401012019-07-11 00:42:35 +02007610private function f_tc_ho_neighbor_config_7(charstring id) runs on MSC_ConnHdlr {
7611 f_tc_ho_neighbor_config_start();
7612
7613 /*
7614 * bts 0 ARFCN 871 BSIC 10
7615 * bts 1 ARFCN 871 BSIC 11
7616 * bts 2 ARFCN 871 BSIC 12
7617 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7618 */
7619
7620 log("f_tc_ho_neighbor_config: 7. explicit local and remote neighbors:"
7621 & " 'neighbor bts 2; neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007622 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007623 f_sleep(0.5);
7624
7625 f_probe_for_handover("7.a", "HO to 871-12 does HO to bts 2",
7626 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007627 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007628 f_probe_for_handover("7.b", "HO to 123-45 triggers inter-BSC HO",
7629 "handover any to arfcn 123 bsic 45",
7630 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007631 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007632}
Neels Hofmeyr91401012019-07-11 00:42:35 +02007633testcase TC_ho_neighbor_config_7() runs on test_CT {
7634 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf2b88032020-06-16 00:35:04 +02007635 f_init(3, true, guard_timeout := 50.0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007636 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007637 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007638 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_7));
7639 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007640
7641 /* f_tc_ho_neighbor_config_start() */
7642 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7643 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7644
7645 /* 7.a */
7646 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7647 * handover quickly by sending a Handover Failure message. */
7648 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7649 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7650 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7651 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007652 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7653 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007654
7655 /* 7.b */
7656 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7657 * handover quickly by timing out after the Handover Required message */
7658 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7659 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7660 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7661 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7662
7663 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007664 f_shutdown_helper(ho := true);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007665}
7666
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007667/* OS#3041: Open and close N connections in a normal fashion, and expect no
7668 * BSSMAP Reset just because of that. */
7669testcase TC_bssap_rlsd_does_not_cause_bssmap_reset() runs on test_CT {
7670 var default d;
7671 var integer i;
7672 var DchanTuple dt;
7673
7674 f_init();
7675
7676 /* Wait for initial BSSMAP Reset to pass */
7677 f_sleep(4.0);
7678
7679 d := activate(no_bssmap_reset());
7680
7681 /* Setup up a number of connections and RLSD them again from the MSC
7682 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7683 * Let's do it some more times for good measure. */
Harald Weltec3260d92018-06-11 17:48:16 +02007684 for (i := 0; i < 4; i := i+1) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007685 /* Since we're doing a lot of runs, give each one a fresh
7686 * T_guard from the top. */
7687 T_guard.start;
7688
7689 /* Setup a BSSAP connection and clear it right away. This is
7690 * the MSC telling the BSC about a planned release, it's not an
7691 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007692 dt := f_est_dchan(int2oct(i,1), 23+i, gen_l3_valid_payload());
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007693
7694 /* MSC disconnects (RLSD). */
7695 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
7696 }
7697
7698 /* In the buggy behavior, a timeout of 2 seconds happens between above
7699 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7700 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7701 f_sleep(4.0);
7702
7703 deactivate(d);
7704 f_shutdown_helper();
7705}
Harald Welte552620d2017-12-16 23:21:36 +01007706
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007707/* OS#3041: Open and close N connections in a normal fashion, and expect no
7708 * BSSMAP Reset just because of that. Invoke the release by a BSSMAP Clear from
7709 * the MSC. */
7710testcase TC_bssmap_clear_does_not_cause_bssmap_reset() runs on test_CT {
7711 var default d;
7712 var integer i;
7713 var DchanTuple dt;
7714 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007715 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_CALL_CONTROL;
7716 var BssmapCause cause := enum2int(cause_val);
7717
7718 f_init();
7719
7720 /* Wait for initial BSSMAP Reset to pass */
7721 f_sleep(4.0);
7722
7723 d := activate(no_bssmap_reset());
7724
7725 /* Setup up a number of connections and RLSD them again from the MSC
7726 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7727 * Let's do it some more times for good measure. */
7728 for (i := 0; i < 8; i := i+1) {
7729 /* Since we're doing a lot of runs, give each one a fresh
7730 * T_guard from the top. */
7731 T_guard.start;
7732
7733 /* Setup a BSSAP connection and clear it right away. This is
7734 * the MSC telling the BSC about a planned release, it's not an
7735 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007736 dt := f_est_dchan(int2oct(i,1), 23+i, gen_l3_valid_payload());
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007737
7738 /* Instruct BSC to clear channel */
7739 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7740
7741 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007742 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007743 }
7744
7745 /* In the buggy behavior, a timeout of 2 seconds happens between above
7746 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7747 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7748 f_sleep(4.0);
7749
7750 deactivate(d);
7751 f_shutdown_helper();
7752}
7753
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007754/* OS#3041: Open and close N connections in a normal fashion, and expect no
7755 * BSSMAP Reset just because of that. Close connections from the MS side with a
7756 * Release Ind on RSL. */
7757testcase TC_ms_rel_ind_does_not_cause_bssmap_reset() runs on test_CT {
7758 var default d;
7759 var integer i;
7760 var DchanTuple dt;
7761 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007762 var integer j;
7763
7764 f_init();
7765
7766 /* Wait for initial BSSMAP Reset to pass */
7767 f_sleep(4.0);
7768
7769 d := activate(no_bssmap_reset());
7770
7771 /* Setup up a number of connections and RLSD them again from the MSC
7772 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7773 * Let's do it some more times for good measure. */
7774 for (i := 0; i < 8; i := i+1) {
7775 /* Since we're doing a lot of runs, give each one a fresh
7776 * T_guard from the top. */
7777 T_guard.start;
7778
7779 /* Setup a BSSAP connection and clear it right away. This is
7780 * the MSC telling the BSC about a planned release, it's not an
7781 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007782 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007783
7784 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007785 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007786
7787 /* expect Clear Request on MSC side */
7788 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
7789
7790 /* Instruct BSC to clear channel */
7791 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
7792 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7793
7794 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007795 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007796 }
7797
7798 /* In the buggy behavior, a timeout of 2 seconds happens between above
7799 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7800 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7801 f_sleep(4.0);
7802
7803 deactivate(d);
7804 f_shutdown_helper();
7805}
7806
Harald Welte94e0c342018-04-07 11:33:23 +02007807/***********************************************************************
7808 * IPA style dynamic PDCH
7809 ***********************************************************************/
7810
7811private function f_dyn_ipa_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7812 template (omit) RSL_Cause nack := omit)
7813runs on test_CT {
7814 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7815 var RSL_Message rsl_unused;
7816 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7817 f_vty_ts_action("pdch activate", bts_nr, trx_nr, ts_nr);
7818 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007819 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007820 if (istemplatekind(nack, "omit")) {
7821 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007822 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007823 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007824 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007825 }
7826}
7827
7828private function f_dyn_ipa_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7829 template (omit) RSL_Cause nack := omit)
7830runs on test_CT {
7831 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7832 var RSL_Message rsl_unused;
7833 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7834 f_vty_ts_action("pdch deactivate", bts_nr, trx_nr, ts_nr);
7835 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007836 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_DEACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007837 if (istemplatekind(nack, "omit")) {
7838 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007839 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007840 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007841 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007842 }
7843}
7844
7845private function f_ts_dyn_mode_get(integer bts_nr, integer trx_nr, integer ts_nr)
7846runs on test_CT return charstring {
7847 var charstring cmd, resp;
7848 cmd := "show timeslot "&int2str(bts_nr)&" "&int2str(trx_nr)&" "&int2str(ts_nr);
Stefan Sperlingcff13562018-11-13 15:24:06 +01007849 return f_vty_transceive_match_regexp_retry(BSCVTY, cmd, "*\((*)\)*", 0, 4, 1.0);
Harald Welte94e0c342018-04-07 11:33:23 +02007850}
7851
7852private function f_ts_dyn_mode_assert(integer bts_nr, integer trx_nr, integer ts_nr,
7853 template charstring exp)
7854runs on test_CT {
7855 var charstring mode := f_ts_dyn_mode_get(bts_nr, trx_nr, ts_nr);
7856 if (not match(mode, exp)) {
7857 setverdict(fail, "Unexpected TS Mode: ", mode);
Daniel Willmannafce8662018-07-06 23:11:32 +02007858 mtc.stop;
Harald Welte94e0c342018-04-07 11:33:23 +02007859 }
7860}
7861
7862private function f_ts_set_chcomb(integer bts_nr, integer trx_nr, integer ts_nr, charstring chcomb)
7863runs on test_CT {
7864 f_vty_enter_cfg_ts(BSCVTY, bts_nr, trx_nr, ts_nr);
7865 f_vty_transceive(BSCVTY, "phys_chan_config " & chcomb);
7866 f_vty_transceive(BSCVTY, "end");
7867}
7868
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007869
7870private function f_ts_reset_chcomb(integer bts_nr) runs on test_CT {
7871 var integer i;
7872 for (i := 0; i < 8; i := i + 1) {
7873 f_ts_set_chcomb(bts_nr, 0, i, phys_chan_config[i]);
7874 }
7875}
7876
Harald Welte94e0c342018-04-07 11:33:23 +02007877private const charstring TCHF_MODE := "TCH/F mode";
7878private const charstring TCHH_MODE := "TCH/H mode";
7879private const charstring PDCH_MODE := "PDCH mode";
7880private const charstring NONE_MODE := "NONE mode";
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007881private const charstring SDCCH8_MODE := "SDCCH8 mode";
Harald Welte94e0c342018-04-07 11:33:23 +02007882
7883/* Test IPA PDCH activation / deactivation triggered by VTY */
7884testcase TC_dyn_pdch_ipa_act_deact() runs on test_CT {
7885 var RSL_Message rsl_unused;
7886
7887 /* change Timeslot 6 before f_init() starts RSL */
7888 f_init_vty();
7889 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7890 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7891
7892 f_init(1, false);
7893 f_sleep(1.0);
7894
7895 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7896
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007897 log("TCH/F_PDCH pchan starts out in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007898 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7899 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007900 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
7901 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007902 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007903 log("TCH/F_PDCH pchan, PDCH ACT was ACKed, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007904 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7905
7906 /* De-activate it via VTY */
7907 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7908 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007909 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007910 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7911
7912 /* re-activate it via VTY */
7913 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn);
7914 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007915 log("TCH/F_PDCH pchan, PDCH ACT via VTY, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007916 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7917
7918 /* and finally de-activate it again */
7919 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7920 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007921 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007922 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7923
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007924 /* clean up config */
7925 f_ts_set_chcomb(0, 0, 6, "PDCH");
7926
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007927 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007928}
7929
7930/* Test IPA PDCH activation NACK */
7931testcase TC_dyn_pdch_ipa_act_nack() runs on test_CT {
7932 var RSL_Message rsl_unused;
7933
7934 /* change Timeslot 6 before f_init() starts RSL */
7935 f_init_vty();
7936 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7937 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7938
7939 f_init(1, false);
7940 f_sleep(1.0);
7941
7942 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7943
7944 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7945 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007946 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
7947 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007948 f_sleep(1.0);
7949 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7950
7951 /* De-activate it via VTY */
7952 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7953 f_sleep(1.0);
7954 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7955
7956 /* re-activate it via VTY, but fail that; check BSC still assumes TCH/F mode */
7957 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn, RSL_ERR_EQUIPMENT_FAIL);
7958 f_sleep(1.0);
7959 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7960
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007961 /* clean up config */
7962 f_ts_set_chcomb(0, 0, 6, "PDCH");
7963
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007964 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007965}
7966
7967
7968/***********************************************************************
7969 * Osmocom style dynamic PDCH
7970 ***********************************************************************/
7971
7972private function f_dyn_osmo_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7973 template (omit) RSL_Cause nack := omit)
7974runs on test_CT {
7975 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
7976 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02007977 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02007978 /* FIXME: no VTY command to activate Osmocom PDCH !! */
7979 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007980 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT(chan_nr, ?));
Harald Welte94e0c342018-04-07 11:33:23 +02007981 if (istemplatekind(nack, "omit")) {
7982 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007983 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02007984 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007985 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007986 }
7987}
7988
7989private function f_dyn_osmo_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7990 template (omit) RSL_Cause nack := omit)
7991runs on test_CT {
7992 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
7993 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02007994 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02007995 /* FIXME: no VTY command to activate Osmocom PDCH !! */
7996 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007997 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007998 if (istemplatekind(nack, "omit")) {
7999 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008000 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008001 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008002 //f_ipa_tx(ts_RSL_RF_CHAN_REL_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02008003 }
8004}
8005
8006/* Test Osmocom dyn PDCH activation / deactivation triggered by VTY */
8007testcase TC_dyn_pdch_osmo_act_deact() runs on test_CT {
8008 var RSL_Message rsl_unused;
8009
8010 /* change Timeslot 6 before f_init() starts RSL */
8011 f_init_vty();
8012 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
8013 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8014
8015 f_init(1, false);
8016 f_sleep(1.0);
8017
8018 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
8019
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02008020 log("TCH/F_TCH/H_PDCH pchan starts out in disabled mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02008021 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8022 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008023 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008024
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008025 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02008026 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02008027 log("TCH/F_TCH/H_PDCH requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
Harald Welte94e0c342018-04-07 11:33:23 +02008028 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
8029
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008030 /* clean up config */
8031 f_ts_set_chcomb(0, 0, 6, "PDCH");
8032
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008033 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008034}
8035
8036/* Test Osmocom dyn PDCH activation NACK behavior */
8037testcase TC_dyn_pdch_osmo_act_nack() runs on test_CT {
8038 var RSL_Message rsl_unused;
8039
8040 /* change Timeslot 6 before f_init() starts RSL */
8041 f_init_vty();
8042 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
8043 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8044
8045 f_init(1, false);
8046 f_sleep(1.0);
8047
8048 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
8049
8050 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8051 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008052 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008053
8054 /* NACK this activation and expect the "show timeslot" mode still to be NONE */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008055 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
Harald Welte94e0c342018-04-07 11:33:23 +02008056 f_sleep(1.0);
8057 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8058
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008059 /* clean up config */
8060 f_ts_set_chcomb(0, 0, 6, "PDCH");
8061
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008062 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008063}
8064
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008065/* Test Osmocom dyn TS SDCCH8 activation / deactivation */
8066testcase TC_dyn_ts_sdcch8_act_deact() runs on test_CT {
8067 var RSL_Message rsl_unused, rsl_msg;
8068 var DchanTuple dt;
8069 var BSSAP_N_CONNECT_ind rx_c_ind;
8070
8071 /* change Timeslot 6 before f_init() starts RSL */
8072 f_init_vty();
8073 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
8074 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8075
8076 f_init(1, false);
8077 f_sleep(1.0);
8078
8079 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8080
8081 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8082 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8083 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008084 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008085
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008086 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008087 f_sleep(1.0);
8088 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8089 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8090
8091 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8092 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008093 var DchanTuples sdcch_cleanup := {};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008094 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008095 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008096 dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008097 sdcch_cleanup := sdcch_cleanup & { dt };
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008098 }
8099
8100 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008101 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8102 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8103 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008104
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008105 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008106 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008107 dt.idx := {0, 0};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008108
8109 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008110 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8111 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008112 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
8113
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008114 f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), '1234'O));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008115 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8116 dt.sccp_conn_id := rx_c_ind.connectionId;
8117 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8118
8119 /* Instruct BSC to clear channel */
8120 var BssmapCause cause := 0;
8121 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008122 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008123
8124 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008125 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8126 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008127 f_sleep(1.0);
8128 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8129
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008130 /* Clean up SDCCH lchans */
8131 for (i := 0; i < lengthof(sdcch_cleanup); i := i + 1) {
8132 f_perform_clear_test_ct(sdcch_cleanup[i]);
8133 }
8134
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008135 /* clean up config */
8136 f_ts_set_chcomb(0, 0, 6, "PDCH");
8137
8138 f_shutdown_helper();
8139}
8140
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008141/* Validate all 8 subslots of a dynamics TS configured as SDCCH8 are used */
8142testcase TC_dyn_ts_sdcch8_all_subslots_used() runs on test_CT {
8143 var ASP_RSL_Unitdata rsl_ud;
8144 var integer i;
8145 var integer chreq_total, chreq_nochan;
8146
8147 f_init_vty();
8148 for (i := 1; i < 8; i := i + 1) {
8149 if (i == 2) {
8150 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8151 } else {
8152 f_ts_set_chcomb(0, 0, i, "PDCH");
8153 }
8154 }
8155 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8156
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008157 f_init(1, guard_timeout := 60.0);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008158
8159 /* The dyn TS want to activate PDCH mode, ACK that. */
8160 var RslChannelNr chan_nr;
8161 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008162 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
8163 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008164
8165 f_sleep(1.0);
8166
8167 /* Exhaust all dedicated SDCCH lchans.
8168 /* GSM 44.018 Table 9.1.8.2:
8169 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
8170 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008171 var DchanTuples chan_cleanup := {};
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008172 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008173 chan_cleanup := chan_cleanup & { f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, gen_l3_valid_payload()) };
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008174 }
8175
8176 /* Only the dyn TS is still available. Its first lchan gets converted to SDCCH8 */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008177 chan_cleanup := chan_cleanup & { f_est_dchan_dyn('33'O, NUM_SDCCH_PER_BTS + i, gen_l3_valid_payload()) };
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008178 /* Also occupy the seven other SDCCH of the dyn TS */
8179 for (i := 0; i < 7; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008180 chan_cleanup := chan_cleanup & { f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, gen_l3_valid_payload()) };
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008181 }
8182
8183 /* Clean up SDCCH lchans */
8184 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8185 f_perform_clear_test_ct(chan_cleanup[i]);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008186 }
8187
8188 /* clean up config */
8189 f_ts_reset_chcomb(0);
8190
8191 f_shutdown_helper();
8192}
8193
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008194/* Test Osmocom dyn TS SDCCH8 activation / deactivation: If activating dyn TS as
8195 SDCCH8 would end up in having no free TCH, then BSC should decide to activate
8196 it as TCH directly instead. SYS#5309. */
8197testcase TC_dyn_ts_sdcch8_tch_call_act_deact() runs on test_CT {
8198 var RSL_Message rsl_unused, rsl_msg;
8199 var DchanTuple dt;
8200 var BSSAP_N_CONNECT_ind rx_c_ind;
8201 var integer i;
8202
8203 /* change Timeslot 6 before f_init() starts RSL */
8204 f_init_vty();
8205 for (i := 1; i < 8; i := i + 1) {
8206 if (i == 6) {
8207 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8208 } else {
8209 f_ts_set_chcomb(0, 0, i, "PDCH");
8210 }
8211 }
8212 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8213
8214 f_init(1, false);
8215 f_sleep(1.0);
8216
8217 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8218
8219 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8220 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8221 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008222 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008223
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008224 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008225 f_sleep(1.0);
8226 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8227 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8228
8229 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8230 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008231 var DchanTuples chan_cleanup := {};
Pau Espin Pedrol2ebbe7c2021-07-23 16:17:09 +02008232 var OCT1 ra := '43'O; /* RA containing reason=originating speech call*/
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008233 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008234 dt := f_est_dchan(ra, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008235 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008236 }
8237
8238 /* Now the dyn ts is selected. First PDCH is released, then TCH chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008239 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int(ra) + i, 1), 2342));
8240 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8241 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008242
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008243 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008244 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008245 dt.idx := {0, 0};
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008246
8247 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008248 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8249 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008250 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
8251
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008252 f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), '1234'O));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008253 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8254 dt.sccp_conn_id := rx_c_ind.connectionId;
8255 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8256
8257 /* Instruct BSC to clear channel */
8258 var BssmapCause cause := 0;
8259 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008260 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008261
8262 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008263 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8264 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008265 f_sleep(1.0);
8266 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8267
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008268 /* Clean up SDCCH lchans */
8269 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8270 f_perform_clear_test_ct(chan_cleanup[i]);
8271 }
8272
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008273 /* clean up config */
8274 f_ts_reset_chcomb(0);
8275 /* TODO: clean up other channels? */
8276
8277 f_shutdown_helper();
8278}
8279
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008280/* Test Osmocom dyn TS SDCCH8 activation / deactivation when SDCCH fails at BTS */
8281testcase TC_dyn_ts_sdcch8_act_nack() runs on test_CT {
8282 var RSL_Message rsl_unused, rsl_msg;
8283 var DchanTuple dt;
8284 var BSSAP_N_CONNECT_ind rx_c_ind;
8285 var GsmRrMessage rr;
8286
8287 /* change Timeslot 6 before f_init() starts RSL */
8288 f_init_vty();
8289 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
8290 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8291
8292 f_init(1, false);
8293 f_sleep(1.0);
8294
8295 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8296
8297 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8298 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8299 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008300 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008301
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008302 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008303 f_sleep(1.0);
8304 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8305 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8306
8307 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8308 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008309 var DchanTuples chan_cleanup := {};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008310 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008311 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008312 dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008313 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008314 }
8315
8316 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008317 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8318 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8319 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008320
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008321 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008322 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008323 dt.idx := {0, 0};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008324
8325 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008326 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(dt.rsl_chan_nr, RSL_ERR_EQUIPMENT_FAIL));
8327 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008328 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
8329 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
8330 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Expected reject");
8331 }
8332
8333 /* FIXME? Currently the TS stays in state BORKEN: */
8334
8335 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008336 /* rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8337 * f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008338 * f_sleep(1.0);
8339 * f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE)
8340 */
8341
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008342 /* Clean up SDCCH lchans */
8343 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8344 f_perform_clear_test_ct(chan_cleanup[i]);
8345 }
8346
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008347 /* clean up config */
8348 f_ts_set_chcomb(0, 0, 6, "PDCH");
8349
8350 f_shutdown_helper();
8351}
8352
Stefan Sperling0796a822018-10-05 13:01:39 +02008353testcase TC_chopped_ipa_ping() runs on test_CT {
Stefan Sperling554123f2018-10-09 14:12:30 +02008354 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port, mp_bsc_ctrl_port};
Stefan Sperling0796a822018-10-05 13:01:39 +02008355 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8356 IPA_Testing.f_run_TC_chopped_ipa_ping(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8357 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008358 f_shutdown_helper();
Stefan Sperling0796a822018-10-05 13:01:39 +02008359}
8360
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008361testcase TC_chopped_ipa_payload() runs on test_CT {
8362 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port
8363 /* TODO: mp_bsc_ctrl_port does not work yet */};
8364 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8365 IPA_Testing.f_run_TC_chopped_ipa_payload(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8366 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008367 f_shutdown_helper();
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008368}
8369
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008370/* Verify the BSC sends the MS Power Parameters IE during CHAN ACT to make sure
8371 the BTS does autonomous MS power control loop */
8372testcase TC_assignment_verify_ms_power_params_ie() runs on test_CT {
8373 var MSC_ConnHdlr vc_conn;
8374 var TestHdlrParams pars := f_gen_test_hdlr_pars();
8375 //pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
8376 pars.exp_ms_power_params := true;
8377
8378 f_init(1, true);
8379 f_sleep(1.0);
8380 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
8381 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008382 f_shutdown_helper();
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008383}
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008384
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008385/* Verify activation and deactivation of the BCCH carrier power reduction mode */
8386testcase TC_c0_power_red_mode() runs on test_CT {
8387 f_init(1);
8388
8389 for (var integer red := 6; red >= 0; red := red - 2) {
8390 /* Configure BCCH carrier power reduction mode via the VTY */
8391 f_vty_transceive(BSCVTY, "bts 0 c0-power-reduction " & int2str(red));
8392
8393 /* Expect Osmocom specific BS Power Control message on the RSL */
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03008394 var template (present) RSL_Message tr_rsl_pdu := tr_RSL_BS_PWR_CTRL(
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008395 chan_nr := t_RslChanNr_BCCH(0),
8396 bs_power := tr_RSL_IE_BS_Power(red / 2));
8397 tr_rsl_pdu.msg_disc := tr_RSL_MsgDisc(RSL_MDISC_CCHAN, false);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008398 var RSL_Message unused := f_exp_ipa_rx(tr_rsl_pdu);
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008399
8400 /* Additionally verify the applied value over the CTRL interface */
8401 var CtrlValue cred := f_ctrl_get_bts(IPA_CTRL, 0, "c0-power-reduction");
8402 if (cred != int2str(red)) {
8403 setverdict(fail, "Unexpected BCCH carrier power reduction value ",
8404 cred, " (expected ", red, ")");
8405 }
8406 }
8407
8408 f_shutdown_helper();
8409}
8410
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008411/***********************************************************************
8412 * MSC Pooling
8413 ***********************************************************************/
8414
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008415template MobileIdentityLV ts_MI_TMSI_NRI_LV(integer nri_v, integer nri_bitlen := 10) :=
Harald Weltebf397612021-01-14 20:39:46 +01008416 ts_MI_TMSI_LV(tmsi := f_gen_tmsi(suffix := 0, nri_v := nri_v, nri_bitlen := nri_bitlen));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008417
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008418private function f_expect_lchan_rel(RSL_DCHAN_PT rsl_pt, RSLEM_PROC_PT rsl_proc_pt, template PDU_ML3_NW_MS exp_rr_rel_tmpl := tr_RRM_RR_RELEASE)
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02008419runs on MSC_ConnHdlr {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008420 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008421 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008422 f_logp(BSCVTY, "Got RSL RR Release");
8423 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008424 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008425 f_logp(BSCVTY, "Got RSL Deact SACCH");
8426 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008427 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008428 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008429 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8430 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008431 break;
8432 }
8433 }
8434}
8435
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008436private altstep as_mgcp_ack_all_dlcx() runs on MSC_ConnHdlr {
8437 var MgcpCommand mgcp_cmd;
8438 [] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
8439 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
8440 repeat;
8441 }
8442}
8443
8444private altstep as_rsl_ack_all_rel_req() runs on MSC_ConnHdlr {
8445 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
8446 [] RSL.receive(tr_RSL_REL_REQ(g_chan_nr, ?)) {
8447 RSL.send(ts_RSL_REL_CONF(g_chan_nr, main_dcch));
8448 repeat;
8449 }
8450}
8451
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008452friend function f_perform_clear(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC,
8453 template PDU_ML3_NW_MS exp_rr_rel_tmpl := tr_RRM_RR_RELEASE)
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02008454runs on MSC_ConnHdlr {
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008455 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8456 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008457 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008458 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8459 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008460 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008461 f_logp(BSCVTY, "Got RSL RR Release");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008462 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008463 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008464 f_logp(BSCVTY, "Got RSL Deact SACCH");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008465 }
8466 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008467 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008468 /* Also drop the SCCP connection */
8469 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8470 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008471 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008472 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008473 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8474 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008475 }
8476 }
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008477 deactivate(ack_dlcx);
8478 deactivate(ack_rel_req);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008479}
8480
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01008481friend function f_perform_clear_no_rr_rel(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC)
8482runs on MSC_ConnHdlr {
8483 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8484 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
8485 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8486 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8487 interleave {
8488 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
8489 f_logp(BSCVTY, "Got RSL Deact SACCH");
8490 }
8491 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
8492 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8493 /* Also drop the SCCP connection */
8494 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8495 }
8496 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
8497 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
8498 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8499 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
8500 }
8501 }
8502 deactivate(ack_dlcx);
8503 deactivate(ack_rel_req);
8504}
8505
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01008506friend function f_perform_clear_no_lchan()
8507runs on MSC_ConnHdlr {
8508 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8509 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8510 BSSAP.receive(tr_BSSMAP_ClearComplete);
8511 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8512 /* Also drop the SCCP connection */
8513 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8514}
8515
Vadim Yanitskiy65d879d2022-06-23 18:15:39 +07008516friend function f_perform_clear_test_ct(DchanTuple dt)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008517 runs on test_CT
8518{
8519 /* Instruct BSC to clear channel */
8520 var BssmapCause cause := 0;
8521 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008522 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008523}
8524
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008525private function f_perform_compl_l3(RSL_DCHAN_PT rsl_pt, RSLEM_PROC_PT rsl_proc_pt,
8526 template PDU_ML3_MS_NW l3_info, boolean do_clear := true, boolean expect_bssmap_l3 := true)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008527runs on MSC_ConnHdlr {
8528 timer T := 10.0;
8529 var octetstring l3_enc := enc_PDU_ML3_MS_NW(valueof(l3_info));
8530
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008531 f_logp(BSCVTY, "establish channel, send Complete Layer 3 Info");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008532 f_create_bssmap_exp(l3_enc);
8533
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008534 /* RSL_Emulation.f_chan_est() on rsl_pt:
8535 * This is basically code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008536 * RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
8537 */
8538 var RSL_Message rx_rsl;
8539 var GsmRrMessage rr;
8540
8541 /* request a channel to be established */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008542 rsl_pt.send(ts_RSLDC_ChanRqd(g_pars.ra, g_pars.fn));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008543 /* expect immediate assignment.
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008544 * Code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008545 * rx_rsl := f_rx_or_fail(tr_RSL_IMM_ASSIGN);
8546 */
8547 timer Tt := 10.0;
8548
8549 /* request a channel to be established */
8550 Tt.start;
8551 alt {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008552 [] rsl_pt.receive(tr_RSL_IMM_ASSIGN) -> value rx_rsl {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008553 Tt.stop;
8554 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008555 [] rsl_pt.receive {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008556 setverdict(fail, "Unexpected RSL message on DCHAN");
8557 mtc.stop;
8558 }
8559 [] Tt.timeout {
8560 setverdict(fail, "Timeout waiting for RSL on DCHAN");
8561 mtc.stop;
8562 }
8563 }
8564 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
8565 g_chan_nr := rr.payload.imm_ass.chan_desc.chan_nr;
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008566 rsl_pt.send(ts_RSL_EST_IND(g_chan_nr, valueof(g_pars.link_id), l3_enc));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008567
8568
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008569 if (expect_bssmap_l3) {
8570 f_logp(BSCVTY, "expect BSSAP Complete Layer 3 Info at MSC");
8571 var template PDU_BSSAP exp_l3_compl;
8572 exp_l3_compl := tr_BSSMAP_ComplL3()
8573 if (g_pars.aoip == false) {
8574 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := omit;
8575 } else {
8576 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := ?;
8577 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008578
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008579 var PDU_BSSAP bssap;
8580 T.start;
8581 alt {
8582 [] BSSAP.receive(exp_l3_compl) -> value bssap {
8583 f_logp(BSCVTY, "received expected Complete Layer 3 Info at MSC");
8584 log("rx exp_l3_compl = ", bssap);
8585 }
8586 [] BSSAP.receive(tr_BSSMAP_ComplL3) {
8587 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received non-matching COMPLETE LAYER 3 INFORMATION");
8588 }
8589 [] T.timeout {
8590 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
8591 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008592 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008593
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008594 /* start ciphering, if requested */
8595 if (ispresent(g_pars.encr)) {
8596 f_logp(BSCVTY, "start ciphering");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008597 f_cipher_mode(g_pars.encr, rsl_pt := rsl_pt, rsl_proc_pt := rsl_proc_pt);
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008598 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008599 }
8600
8601 if (do_clear) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008602 f_perform_clear(rsl_pt, rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008603 }
8604 setverdict(pass);
8605 f_sleep(1.0);
8606}
8607
8608private function f_tc_mscpool_compl_l3(charstring id) runs on MSC_ConnHdlr {
8609 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8610 if (g_pars.mscpool.rsl_idx == 0) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008611 f_perform_compl_l3(RSL, RSL_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008612 } else if (g_pars.mscpool.rsl_idx == 1) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008613 f_perform_compl_l3(RSL1, RSL1_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008614 } else if (g_pars.mscpool.rsl_idx == 2) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008615 f_perform_compl_l3(RSL2, RSL2_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008616 }
8617}
8618
8619/* Various Complete Layer 3 by IMSI all end up with the first MSC, because the other MSCs are not connected. */
8620private function f_tc_mscpool_L3Compl_on_1_msc(charstring id) runs on MSC_ConnHdlr {
8621 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008622 f_perform_compl_l3(RSL, RSL_PROC, ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O) );
8623 f_perform_compl_l3(RSL, RSL_PROC, ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_IMSI_LV('001010000000002'H))) );
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008624 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)) );
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008625 f_perform_compl_l3(RSL, RSL_PROC, ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_IMSI_LV('001010000000004'H))) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008626}
8627testcase TC_mscpool_L3Compl_on_1_msc() runs on test_CT {
8628
8629 f_init(1, true);
8630 f_sleep(1.0);
8631 var MSC_ConnHdlr vc_conn;
8632 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008633
8634 f_ctrs_msc_init();
8635
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008636 vc_conn := f_start_handler(refers(f_tc_mscpool_L3Compl_on_1_msc), pars);
8637 vc_conn.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008638
8639 f_ctrs_msc_expect(0, "mscpool:subscr:new", 4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008640 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008641}
8642
8643/* Three Layer 3 Complete by IMSI are round-robin'ed across two connected MSCs */
8644/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8645 * just as well using only RSL. */
8646testcase TC_mscpool_L3Complete_by_imsi_round_robin() runs on test_CT {
8647
8648 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8649 f_sleep(1.0);
8650
8651 /* Control which MSC gets chosen next by the round-robin, otherwise
8652 * would be randomly affected by which other tests ran before this. */
8653 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8654
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008655 f_ctrs_msc_init();
8656
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008657 var MSC_ConnHdlr vc_conn1;
8658 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8659 pars1.mscpool.rsl_idx := 0;
8660 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
8661 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8662 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008663 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008664
8665 var MSC_ConnHdlr vc_conn2;
8666 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8667 pars2.mscpool.rsl_idx := 1;
8668 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
8669 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8670 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008671 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008672
8673 /* Test round-robin wrap to the first MSC */
8674 var MSC_ConnHdlr vc_conn3;
8675 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8676 pars3.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008677 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008678 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8679 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008680 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008681 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008682}
8683
8684/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 0
8685 * (configured in osmo-bsc.cfg). */
8686/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8687 * just as well using only RSL. */
8688testcase TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() runs on test_CT {
8689
8690 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8691 f_sleep(1.0);
8692
8693 /* Control which MSC gets chosen next by the round-robin, otherwise
8694 * would be randomly affected by which other tests ran before this. */
8695 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8696
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008697 f_ctrs_msc_init();
8698
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008699 var MSC_ConnHdlr vc_conn1;
8700 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8701 pars1.mscpool.rsl_idx := 0;
8702 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8703 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8704 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008705 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008706
8707 var MSC_ConnHdlr vc_conn2;
8708 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8709 pars2.mscpool.rsl_idx := 1;
8710 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8711 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8712 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008713 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008714
8715 /* Test round-robin wrap to the first MSC */
8716 var MSC_ConnHdlr vc_conn3;
8717 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8718 pars3.mscpool.rsl_idx := 2;
8719 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8720 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8721 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008722 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008723 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008724}
8725
8726/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 1
8727 * (configured in osmo-bsc.cfg). In this case, one of the MSC also has the NULL-NRI as part of its owned NRIs, but the
8728 * NULL-NRI setting is stronger than that. */
8729/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8730 * just as well using only RSL. */
8731testcase TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() runs on test_CT {
8732
8733 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8734 f_sleep(1.0);
8735
8736 /* Control which MSC gets chosen next by the round-robin, otherwise
8737 * would be randomly affected by which other tests ran before this. */
8738 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8739
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008740 f_ctrs_msc_init();
8741
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008742 var MSC_ConnHdlr vc_conn1;
8743 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8744 pars1.mscpool.rsl_idx := 0;
8745 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8746 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8747 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008748 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008749
8750 var MSC_ConnHdlr vc_conn2;
8751 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8752 pars2.mscpool.rsl_idx := 1;
8753 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8754 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8755 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008756 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008757
8758 /* Test round-robin wrap to the first MSC */
8759 var MSC_ConnHdlr vc_conn3;
8760 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8761 pars3.mscpool.rsl_idx := 2;
8762 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8763 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8764 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008765 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008766 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008767}
8768
8769/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI not
8770 * assigned to any MSC (configured in osmo-bsc.cfg). */
8771/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8772 * just as well using only RSL. */
8773testcase TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() runs on test_CT {
8774
8775 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8776 f_sleep(1.0);
8777
8778 /* Control which MSC gets chosen next by the round-robin, otherwise
8779 * would be randomly affected by which other tests ran before this. */
8780 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8781
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008782 f_ctrs_msc_init();
8783
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008784 var MSC_ConnHdlr vc_conn1;
8785 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8786 pars1.mscpool.rsl_idx := 0;
8787 /* An NRI that is not assigned to any MSC */
8788 pars1.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(1023))));
8789 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8790 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008791 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008792
8793 var MSC_ConnHdlr vc_conn2;
8794 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8795 pars2.mscpool.rsl_idx := 1;
8796 /* An NRI that is not assigned to any MSC */
8797 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(768)), '00F110'O));
8798 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8799 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008800 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008801
8802 /* Test round-robin wrap to the first MSC */
8803 var MSC_ConnHdlr vc_conn3;
8804 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8805 pars3.mscpool.rsl_idx := 2;
8806 /* An NRI that is not assigned to any MSC */
8807 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_SS_ACT, valueof(ts_MI_TMSI_NRI_LV(819))));
8808 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8809 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008810 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008811 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008812}
8813
8814/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI
8815 * assigned to an MSC that is currently not connected (configured in osmo-bsc.cfg). */
8816/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8817 * just as well using only RSL. */
8818testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() runs on test_CT {
8819
8820 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8821 f_sleep(1.0);
8822
8823 /* Control which MSC gets chosen next by the round-robin, otherwise
8824 * would be randomly affected by which other tests ran before this. */
8825 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8826
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008827 f_ctrs_msc_init();
8828
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008829 var MSC_ConnHdlr vc_conn1;
8830 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8831 pars1.mscpool.rsl_idx := 0;
8832 /* An NRI that is assigned to an unconnected MSC */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008833 pars1.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(512)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008834 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8835 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008836 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8837 f_ctrs_msc_add(0, "mscpool:subscr:new");
8838 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008839
8840 var MSC_ConnHdlr vc_conn2;
8841 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8842 pars2.mscpool.rsl_idx := 1;
8843 /* An NRI that is assigned to an unconnected MSC */
8844 pars2.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(767))));
8845 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8846 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008847 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8848 f_ctrs_msc_add(1, "mscpool:subscr:new");
8849 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008850
8851 /* Test round-robin wrap to the first MSC */
8852 var MSC_ConnHdlr vc_conn3;
8853 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8854 pars3.mscpool.rsl_idx := 2;
8855 /* An NRI that is assigned to an unconnected MSC */
8856 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(750)), '00F110'O));
8857 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8858 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008859 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8860 f_ctrs_msc_add(0, "mscpool:subscr:new");
8861 f_ctrs_msc_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008862 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008863}
8864
8865/* Three Layer 3 Complete by TMSI with valid NRI for the second MSC are all directed to the second MSC (configured in
8866 * osmo-bsc.cfg). */
8867/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8868 * just as well using only RSL. */
8869testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_1() runs on test_CT {
8870
8871 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8872 f_sleep(1.0);
8873
8874 /* All TMSIs in this test point at the second MSC, set the round robin to point at the first MSC to make sure
8875 * this is not using round-robin. */
8876 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8877
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008878 f_ctrs_msc_init();
8879
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008880 var MSC_ConnHdlr vc_conn1;
8881 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
8882 pars1.mscpool.rsl_idx := 0;
8883 /* An NRI of the second MSC's range (256-511) */
8884 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(256))));
8885 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8886 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008887 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008888
8889 var MSC_ConnHdlr vc_conn2;
8890 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8891 pars2.mscpool.rsl_idx := 1;
8892 /* An NRI of the second MSC's range (256-511) */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008893 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(260)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008894 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8895 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008896 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008897
8898 var MSC_ConnHdlr vc_conn3;
8899 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8900 pars3.mscpool.rsl_idx := 2;
8901 /* An NRI of the second MSC's range (256-511) */
8902 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(511)), '00F110'O));
8903 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8904 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008905 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008906 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008907}
8908
8909/* Layer 3 Complete by TMSI with valid NRI for the third MSC are directed to the third MSC (configured in osmo-bsc.cfg),
8910 * while a round-robin remains unaffected by that. */
8911/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8912 * just as well using only RSL. */
8913testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_2() runs on test_CT {
8914
8915 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8916 f_sleep(1.0);
8917
8918 /* All TMSIs in this test point at the third MSC, set the round robin to point at the second MSC to make sure
8919 * this is not using round-robin. */
8920 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
8921
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008922 f_ctrs_msc_init();
8923
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008924 var MSC_ConnHdlr vc_conn1;
8925 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 2);
8926 pars1.mscpool.rsl_idx := 0;
8927 /* An NRI of the third MSC's range (512-767) */
8928 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(512))));
8929 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8930 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008931 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008932
8933 var MSC_ConnHdlr vc_conn2;
8934 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8935 pars2.mscpool.rsl_idx := 1;
8936 /* An NRI of the third MSC's range (512-767) */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008937 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(678)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008938 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8939 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008940 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008941
8942 /* The above forwardings to third MSC have not affected the round robin, which still points at the second MSC */
8943 var MSC_ConnHdlr vc_conn3;
8944 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8945 pars3.mscpool.rsl_idx := 2;
8946 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000013'H)), '00F110'O));
8947 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8948 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008949 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008950 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008951}
8952
8953/* LU with a TMSI but indicating a different PLMN in its previous LAI: ignore the NRI. */
8954/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8955 * just as well using only RSL. */
8956testcase TC_mscpool_LU_by_tmsi_from_other_PLMN() runs on test_CT {
8957
8958 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8959 f_sleep(1.0);
8960
8961 /* The TMSIs in this test points at the second MSC, but since it is from a different PLMN, round-robin is used
8962 * instead, and hits msc 0. */
8963 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8964
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008965 f_ctrs_msc_init();
8966
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008967 /* An NRI of the second MSC's range (256-511), but a PLMN that doesn't match with osmo-bsc.cfg */
8968 var MSC_ConnHdlr vc_conn1;
8969 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8970 pars1.mscpool.rsl_idx := 0;
8971 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(260)), '99F999'O));
8972 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8973 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008974 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008975
8976 /* An NRI of the third MSC's range (512-767) and a matching PLMN gets directed by NRI. */
8977 var MSC_ConnHdlr vc_conn2;
8978 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8979 pars2.mscpool.rsl_idx := 1;
8980 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(555)), '00F110'O));
8981 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8982 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008983 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008984 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008985}
8986
8987/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by IMSI, which would be
8988 * round-robined to another MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
8989private function f_tc_mscpool_paging_imsi(charstring id) runs on MSC_ConnHdlr {
8990 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
8991 //cid_list := { cIl_allInBSS := ''O };
8992 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
8993 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
8994 var BSSAP_N_UNITDATA_req paging;
8995 var hexstring imsi := '001010000000123'H;
8996
8997 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8998
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008999 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009000 valueof(ts_BSSMAP_Paging(imsi, cid_list, omit, bssmap_chneed))));
9001 BSSAP.send(paging);
9002
9003 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
9004 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
9005 * channel number is picked here. */
9006 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
9007 f_rslem_register(0, new_chan_nr);
9008 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(imsi)));
9009 f_rslem_unregister(0, new_chan_nr);
9010
9011 /* Despite the round robin pointing at the second MSC ('roundrobin next 1'), the earlier Paging for the same IMSI
9012 * causes this Paging Response to go to the first MSC (bssap_idx := 0). */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009013 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_IMSI_LV(imsi)) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009014 f_sleep(1.0);
9015}
9016testcase TC_mscpool_paging_and_response_imsi() runs on test_CT {
9017 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
9018 f_sleep(1.0);
9019
9020 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
9021 * second MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
9022 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
9023
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009024 f_ctrs_msc_init();
9025
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009026 var MSC_ConnHdlr vc_conn1;
9027 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9028 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009029 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
9030 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009031 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_imsi), pars1);
9032 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009033 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009034 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009035}
9036
9037/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by TMSI with an NRI value
9038 * that matches a different MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
9039private function f_tc_mscpool_paging_tmsi(charstring id) runs on MSC_ConnHdlr {
9040 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
9041 //cid_list := { cIl_allInBSS := ''O };
9042 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
9043 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
9044 var integer nri_v := 300; /* <-- second MSC's NRI */
Harald Weltebf397612021-01-14 20:39:46 +01009045 var octetstring tmsi := f_gen_tmsi(suffix := 0, nri_v := nri_v);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009046 var BSSAP_N_UNITDATA_req paging;
9047
9048 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9049
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009050 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009051 valueof(ts_BSSMAP_Paging('001010000000011'H, cid_list, tmsi, bssmap_chneed))));
9052 BSSAP.send(paging);
9053
9054 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
9055 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
9056 * channel number is picked here. */
9057 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
9058 f_rslem_register(0, new_chan_nr);
9059 RSL.receive(tr_RSL_PAGING_CMD(t_MI_TMSI(tmsi)));
9060 f_rslem_unregister(0, new_chan_nr);
9061
9062 /* Despite the NRI matching the second MSC (NRI from 'msc 1' in osmo-bsc.cfg) and round robin pointing at the
9063 * third MSC ('roundrobin next 2'), the earlier Paging for the same TMSI causes this Paging Response to go to
9064 * the first MSC (bssap_idx := 0). */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009065 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_TMSI_NRI_LV(nri_v)) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009066 f_sleep(1.0);
9067}
9068testcase TC_mscpool_paging_and_response_tmsi() runs on test_CT {
9069 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
9070 f_sleep(1.0);
9071
9072 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
9073 * third MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
9074 f_vty_transceive(BSCVTY, "mscpool roundrobin next 2");
9075
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009076 f_ctrs_msc_init();
9077
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009078 var MSC_ConnHdlr vc_conn1;
9079 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9080 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009081 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
9082 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009083 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_tmsi), pars1);
9084 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009085 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009086 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009087}
9088
9089/* For round-robin, skip an MSC that has 'no allow-attach' set. */
9090/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
9091 * just as well using only RSL. */
9092testcase TC_mscpool_no_allow_attach_round_robin() runs on test_CT {
9093
9094 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9095 f_sleep(1.0);
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00009096 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
9097 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009098
9099 /* Control which MSC gets chosen next by the round-robin, otherwise
9100 * would be randomly affected by which other tests ran before this. */
9101 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9102
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009103 f_ctrs_msc_init();
9104
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009105 var MSC_ConnHdlr vc_conn1;
9106 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9107 pars1.mscpool.rsl_idx := 0;
9108 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
9109 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9110 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009111 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009112
9113 var MSC_ConnHdlr vc_conn2;
9114 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
9115 pars2.mscpool.rsl_idx := 1;
9116 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9117 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9118 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009119 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009120
9121 var MSC_ConnHdlr vc_conn3;
9122 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
9123 pars3.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009124 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009125 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9126 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009127 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009128 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009129}
9130
9131/* An MSC that has 'no allow-attach' set should still serve subscribers that are already attached according to their
9132 * TMSI NRI. */
9133testcase TC_mscpool_no_allow_attach_valid_nri() runs on test_CT {
9134
9135 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9136 f_sleep(1.0);
9137
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00009138 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
9139 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
9140
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009141 /* Control which MSC gets chosen next by the round-robin, otherwise
9142 * would be randomly affected by which other tests ran before this. */
9143 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9144
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009145 f_ctrs_msc_init();
9146
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009147 /* Round robin points at msc 0, but the valid NRI directs to msc 1, even though msc 1 has 'no allow-attach'. */
9148 var MSC_ConnHdlr vc_conn1;
9149 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
9150 pars1.mscpool.rsl_idx := 0;
9151 /* An NRI of the second MSC's range (256-511) */
9152 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_TMSI_NRI_LV(260))));
9153 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9154 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009155 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009156
9157 var MSC_ConnHdlr vc_conn2;
9158 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 0);
9159 pars2.mscpool.rsl_idx := 1;
9160 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9161 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9162 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009163 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009164
9165 var MSC_ConnHdlr vc_conn3;
9166 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 2);
9167 pars3.mscpool.rsl_idx := 2;
9168 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000003'H))));
9169 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9170 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009171 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009172 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009173}
9174
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +02009175/* When an MSC point-code gets an SCCP N-PCSTATE saying it is unreachable, immediately mark the MSC as unusable. */
9176testcase TC_mscpool_sccp_n_pcstate_detaches_msc() runs on test_CT {
9177
9178 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
9179 f_sleep(1.0);
9180
9181 /* Control which MSC gets chosen next by the round-robin, otherwise
9182 * would be randomly affected by which other tests ran before this. */
9183 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9184
9185 f_ctrs_msc_init();
9186
9187 var MSC_ConnHdlr vc_conn1;
9188 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9189 pars1.mscpool.rsl_idx := 0;
9190 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
9191 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9192 vc_conn1.done;
9193 f_ctrs_msc_expect(0, "mscpool:subscr:new");
9194
9195 var MSC_ConnHdlr vc_conn2;
9196 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
9197 pars2.mscpool.rsl_idx := 1;
9198 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9199 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9200 vc_conn2.done;
9201 f_ctrs_msc_expect(1, "mscpool:subscr:new");
9202
9203 f_logp(BSCVTY, "disconnecting msc0");
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02009204 f_bssap_idx_disconnect(0);
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +02009205
9206 /* Now round-robin would wrap to the first MSC, but since the first MSC is disconnected, it wraps around to msc
9207 * 2 again. */
9208 var MSC_ConnHdlr vc_conn3;
9209 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
9210 pars3.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009211 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +02009212 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9213 vc_conn3.done;
9214 f_ctrs_msc_expect(1, "mscpool:subscr:new");
9215 f_shutdown_helper();
9216}
9217
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02009218/* When an MSC point-code gets an SCCP N-PCSTATE saying it is now reachable, immediately trigger RESET and bring up the
9219 * MSC. */
9220testcase TC_mscpool_sccp_n_pcstate_attaches_msc() runs on test_CT {
9221
9222 f_init(nr_bts := 3, handler_mode := true, nr_msc := 1);
9223 f_sleep(1.0);
9224
9225 /* Control which MSC gets chosen next by the round-robin, otherwise
9226 * would be randomly affected by which other tests ran before this. */
9227 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9228
9229 f_ctrs_msc_init();
9230
9231 /* There is only one MSC, round robin stays on msc0 */
9232 var MSC_ConnHdlr vc_conn1;
9233 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9234 pars1.mscpool.rsl_idx := 0;
9235 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('0010100230000001'H)), '00F110'O));
9236 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9237 vc_conn1.done;
9238 f_ctrs_msc_expect(0, "mscpool:subscr:new");
9239
9240 var MSC_ConnHdlr vc_conn2;
9241 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 0);
9242 pars2.mscpool.rsl_idx := 1;
9243 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010023000002'H))));
9244 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9245 vc_conn2.done;
9246 f_ctrs_msc_expect(0, "mscpool:subscr:new");
9247
9248 f_logp(BSCVTY, "connecting msc1");
9249 f_vty_msc_allow_attach(BSCVTY, { true, true });
9250 f_bssap_idx_init(1);
9251 f_sleep(1.0);
9252
9253 /* This time round-robin wraps to the second MSC, because it is now online. */
9254 var MSC_ConnHdlr vc_conn4;
9255 var TestHdlrParams pars4 := f_gen_test_hdlr_pars(bssap_idx := 1);
9256 pars4.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009257 pars4.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010023000003'H)));
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02009258 vc_conn4 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars4);
9259 vc_conn4.done;
9260 f_ctrs_msc_expect(1, "mscpool:subscr:new");
9261
9262 f_shutdown_helper();
9263}
9264
Philipp Maier783681c2020-07-16 16:47:06 +02009265/* Allow/Deny emergency calls globally via VTY */
9266private function f_vty_allow_emerg_msc(boolean allow) runs on test_CT {
9267 f_vty_enter_cfg_msc(BSCVTY, 0);
9268 if (allow) {
9269 f_vty_transceive(BSCVTY, "allow-emergency allow");
9270 } else {
9271 f_vty_transceive(BSCVTY, "allow-emergency deny");
9272 }
9273 f_vty_transceive(BSCVTY, "exit");
9274 f_vty_transceive(BSCVTY, "exit");
9275}
9276
9277/* Allow/Deny emergency calls per BTS via VTY */
9278private function f_vty_allow_emerg_bts(boolean allow, integer bts_nr) runs on test_CT {
9279 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9280 if (allow) {
9281 f_vty_transceive(BSCVTY, "rach emergency call allowed 1");
9282 } else {
9283 f_vty_transceive(BSCVTY, "rach emergency call allowed 0");
9284 }
9285 f_vty_transceive(BSCVTY, "exit");
9286 f_vty_transceive(BSCVTY, "exit");
Neels Hofmeyrb6ed80c2020-10-12 22:52:39 +00009287 f_vty_transceive(BSCVTY, "exit");
Philipp Maier783681c2020-07-16 16:47:06 +02009288}
9289
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02009290/* Allow/Forbid Fast Return after SRVCC on a given BTS via VTY */
9291private function f_vty_allow_srvcc_fast_return(boolean allow, integer bts_nr) runs on test_CT {
9292 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9293 if (allow) {
9294 f_vty_transceive(BSCVTY, "srvcc fast-return allow");
9295 } else {
9296 f_vty_transceive(BSCVTY, "srvcc fast-return forbid");
9297 }
9298 f_vty_transceive(BSCVTY, "exit");
9299 f_vty_transceive(BSCVTY, "exit");
9300 f_vty_transceive(BSCVTY, "exit");
9301}
9302
Pau Espin Pedrol14475352021-07-22 15:48:16 +02009303/* Allow/Forbid TCH for signalling if SDCCH exhausted on a given BTS via VTY */
9304private function f_vty_allow_tch_for_signalling(boolean allow, integer bts_nr) runs on test_CT {
9305 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9306 if (allow) {
9307 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 1");
9308 } else {
9309 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 0");
9310 }
9311 f_vty_transceive(BSCVTY, "exit");
9312 f_vty_transceive(BSCVTY, "exit");
9313 f_vty_transceive(BSCVTY, "exit");
9314}
9315
Pau Espin Pedrol35609792023-01-03 16:56:59 +01009316/* Begin assignment procedure and send an EMERGENCY SETUP (RR) */
Philipp Maier783681c2020-07-16 16:47:06 +02009317private function f_assignment_emerg_setup() runs on MSC_ConnHdlr {
9318 var PDU_ML3_MS_NW emerg_setup;
9319 var octetstring emerg_setup_enc;
9320 var RSL_Message emerg_setup_data_ind;
9321
9322 f_establish_fully(omit, omit);
9323
9324 emerg_setup := valueof(ts_ML3_MO_CC_EMERG_SETUP(1, valueof(ts_Bcap_voice)));
9325 emerg_setup_enc := enc_PDU_ML3_MS_NW(emerg_setup);
9326 emerg_setup_data_ind := valueof(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), emerg_setup_enc));
9327
9328 RSL.send(emerg_setup_data_ind);
9329}
9330
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009331/* expect EmergencySetup on BSSAP after calling f_assignment_emerg_setup() */
9332private function f_assignment_emerg_setup_exp_bssap()
9333runs on MSC_ConnHdlr {
Philipp Maier783681c2020-07-16 16:47:06 +02009334 var PDU_BSSAP emerg_setup_data_ind_bssap;
9335 var PDU_ML3_MS_NW emerg_setup;
9336 timer T := 3.0;
9337
Philipp Maier783681c2020-07-16 16:47:06 +02009338 T.start;
9339 alt {
9340 [] BSSAP.receive(tr_BSSAP_DTAP) -> value emerg_setup_data_ind_bssap {
9341 emerg_setup := dec_PDU_ML3_MS_NW(emerg_setup_data_ind_bssap.pdu.dtap);
9342 if (not isbound(emerg_setup.msgs.cc.emergencySetup)) {
9343 setverdict(fail, "no emergency setup");
9344 }
9345 }
9346 [] BSSAP.receive {
9347 setverdict(fail, "unexpected BSSAP message!");
9348 }
9349 [] T.timeout {
9350 setverdict(fail, "timout waiting for EMERGENCY SETUP!");
9351 }
9352 }
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009353}
9354
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009355private function f_assignment_emerg_setup_voice()
9356runs on MSC_ConnHdlr {
9357 /* Go on with voice call assignment */
9358 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
9359 var PDU_BSSAP ass_cmd := f_gen_ass_req();
9360
9361 /* Below speechOrDataIndicator and codecList are copied from an emergency call captured during tests.
9362 * They seem a bit weird (AMR-WB, and the order differ between speechId_DataIndicator and the codecList), but
9363 * seems a good idea to see how osmo-bsc reacts to this. */
9364 ass_cmd.pdu.bssmap.assignmentRequest.channelType := {
9365 elementIdentifier := '0B'O, /* overwritten */
9366 lengthIndicator := 0, /* overwritten */
9367 speechOrDataIndicator := '0001'B, /* speech */
9368 spare1_4 := '0000'B,
9369 channelRateAndType := ChRate_TCHForH_Fpref,
9370 speechId_DataIndicator := 'c2918105'O
9371 };
9372 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({
9373 ts_CodecHR, ts_CodecAMR_WB, ts_CodecEFR, ts_CodecFR}));
9374
9375 f_rslem_dchan_queue_enable();
9376
9377 var ExpectCriteria mgcpcrit := {
9378 connid := omit,
9379 endpoint := omit,
9380 transid := omit
9381 };
9382 f_create_mgcp_expect(mgcpcrit);
9383
9384 BSSAP.send(ass_cmd);
9385
9386 var AssignmentState st := valueof(ts_AssignmentStateInit);
9387 st.voice_call := true;
9388 st.is_assignment := false;
9389 alt {
9390 [] as_modify(st);
9391 [] as_Media();
9392 [st.modify_done] BSSAP.receive(exp_compl) {
9393 setverdict(pass);
9394 }
9395 }
9396
9397 /* Voice call carries on ... */
9398 f_sleep(2.0);
9399}
9400
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009401/* Test if the EMERGENCY SETUP gets passed on to the MSC via A when EMERGENCY
9402 * CALLS are permitted by the BSC config. */
9403private function f_TC_assignment_emerg_setup_allow(charstring id) runs on MSC_ConnHdlr {
9404
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009405 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
9406 * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
9407 * another lchan. */
9408 g_pars.ra := f_rnd_ra_emerg();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009409 f_assignment_emerg_setup();
9410 f_assignment_emerg_setup_exp_bssap();
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009411 f_assignment_emerg_setup_voice();
Philipp Maier783681c2020-07-16 16:47:06 +02009412
9413 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009414 f_perform_clear();
Philipp Maier783681c2020-07-16 16:47:06 +02009415}
9416
9417/* Test if the EMERGENCY SETUP gets blocked by the BSC if EMERGENCY CALLS are
9418 * forbidden by the BSC config. */
9419private function f_TC_assignment_emerg_setup_deny(charstring id) runs on MSC_ConnHdlr {
9420 var PDU_BSSAP emerg_setup_data_ind_bssap;
9421 timer T := 3.0;
9422
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009423 f_assignment_emerg_setup();
Philipp Maier783681c2020-07-16 16:47:06 +02009424
9425 T.start;
9426 alt {
9427 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
9428 setverdict(pass);
9429 }
9430 [] RSL.receive {
9431 setverdict(fail, "unexpected RSL message!");
9432 }
9433 [] T.timeout {
9434 setverdict(fail, "timout waiting for RR CHANNEL RELEASE!");
9435 }
9436 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009437 BSSAP.receive(tr_BSSMAP_ClearRequest);
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01009438 f_perform_clear_no_rr_rel();
Philipp Maier783681c2020-07-16 16:47:06 +02009439}
9440
9441/* EMERGENCY CALL situation #1, allowed globally and by BTS */
9442testcase TC_assignment_emerg_setup_allow() runs on test_CT {
9443 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9444 var MSC_ConnHdlr vc_conn;
9445
9446 f_init(1, true);
9447 f_sleep(1.0);
9448
9449 f_vty_allow_emerg_msc(true);
9450 f_vty_allow_emerg_bts(true, 0);
9451 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
9452 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009453 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009454}
9455
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +01009456/* Test MO emergency call using MobileIdentity=IMEI (possible for emergency
9457 * calls from phones without SIM card).
9458 * 3GPP TS 24.008 section 10.5.1.4, OS#5849 */
9459testcase TC_assignment_emerg_setup_allow_imei() runs on test_CT {
9460 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9461 var MSC_ConnHdlr vc_conn;
9462
9463 /* Remove IMSI set by f_gen_test_hdlr_pars(), then IMEI will be used to place the call */
9464 pars.imsi := omit;
9465
9466 f_init(1, true);
9467 f_sleep(1.0);
9468
9469 f_vty_allow_emerg_msc(true);
9470 f_vty_allow_emerg_bts(true, 0);
9471 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
9472 vc_conn.done;
9473 f_shutdown_helper();
9474}
9475
Philipp Maier783681c2020-07-16 16:47:06 +02009476/* EMERGENCY CALL situation #2, forbidden globally but allowed by BTS */
9477testcase TC_assignment_emerg_setup_deny_msc() runs on test_CT {
9478 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9479 var MSC_ConnHdlr vc_conn;
9480
9481 f_init(1, true);
9482 f_sleep(1.0);
9483
9484 f_vty_allow_emerg_msc(false);
9485 f_vty_allow_emerg_bts(true, 0);
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009486 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx): */
9487 pars.ra := f_rnd_ra_emerg();
Philipp Maier783681c2020-07-16 16:47:06 +02009488 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9489 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009490 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009491}
9492
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009493/* EMERGENCY CALL situation #3, allowed globally but forbidden by BTS.
9494 * The RACH req (and hence CHAN RQD) indicate other than emergency call.
9495 * Hence BSC only learns about it being an emergency call later during call setup.
9496 * If interested in the ra="emergency call" + deny bts policy case,
9497 * see TC_chan_rqd_emerg_deny.
9498 */
Philipp Maier783681c2020-07-16 16:47:06 +02009499testcase TC_assignment_emerg_setup_deny_bts() runs on test_CT {
9500 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9501 var MSC_ConnHdlr vc_conn;
9502
9503 /* Note: This simulates a spec violation by the MS, correct MS
9504 * implementations would not try to establish an emergency call because
9505 * the system information tells in advance that emergency calls are
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009506 * not allowed */
Philipp Maier783681c2020-07-16 16:47:06 +02009507
9508 f_init(1, true);
9509 f_sleep(1.0);
9510
9511 f_vty_allow_emerg_msc(true);
9512 f_vty_allow_emerg_bts(false, 0);
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009513 /* Note: Here we implicitly leave default g_pars.ra which is different than "emergency call" */
Philipp Maier783681c2020-07-16 16:47:06 +02009514 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9515 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009516 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009517}
9518
Philipp Maier82812002020-08-13 18:48:27 +02009519/* Test what happens when an emergency call arrives while all TCH channels are
9520 * busy, the BSC is expected to terminate one call in favor of the incoming
9521 * emergency call */
9522testcase TC_emerg_premption() runs on test_CT {
9523 var ASP_RSL_Unitdata rsl_ud;
9524 var integer i;
9525 var integer chreq_total, chreq_nochan;
9526 var RSL_Message rx_rsl;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009527 var octetstring l3_payload := gen_l3_valid_payload();
Philipp Maier82812002020-08-13 18:48:27 +02009528
9529 f_init(1);
9530 f_sleep(1.0);
9531
9532 f_vty_allow_emerg_msc(true);
9533 f_vty_allow_emerg_bts(true, 0);
9534
9535 /* Fill up all channels on the BTS */
9536 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
9537 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
9538 for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS; i := i+1) {
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009539 f_chreq_act_ack('33'O, i);
Philipp Maier82812002020-08-13 18:48:27 +02009540 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009541 IPA_RSL[0][0].clear;
Philipp Maier82812002020-08-13 18:48:27 +02009542 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
9543 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
9544
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009545 /* Send EST IND for the first TCH, so we get to test the RR release cause */
9546 var RslChannelNr first_tch := valueof(t_RslChanNr_Bm(1));
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009547 f_ipa_tx(ts_RSL_EST_IND(first_tch, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009548
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009549 /* Accept BSSAP conn, so we get to test the Clear Request cause */
9550 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009551 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009552 var integer sccp_conn_id := rx_c_ind.connectionId;
9553 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
9554
Philipp Maier82812002020-08-13 18:48:27 +02009555 /* Send Channel request for emegergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009556 f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
Philipp Maier82812002020-08-13 18:48:27 +02009557
9558 /* Expect the BSC to release one (the first) TCH/F on the BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009559 f_expect_chan_rel(first_tch, expect_rr_chan_rel := true, expect_rll_rel_req := false,
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009560 expect_rr_cause := GSM48_RR_CAUSE_PREMPTIVE_REL);
Philipp Maier82812002020-08-13 18:48:27 +02009561
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009562 /* Also expect a BSSMAP Clear Request with PREEMPTION */
9563 var BSSAP_N_DATA_ind rx_clear_req;
9564 const myBSSMAP_Cause preemption := GSM0808_CAUSE_PREEMPTION;
9565 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_clear_req;
9566 log("XXX ", rx_clear_req);
9567 if (rx_clear_req.userData.pdu.bssmap.clearRequest.cause.causeValue != int2bit(enum2int(preemption), 7)) {
9568 setverdict(fail, "BSSMAP Clear Request: expected cause PREEMPTION");
9569 }
9570
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009571 /* Expect the BSC to send activate/assign the channel for the emergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009572 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009573 if (first_tch != rx_rsl.ies[0].body.chan_nr) {
9574 setverdict(fail, "different TCH lchan activated than expected");
9575 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009576 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(first_tch, 33));
9577 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Philipp Maier104f4c02020-09-11 18:12:18 +02009578
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009579 /* complete the BSSMAP Clear to satisfy the conn leak check */
9580 BSSAP.send(ts_BSSAP_DATA_req(sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(preemption))));
9581 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearComplete)) {
9582 BSSAP.send(ts_BSSAP_DISC_req(sccp_conn_id, 0));
9583 }
9584
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009585 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009586}
9587
9588/* Hopping parameters per a timeslot */
Vadim Yanitskiybc6654a2020-09-13 01:27:40 +07009589private type record length(0..64) of GsmArfcn ArfcnList;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009590private type record FHParamsTs {
9591 boolean enabled,
9592 uint6_t hsn,
9593 uint6_t maio,
9594 ArfcnList ma
9595};
9596
9597/* Hopping parameters per a transceiver */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009598private type record FHParamsTrx {
Philipp Maier798d8952021-10-19 14:43:19 +02009599 GsmBandArfcn arfcn,
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009600 FHParamsTs ts[8]
9601};
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009602
9603/* Randomly generate the hopping parameters for the given timeslot numbers */
9604private function f_TC_fh_params_gen(template integer tr_tn := (1, 3, 5))
9605runs on test_CT return FHParamsTrx {
9606 var FHParamsTrx fhp;
9607
Philipp Maier798d8952021-10-19 14:43:19 +02009608 /* Generate a random ARFCN in the range of 0 - 3. This ARFCN will
9609 * fall in the GSM900 band. */
9610 fhp.arfcn.arfcn := f_rnd_int(3);
9611 fhp.arfcn.pcs := false;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009612
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009613 for (var integer tn := 0; tn < 8; tn := tn + 1) {
9614 if (not match(tn, tr_tn)) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009615 fhp.ts[tn].enabled := false;
9616 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009617 continue;
9618 }
9619
9620 /* Random HSN / MAIO values: 0..63 */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009621 fhp.ts[tn].hsn := f_rnd_int(64);
9622 fhp.ts[tn].maio := f_rnd_int(64);
9623 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009624
9625 /* Random Mobile Allocation (hopping channels) */
9626 var integer ma_len := 2 + f_rnd_int(9); /* 2..10 channels */
9627 var integer step := 3 + f_rnd_int(4); /* 3..6 stepping */
9628 for (var integer i := 1; i <= ma_len; i := i + 1) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009629 fhp.ts[tn].ma := fhp.ts[tn].ma & { i * step };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009630 }
9631
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009632 fhp.ts[tn].enabled := true;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009633 }
9634
9635 log("f_TC_fh_params_gen(): ", fhp);
9636 return fhp;
9637}
9638
9639/* Make sure that the given Channel Description IE matches the hopping configuration */
9640private function f_TC_fh_params_match_chan_desc(in FHParamsTrx fhp, in ChannelDescription cd)
9641{
9642 var template (present) ChannelDescription tr_cd;
9643 var template (present) MaioHsn tr_maio_hsn;
9644 var uint3_t tn := cd.chan_nr.tn;
9645
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009646 if (fhp.ts[tn].enabled) {
9647 tr_maio_hsn := tr_HsnMaio(fhp.ts[tn].hsn, fhp.ts[tn].maio);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009648 tr_cd := tr_ChanDescH1(cd.chan_nr, tr_maio_hsn);
9649 } else {
Philipp Maier798d8952021-10-19 14:43:19 +02009650 tr_cd := tr_ChanDescH0(cd.chan_nr, fhp.arfcn.arfcn);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009651 }
9652
9653 if (not match(cd, tr_cd)) {
9654 setverdict(fail, "Channel Description IE does not match: ",
9655 cd, " vs expected ", tr_cd);
9656 }
9657}
9658
9659/* Make sure that the given Mobile Allocation IE matches the hopping configuration */
9660private function f_TC_fh_params_match_ma(in FHParamsTrx fhp, uint3_t tn,
9661 in MobileAllocationLV ma)
9662{
9663 var template MobileAllocationLV tr_ma := f_TC_fh_params_gen_tr_ma(fhp, tn, ma);
9664
9665 if (not match(ma, tr_ma)) {
9666 setverdict(fail, "Mobile Allocation IE does not match (tn := ",
9667 tn, "): ", ma, " vs expected: ", tr_ma);
9668 } else {
9669 setverdict(pass);
9670 }
9671}
9672
9673private function f_TC_fh_params_gen_tr_ma(in FHParamsTrx fhp, uint3_t tn,
9674 in MobileAllocationLV ma)
9675return template MobileAllocationLV {
9676 /* Mobile Allocation IE is expected to be empty if hopping is not enabled */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009677 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009678 return { len := 0, ma := ''B };
9679 }
9680
9681 var bitstring full_mask := f_pad_bit(''B, 1024, '0'B);
9682 var bitstring slot_mask := f_pad_bit(''B, 1024, '0'B);
9683 var bitstring ma_mask := ''B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009684
9685 /* Compose the full bit-mask (all channels, up to 1024 entries) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009686 for (var integer i := 0; i < lengthof(fhp.ts); i := i + 1) {
9687 for (var integer j := 0; j < lengthof(fhp.ts[i].ma); j := j + 1) {
9688 if (full_mask[fhp.ts[i].ma[j]] == '1'B)
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009689 { continue; }
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009690 full_mask[fhp.ts[i].ma[j]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009691 }
9692 }
9693
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009694 /* Take ARFCN of the TRX itself into account */
Philipp Maier798d8952021-10-19 14:43:19 +02009695 full_mask[fhp.arfcn.arfcn] := '1'B;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009696
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009697 /* Compose a bit-mask for the given timeslot number */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009698 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9699 slot_mask[fhp.ts[tn].ma[i]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009700 }
9701
9702 /* Finally, compose the Mobile Allocation bit-mask */
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009703 for (var integer i := 1; i < lengthof(full_mask); i := i + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009704 if (full_mask[i] != '1'B)
9705 { continue; }
9706
9707 /* FIXME: ma_mask := ma_mask & slot_mask[i]; // triggers a bug in TITAN */
9708 if (slot_mask[i] == '1'B) {
9709 ma_mask := ma_mask & '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009710 } else {
9711 ma_mask := ma_mask & '0'B;
9712 }
9713 }
9714
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009715 /* ARFCN 0 (if present) goes to the last position of the bit-mask */
9716 if (full_mask[0] == '1'B) {
9717 /* FIXME: ma_mask := ma_mask & slot_mask[0]; // triggers a bug in TITAN */
9718 if (slot_mask[0] == '1'B) {
9719 ma_mask := ma_mask & '1'B;
9720 } else {
9721 ma_mask := ma_mask & '0'B;
9722 }
9723 }
9724
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009725 /* Ensure that ma_mask is octet-aligned */
Vadim Yanitskiy2aa02522020-09-06 14:05:23 +07009726 var integer ma_mask_len := (lengthof(ma_mask) + 8 - 1) / 8;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009727 ma_mask := f_pad_bit(ma_mask, ma_mask_len * 8, '0'B);
9728
9729 return { len := ma_mask_len, ma := ma_mask };
9730}
9731
Philipp Maier798d8952021-10-19 14:43:19 +02009732/* Configure the appropriate band for a given arfcn, exc */
9733private function f_TC_set_band_by_arfcn(integer bts_nr, GsmBandArfcn arfcn) runs on test_CT
9734{
9735 var charstring band;
9736 var GsmBandArfcn arfcn_ := valueof(ts_GsmBandArfcn(arfcn.arfcn, arfcn.pcs, false));
9737
9738 select (arfcn_) {
9739 case (tr_GsmBandArfcn((259..293), false, ?)) { band := "GSM450"; }
9740 case (tr_GsmBandArfcn((306..340), false, ?)) { band := "GSM480"; }
9741 case (tr_GsmBandArfcn((438..511), false, ?)) { band := "GSM750"; }
9742 case (tr_GsmBandArfcn((128..251), false, ?)) { band := "GSM850"; }
9743 case (tr_GsmBandArfcn((0..124), false, ?)) { band := "GSM900"; }
9744 case (tr_GsmBandArfcn((955..1023), false, ?)) { band := "GSM900"; }
9745 case (tr_GsmBandArfcn((512..885), false, ?)) { band := "DCS1800"; }
9746 case (tr_GsmBandArfcn((512..810), true, ?)) { band := "PCS1900"; }
9747 case else { return; }
9748 }
9749
9750 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9751 f_vty_transceive(BSCVTY, "band " & band);
9752 f_vty_transceive(BSCVTY, "end");
9753}
9754
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009755/* Configure the hopping parameters in accordance with the given record */
9756private function f_TC_fh_params_set(in FHParamsTrx fhp,
9757 uint8_t bts_nr := 0,
9758 uint8_t trx_nr := 0)
9759runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009760
9761 f_TC_set_band_by_arfcn(bts_nr, fhp.arfcn);
9762
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009763 /* Enter the configuration node for the given BTS/TRX numbers */
9764 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9765
Philipp Maier798d8952021-10-19 14:43:19 +02009766 f_vty_transceive(BSCVTY, "arfcn " & int2str(fhp.arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009767
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009768 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009769 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9770
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009771 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009772 f_vty_transceive(BSCVTY, "hopping enabled 0");
9773 f_vty_transceive(BSCVTY, "exit"); /* go back */
9774 continue;
9775 }
9776
9777 /* Configure HSN / MAIO values */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009778 f_vty_transceive(BSCVTY, "hopping sequence-number " & int2str(fhp.ts[tn].hsn));
9779 f_vty_transceive(BSCVTY, "hopping maio " & int2str(fhp.ts[tn].maio));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009780
9781 /* Configure the Mobile Allocation (hopping channels) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009782 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9783 f_vty_transceive(BSCVTY, "hopping arfcn add " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009784 }
9785
9786 f_vty_transceive(BSCVTY, "hopping enabled 1");
9787 f_vty_transceive(BSCVTY, "exit"); /* go back */
9788 }
9789
9790 f_vty_transceive(BSCVTY, "end");
9791}
9792
9793/* Disable frequency hopping on all timeslots */
9794private function f_TC_fh_params_unset(in FHParamsTrx fhp,
9795 uint8_t bts_nr := 0,
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009796 uint8_t trx_nr := 0,
Philipp Maier798d8952021-10-19 14:43:19 +02009797 GsmBandArfcn arfcn := {pcs := false, arfcn := 871})
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009798runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009799
9800 f_TC_set_band_by_arfcn(bts_nr, arfcn);
9801
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009802 /* Enter the configuration node for the given BTS/TRX numbers */
9803 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9804
Philipp Maier798d8952021-10-19 14:43:19 +02009805 f_vty_transceive(BSCVTY, "arfcn " & int2str(arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009806
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009807 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009808 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9809
9810 /* Delete all ARFCNs from the Mobile Allocation (if any) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009811 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9812 f_vty_transceive(BSCVTY, "hopping arfcn del " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009813 }
9814
9815 f_vty_transceive(BSCVTY, "hopping enabled 0");
9816 f_vty_transceive(BSCVTY, "exit"); /* go back */
9817 }
9818
9819 f_vty_transceive(BSCVTY, "end");
9820 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9821}
9822
9823/* Verify presence and correctness of the hopping parameters (HSN, MAIO)
9824 * in the Channel Identification IE of the RSL CHANnel ACTIVation message. */
9825testcase TC_fh_params_chan_activ() runs on test_CT {
9826 var FHParamsTrx fhp := f_TC_fh_params_gen();
9827 var RSL_Message rsl_msg;
9828 var RSL_IE_Body ie;
9829
9830 f_init_vty();
9831
9832 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9833 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9834
9835 f_init(1);
9836
9837 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9838 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009839 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9840 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009841
9842 /* Make sure that Channel Identification IE is present */
9843 if (not f_rsl_find_ie(rsl_msg, RSL_IE_CHAN_IDENT, ie)) {
9844 setverdict(fail, "RSL Channel Identification IE is absent");
9845 continue;
9846 }
9847
9848 /* Make sure that hopping parameters (HSN/MAIO) match */
9849 f_TC_fh_params_match_chan_desc(fhp, ie.chan_ident.ch_desc.v);
9850
9851 /* "Mobile Allocation shall be included but empty" - let's check this */
9852 if (ie.chan_ident.ma.v.len != 0) {
9853 setverdict(fail, "Mobile Allocation IE is not empty: ",
9854 ie.chan_ident.ma, ", despite it shall be");
9855 continue;
9856 }
9857 }
9858
9859 /* Disable frequency hopping */
9860 f_TC_fh_params_unset(fhp);
9861
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009862 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009863}
9864
9865/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Immediate Assignment */
9866testcase TC_fh_params_imm_ass() runs on test_CT {
9867 var FHParamsTrx fhp := f_TC_fh_params_gen();
9868 var RSL_Message rsl_msg;
9869 var RSL_IE_Body ie;
9870
9871 f_init_vty();
9872
9873 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9874 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9875
9876 f_init(1);
9877
9878 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9879 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009880 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9881 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009882
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009883 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9884 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009885
9886 /* Make sure that Full Immediate Assign Info IE is present */
9887 if (not f_rsl_find_ie(rsl_msg, RSL_IE_FULL_IMM_ASS_INFO, ie)) {
9888 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
9889 continue;
9890 }
9891
9892 /* Decode the actual Immediate Assignment message */
9893 var GsmRrMessage rr_msg := dec_GsmRrMessage(ie.full_imm_ass_info.payload);
9894 if (not match(rr_msg.header, t_RrHeader(IMMEDIATE_ASSIGNMENT, ?))) {
9895 setverdict(fail, "Failed to match Immediate Assignment: ", rr_msg);
9896 continue;
9897 }
9898
9899 /* Make sure that hopping parameters (HSN/MAIO) match */
9900 f_TC_fh_params_match_chan_desc(fhp, rr_msg.payload.imm_ass.chan_desc);
9901
9902 /* Make sure that the Mobile Allocation IE matches */
9903 f_TC_fh_params_match_ma(fhp, rr_msg.payload.imm_ass.chan_desc.chan_nr.tn,
9904 rr_msg.payload.imm_ass.mobile_allocation);
9905 }
9906
9907 /* Disable frequency hopping */
9908 f_TC_fh_params_unset(fhp);
Philipp Maier82812002020-08-13 18:48:27 +02009909
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009910 f_shutdown_helper();
Philipp Maier82812002020-08-13 18:48:27 +02009911}
9912
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009913/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Assignment Command */
9914testcase TC_fh_params_assignment_cmd() runs on test_CT {
9915 var FHParamsTrx fhp := f_TC_fh_params_gen();
9916 var RSL_Message rsl_msg;
9917 var RSL_IE_Body ie;
9918
9919 f_init_vty();
9920
9921 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9922 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9923
9924 f_init(1);
9925
9926 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02009927 vc_MGCP[0].stop;
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009928
9929 var template PDU_BSSAP ass_cmd := f_gen_ass_req();
9930 ass_cmd.pdu.bssmap.assignmentRequest.codecList := ts_BSSMAP_IE_CodecList({ts_CodecFR});
9931
9932 /* CS domain (TCH): 4 (TCH/F) + 2 (TCH/H) channels available
9933 * NOTE: only 3 SDCCH/4 channels are available on CCCH+SDCCH4+CBCH */
9934 for (var integer i := 0; i < 3; i := i + 1) {
9935 /* Establish a dedicated channel, so we can trigger (late) TCH assignment */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009936 var DchanTuple dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009937
9938 /* Send a BSSMAP Assignment Command, expect CHANnel ACTIVation */
9939 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009940 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009941
9942 /* ACKnowledge CHANnel ACTIVation, expect RSL DATA REQuest */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009943 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9944 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009945
9946 /* Make sure that L3 Information IE is present */
9947 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
9948 setverdict(fail, "RSL L3 Information IE is absent");
9949 continue;
9950 }
9951
9952 /* Decode the L3 message and make sure it is (RR) Assignment Command */
9953 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
9954 if (not match(l3_msg.header, t_RrL3Header(ASSIGNMENT_COMMAND))) {
9955 setverdict(fail, "Failed to match Assignment Command: ", l3_msg);
9956 continue;
9957 }
9958
9959 /* Make sure that hopping parameters (HSN/MAIO) match */
9960 var ChannelDescription chan_desc := l3_msg.payload.ass_cmd.chan_desc;
9961 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9962
9963 /* Make sure that Cell Channel Description IE is present if FH is enabled */
9964 if (chan_desc.h and not ispresent(l3_msg.payload.ass_cmd.cell_chan_desc)) {
Vadim Yanitskiy38d069d2020-09-02 17:18:57 +07009965 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009966 continue;
9967 }
9968
9969 /* Make sure that the Mobile Allocation IE matches (if present) */
9970 var boolean ma_present := ispresent(l3_msg.payload.ass_cmd.mobile_allocation);
9971 if (chan_desc.h and ma_present) {
9972 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
9973 l3_msg.payload.ass_cmd.mobile_allocation.v);
9974 } else if (chan_desc.h and not ma_present) {
9975 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
9976 continue;
9977 } else if (not chan_desc.h and ma_present) {
9978 setverdict(fail, "FH disabled, but Mobile Allocation IE is present");
9979 continue;
9980 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009981
9982 f_perform_clear_test_ct(dt);
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009983 }
9984
9985 /* Give the IUT some time to release all channels */
9986 f_sleep(3.0);
9987
9988 /* Disable frequency hopping */
9989 f_TC_fh_params_unset(fhp);
9990
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009991 f_shutdown_helper();
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009992}
9993
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009994/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Handover Command */
9995private function f_TC_fh_params_handover_cmd(in FHParamsTrx fhp)
9996runs on test_CT {
9997 var RSL_Message rsl_msg;
9998 var RSL_IE_Body ie;
9999 var DchanTuple dt;
10000
10001 /* Establish a dedicated channel, so we can trigger handover */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010010002 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiyc18ff472021-11-18 20:15:37 +030010003 f_sleep(0.5);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010004
10005 /* Trigger handover from BTS0 to BTS1 */
10006 f_bts_0_cfg(BSCVTY, { "neighbor bts 1" });
10007 f_vty_handover(BSCVTY, 0, 0, dt.rsl_chan_nr, 1);
10008
10009 /* Expect RSL CHANnel ACTIVation on BTS1/TRX0/TS1 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010010 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx := {1, 0});
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010011
10012 /* ACKnowledge channel activation and expect (RR) Handover Command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010013 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33), idx := {1, 0});
10014 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010015
10016 /* Make sure that L3 Information IE is present */
10017 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
10018 setverdict(fail, "RSL L3 Information IE is absent");
10019 return;
10020 }
10021
10022 /* Decode the L3 message and make sure it is (RR) Handover Command */
10023 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
10024 if (not match(l3_msg.header, t_RrL3Header(HANDOVER_COMMAND))) {
10025 setverdict(fail, "Failed to match Handover Command: ", l3_msg);
10026 return;
10027 }
10028
10029 /* Make sure that we've got SDCCH/8 on TS1 (expected to be hopping) */
10030 var ChannelDescription chan_desc := l3_msg.payload.ho_cmd.chan_desc;
10031 if (not match(chan_desc.chan_nr, t_RslChanNr_SDCCH8(1, ?))) {
10032 setverdict(fail, "Unexpected channel number: ", chan_desc.chan_nr);
10033 return;
10034 }
10035
10036 /* Make sure that hopping parameters (HSN/MAIO) match */
10037 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
10038
10039 /* Make sure that Cell Channel Description IE is present */
10040 if (not ispresent(l3_msg.payload.ho_cmd.cell_chan_desc)) {
10041 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
10042 return;
10043 }
10044
10045 /* Make sure that the Mobile Allocation (after time) IE is present and matches */
10046 var boolean ma_present := ispresent(l3_msg.payload.ho_cmd.mobile_allocation);
10047 if (ma_present) {
10048 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
10049 l3_msg.payload.ho_cmd.mobile_allocation.v);
10050 } else {
10051 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
10052 return;
10053 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010054
10055 f_perform_clear_test_ct(dt);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010056}
10057testcase TC_fh_params_handover_cmd() runs on test_CT {
10058 var FHParamsTrx fhp := f_TC_fh_params_gen();
10059
10060 f_init_vty();
10061
10062 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8 on BTS1/TRX0 */
10063 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
10064
10065 f_vty_transceive(BSCVTY, "timeslot 0");
10066 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
10067 f_vty_transceive(BSCVTY, "exit"); /* go back */
10068
10069 f_vty_transceive(BSCVTY, "timeslot 1");
10070 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8");
10071 f_vty_transceive(BSCVTY, "end"); /* we're done */
10072
10073 f_TC_fh_params_set(fhp, 1); /* Enable frequency hopping on BTS1 */
10074 f_vty_transceive(BSCVTY, "drop bts connection 1 oml");
10075
10076 f_init(2);
10077
10078 f_TC_fh_params_handover_cmd(fhp);
10079
10080 /* Disable frequency hopping on BTS1 */
10081 f_TC_fh_params_unset(fhp, 1);
10082
10083 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
10084 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
10085
10086 f_vty_transceive(BSCVTY, "timeslot 0");
10087 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
10088 f_vty_transceive(BSCVTY, "exit"); /* go back */
10089
10090 f_vty_transceive(BSCVTY, "timeslot 1");
10091 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
10092 f_vty_transceive(BSCVTY, "end"); /* we're done */
10093
10094 f_shutdown_helper();
10095}
10096
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010097/* Verify the hopping parameters in System Information Type 4 */
10098testcase TC_fh_params_si4_cbch() runs on test_CT {
10099 var FHParamsTrx fhp := f_TC_fh_params_gen(tr_tn := 1);
10100 var ASP_RSL_Unitdata rx_rsl_ud;
10101 timer T := 5.0;
10102
10103 f_init_vty();
10104
10105 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8+CBCH */
10106 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
10107
10108 f_vty_transceive(BSCVTY, "timeslot 0");
10109 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
10110 f_vty_transceive(BSCVTY, "exit"); /* go back */
10111
10112 f_vty_transceive(BSCVTY, "timeslot 1");
10113 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8+cbch");
10114 f_vty_transceive(BSCVTY, "end"); /* we're done */
10115
10116 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
10117 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
10118
10119 f_init(1);
10120
10121 T.start;
10122 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010123 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO(RSL_SYSTEM_INFO_4))) -> value rx_rsl_ud {
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010124 var RSL_IE_Body ie := rx_rsl_ud.rsl.ies[2].body; /* FULL BCCH Information IE */
10125 var SystemInformation si := dec_SystemInformation(ie.other.payload);
10126
10127 /* Make sure that what we decoded is System Information Type 4 */
10128 if (si.header.message_type != SYSTEM_INFORMATION_TYPE_4) {
10129 setverdict(fail, "RSL FULL BCCH Information IE contains: ", si);
10130 repeat;
10131 }
10132
10133 /* Make sure that CBCH Channel Description IE is present */
10134 if (not ispresent(si.payload.si4.cbch_chan_desc)) {
10135 setverdict(fail, "CBCH Channel Description IE is absent");
10136 break;
10137 }
10138
10139 /* Finally, check the hopping parameters (HSN, MAIO) */
10140 var ChannelDescription chan_desc := si.payload.si4.cbch_chan_desc.v;
10141 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
10142
10143 /* 3GPP TS 44.018, section 9.1.36.2 "CBCH Mobile Allocation":
10144 * The CBCH Mobile Allocation IE *shall* be present if FH is enabled. */
10145 if (chan_desc.h and not ispresent(si.payload.si4.cbch_mobile_alloc)) {
10146 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
10147 break;
10148 } else if (chan_desc.h and ispresent(si.payload.si4.cbch_mobile_alloc)) {
10149 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
10150 si.payload.si4.cbch_mobile_alloc.v);
10151 }
10152 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010153 [] IPA_RSL[0][0].receive { repeat; }
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010154 [] T.timeout {
10155 setverdict(fail, "Timeout waiting for RSL BCCH INFOrmation (SI4)");
10156 }
10157 }
10158
10159 /* Disable frequency hopping */
10160 f_TC_fh_params_unset(fhp);
10161
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +070010162 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010163 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
10164
10165 f_vty_transceive(BSCVTY, "timeslot 0");
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +070010166 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010167 f_vty_transceive(BSCVTY, "exit"); /* go back */
10168
10169 f_vty_transceive(BSCVTY, "timeslot 1");
10170 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
10171 f_vty_transceive(BSCVTY, "end"); /* we're done */
10172
Vadim Yanitskiy21726312020-09-04 01:45:36 +070010173 f_shutdown_helper();
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010174}
10175
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010176template (value) PDU_BSSAP_LE ts_BSSMAP_LE_BSSLAP(template (value) BSSLAP_PDU bsslap)
10177 := ts_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, data := enc_BSSLAP_PDU(valueof(bsslap)));
10178
10179private function f_match_bsslap(PDU_BSSAP_LE got_bsslap_msg,
10180 template (present) BSSLAP_PDU expect_bsslap)
10181{
10182 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(got_bsslap_msg.pdu.bssmap.co_info.bsslap_apdu.data);
10183 if (not match(bsslap, expect_bsslap)) {
10184 log("EXPECTING BSSLAP: ", expect_bsslap);
10185 log("GOT BSSLAP: ", bsslap);
10186 setverdict(fail, "BSSLAP is not as expected");
10187 mtc.stop;
10188 }
10189 setverdict(pass);
10190}
10191
10192/* GAD: this is an Ellipsoid point with uncertainty circle, encoded as in 3GPP TS 23.032 §7.3.2. */
10193const octetstring gad_ell_point_unc_circle := '10b0646d0d5f6627'O;
10194
10195private function f_expect_bsslap(template (present) BSSLAP_PDU expect_rx_bsslap) runs on MSC_ConnHdlr {
10196 var PDU_BSSAP_LE rx_bsslap;
10197 BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap);
10198 f_match_bsslap(rx_bsslap, expect_rx_bsslap);
10199}
10200
10201/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10202 * Request on Lb interface. Either with or without the SMLC doing a BSSLAP TA Request. */
10203private function f_lcs_loc_req_for_active_ms(boolean do_ta_request := false) runs on MSC_ConnHdlr {
10204 f_sleep(1.0);
10205
10206 f_establish_fully(omit, omit);
10207 f_bssap_le_register_imsi(g_pars.imsi, omit);
10208
10209 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10210 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10211
10212 var PDU_BSSAP_LE plr;
10213 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10214
10215 if (not do_ta_request) {
10216 /* verify TA Layer 3 in APDU. First the APDU type (BSSLAP), then the BSSLAP data contents. */
10217 var template BSSMAP_LE_IE_APDU expect_apdu := tr_BSSMAP_LE_APDU(BSSMAP_LE_PROT_BSSLAP, ?);
10218 if (not match(plr.pdu.bssmap.perf_loc_req.bsslap_apdu, expect_apdu)) {
10219 log("EXPECTING BSSMAP-LE APDU IE ", expect_apdu);
10220 log("GOT BSSMAP-LE APDU IE ", plr.pdu.bssmap.perf_loc_req.bsslap_apdu);
10221 setverdict(fail, "BSSMAP-LE APDU IE is not as expected");
10222 mtc.stop;
10223 }
10224 var template BSSLAP_PDU expect_ta_layer3 := tr_BSSLAP_TA_Layer3(tr_BSSLAP_IE_TA(0));
10225 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(plr.pdu.bssmap.perf_loc_req.bsslap_apdu.data);
10226 if (not match(bsslap, expect_ta_layer3)) {
10227 log("EXPECTING BSSLAP TA Layer 3: ", expect_ta_layer3);
10228 log("GOT BSSLAP: ", bsslap);
10229 setverdict(fail, "BSSLAP is not as expected");
10230 mtc.stop;
10231 }
10232 /* OsmoBSC directly sent the TA as BSSLAP APDU in the BSSMAP-LE Perform Location Request to the SMLC. The SMLC
10233 * has no need to request the TA from the BSC and directly responds. */
10234 } else {
10235 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10236 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10237 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10238 }
10239
10240 /* SMLC got the TA from the BSC, now responds with geo information data. */
10241 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10242 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10243 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10244
10245 /* The LCS was using an active A-interface conn. It should still remain active after this. */
10246 f_mo_l3_transceive();
10247
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010248 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010249
10250 f_sleep(2.0);
10251 setverdict(pass);
10252}
10253
10254/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10255 * Request on Lb interface. Without the SMLC doing a BSSLAP TA Request. */
10256private function f_tc_lcs_loc_req_for_active_ms(charstring id) runs on MSC_ConnHdlr {
10257 f_lcs_loc_req_for_active_ms(false);
10258}
10259testcase TC_lcs_loc_req_for_active_ms() runs on test_CT {
10260 var MSC_ConnHdlr vc_conn;
10261 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10262
10263 f_init(1, true);
10264 f_sleep(1.0);
10265 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms), pars);
10266 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010267 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010268}
10269
10270/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10271 * Request on Lb interface. With the SMLC doing a BSSLAP TA Request. */
10272private function f_tc_lcs_loc_req_for_active_ms_ta_req(charstring id) runs on MSC_ConnHdlr {
10273 f_lcs_loc_req_for_active_ms(true);
10274}
10275testcase TC_lcs_loc_req_for_active_ms_ta_req() runs on test_CT {
10276 var MSC_ConnHdlr vc_conn;
10277 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10278
10279 f_init(1, true);
10280 f_sleep(1.0);
10281 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_ta_req), pars);
10282 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010283 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010284}
10285
10286/* Clear the A-interface conn only, without doing anything on Abis. Useful for LCS, for cases where there is only an A
10287 * conn without an active lchan. */
10288private function f_clear_A_conn() runs on MSC_ConnHdlr
10289{
10290 var BssmapCause cause := 0;
10291 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
10292 BSSAP.receive(tr_BSSMAP_ClearComplete);
10293 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
10294
10295 timer no_more_bssap := 5.0;
10296 no_more_bssap.start;
10297 alt {
10298 [] no_more_bssap.timeout { break; }
10299 [] BSSAP.receive(tr_BSSAP_BSSMAP) {
10300 setverdict(fail, "Expected no more BSSAP after Clear Complete");
10301 mtc.stop;
10302 }
10303 }
10304 setverdict(pass);
10305}
10306
10307/* Verify that the A-interface connection is still working, and then clear it, without doing anything on Abis. Useful
10308 * for LCS, for cases where there is only an A conn without an active lchan. */
10309private function f_verify_active_A_conn_and_clear() runs on MSC_ConnHdlr
10310{
10311 f_logp(BSCVTY, "f_verify_active_A_conn_and_clear: test A link, then clear");
10312
10313 /* When an lchan is active, we can send some L3 data from the BTS side and verify that it shows up on the other
10314 * side towards the MSC. When there is no lchan, this is not possible. To probe whether the A-interface
10315 * connection is still up, we need something that echos back on the A-interface. Another LCS request! */
10316 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10317 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10318 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10319
10320 /* Right, the Perform Location Request showed up on Lb, now we can clear the A conn. */
10321 f_clear_A_conn();
10322 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10323 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10324}
10325
10326/* With *no* active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10327 * Request on Lb interface. BSC will Page for the subscriber as soon as we (virtual SMLC) request the TA via BSSLAP.
10328 */
10329private function f_tc_lcs_loc_req_for_idle_ms(charstring id) runs on MSC_ConnHdlr {
10330 f_sleep(1.0);
10331
10332 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10333 f_bssap_le_register_imsi(g_pars.imsi, omit);
10334
10335 /* Register to receive the Paging Command */
10336 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10337 g_chan_nr := new_chan_nr;
10338 f_rslem_register(0, g_chan_nr);
10339
10340 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10341 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10342 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10343 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10344
10345 var PDU_BSSAP_LE plr;
10346 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10347
10348 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10349 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10350
10351 /* OsmoBSC needs to Page */
10352 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi)));
10353 f_logp(BSCVTY, "got Paging Command");
10354
10355 /* MS requests channel. Since the Paging was for LCS, the Paging Response does not trigger a Complete Layer 3 to
10356 * the MSC, and releases the lchan directly. */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +020010357 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_IMSI_LV(g_pars.imsi)), do_clear := false, expect_bssmap_l3 := false);
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010358 f_expect_lchan_rel(RSL, RSL_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010359
10360 /* From the Paging Response, the TA is now known to the BSC, and it responds to the SMLC. */
10361
10362 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10363
10364 /* SMLC got the TA from the BSC, now responds with geo information data. */
10365 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10366 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10367
10368 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10369
10370 /* The lchan is gone, the A-interface conn was created for the LCS only.
10371 * Still it is clearly the MSC's job to decide whether to tear down the conn or not. */
10372 f_verify_active_A_conn_and_clear();
10373
10374 f_sleep(2.0);
10375 setverdict(pass);
10376}
10377testcase TC_lcs_loc_req_for_idle_ms() runs on test_CT {
10378 var MSC_ConnHdlr vc_conn;
10379 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10380
10381 f_init(1, true);
10382 f_sleep(1.0);
10383
10384 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10385 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10386
10387 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms), pars);
10388 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010389 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010390}
10391
10392/* With no active lchan, start BSSMAP Perform Location Request on A interface, but omit IMSI; expect failure response.
10393 */
10394private function f_tc_lcs_loc_req_no_subscriber(charstring id) runs on MSC_ConnHdlr {
10395 f_sleep(1.0);
10396
10397 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10398 f_bssap_le_register_imsi(g_pars.imsi, omit);
10399
10400 /* provoke an abort by omitting both IMSI and IMEI */
10401 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10402 valueof(ts_BSSMAP_Perform_Location_Request(omit,
10403 ts_CellId_CGI('262'H, '42'H, 23, 42)))));
10404 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10405
10406 /* BSC tells MSC about failure */
10407 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10408 locationEstimate := omit, positioningData := omit,
10409 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_DATA_MISSING_IN_REQ)));
10410
10411 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10412 f_verify_active_A_conn_and_clear();
10413
10414 f_sleep(2.0);
10415 setverdict(pass);
10416}
10417testcase TC_lcs_loc_req_no_subscriber() runs on test_CT {
10418 var MSC_ConnHdlr vc_conn;
10419 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10420
10421 f_init(1, true);
10422 f_sleep(1.0);
10423
10424 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10425 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10426
10427 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_no_subscriber), pars);
10428 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010429 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010430}
10431
10432/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10433 * BSSMAP-LE Perform Location Response (before or after sending a BSSLAP TA Request) */
10434private function f_lcs_loc_req_for_active_ms_le_timeout(boolean do_ta) runs on MSC_ConnHdlr {
10435 f_sleep(1.0);
10436
10437 f_establish_fully(omit, omit);
10438 f_bssap_le_register_imsi(g_pars.imsi, omit);
10439
10440 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10441 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10442
10443 var PDU_BSSAP_LE plr;
10444 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10445
10446 if (do_ta) {
10447 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10448 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10449 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10450 }
10451
10452 /* SMLC fails to respond, BSC runs into timeout */
10453 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_SYSTEM_FAILURE));
10454 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10455
10456 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10457 locationEstimate := omit, positioningData := omit,
10458 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_SYSTEM_FAILURE)));
10459
10460 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10461 f_verify_active_A_conn_and_clear();
10462
10463 f_sleep(2.0);
10464 setverdict(pass);
10465}
10466
10467/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10468 * BSSMAP-LE Perform Location Response, without sending a BSSLAP TA Request. */
10469private function f_tc_lcs_loc_req_for_active_ms_le_timeout(charstring id) runs on MSC_ConnHdlr {
10470 f_lcs_loc_req_for_active_ms_le_timeout(false);
10471}
10472
10473testcase TC_lcs_loc_req_for_active_ms_le_timeout() runs on test_CT {
10474 var MSC_ConnHdlr vc_conn;
10475 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10476
10477 f_init(1, true);
10478 f_sleep(1.0);
10479 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout), pars);
10480 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010481 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010482}
10483
10484/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10485 * BSSMAP-LE Perform Location Response, after sending a BSSLAP TA Request. */
10486private function f_tc_lcs_loc_req_for_active_ms_le_timeout2(charstring id) runs on MSC_ConnHdlr {
10487 f_lcs_loc_req_for_active_ms_le_timeout(true);
10488}
10489
10490testcase TC_lcs_loc_req_for_active_ms_le_timeout2() runs on test_CT {
10491 var MSC_ConnHdlr vc_conn;
10492 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10493
10494 f_init(1, true);
10495 f_sleep(1.0);
10496 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout2), pars);
10497 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010498 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010499}
10500
10501/* With *no* active lchan, start a Perform Location Request, expecting that the MS will be Paged. */
10502private function f_tc_lcs_loc_req_for_idle_ms_no_pag_resp(charstring id) runs on MSC_ConnHdlr {
10503 f_sleep(1.0);
10504
10505 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10506 f_bssap_le_register_imsi(g_pars.imsi, omit);
10507
10508 /* Register to receive the Paging Command */
10509 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10510 g_chan_nr := new_chan_nr;
10511 f_rslem_register(0, g_chan_nr);
10512
10513 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10514 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10515 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10516 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10517
10518 var PDU_BSSAP_LE plr;
10519 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10520
10521 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10522 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10523
10524 /* OsmoBSC needs to Page */
10525 var PDU_BSSAP_LE rx_bsslap;
10526 alt {
10527 [] RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi))) {
10528 f_logp(BSCVTY, "got Paging Command");
10529 repeat;
10530 }
10531 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10532 /* MS does not respond to Paging, TA Req runs into timeout. */
10533 f_match_bsslap(rx_bsslap, tr_BSSLAP_Abort(?));
10534 }
10535 }
10536
10537 /* SMLC responds with failure */
10538 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(omit, BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10539 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10540
10541 /* BSC tells MSC about failure */
10542 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10543 locationEstimate := omit, positioningData := omit,
10544 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_REQUEST_ABORTED)));
10545
10546 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10547 f_verify_active_A_conn_and_clear();
10548
10549 f_sleep(2.0);
10550 setverdict(pass);
10551}
10552testcase TC_lcs_loc_req_for_idle_ms_no_pag_resp() runs on test_CT {
10553 var MSC_ConnHdlr vc_conn;
10554 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10555
10556 f_init(1, true);
10557 f_sleep(1.0);
10558
10559 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10560 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10561
10562 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms_no_pag_resp), pars);
10563 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010564 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010565}
10566
10567/* During an ongoing Location Request, the MS sends a CM Service Request. Expect the same A-conn to be re-used / taken
10568 * over. */
10569private function f_tc_cm_service_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10570 f_sleep(1.0);
10571
10572 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10573 f_bssap_le_register_imsi(g_pars.imsi, omit);
10574
10575 /* Register to receive the Paging Command */
10576 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10577 g_chan_nr := new_chan_nr;
10578 f_rslem_register(0, g_chan_nr);
10579
10580 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10581 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10582 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10583 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10584
10585 var PDU_BSSAP_LE plr;
10586 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10587
10588 /* As the A-interface conn was established for LCS, the MS coincidentally decides to issue a CM Service Request
10589 * and establish Layer 3. It should use the existing A-interface conn. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010590 f_perform_compl_l3(RSL, RSL_PROC, valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV(g_pars.imsi)))),
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010591 do_clear := false, expect_bssmap_l3 := true);
10592
10593 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10594 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10595
10596 /* OsmoBSC already has an lchan, no need to Page, just returns the TA */
10597 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10598
10599 /* SMLC got the TA from the BSC, now responds with geo information data. */
10600 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10601 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10602 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10603
10604 /* The lchan should still exist, it was from a CM Service Request. */
10605 f_mo_l3_transceive();
10606
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010607 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010608
10609 f_sleep(2.0);
10610 setverdict(pass);
10611}
10612testcase TC_cm_service_during_lcs_loc_req() runs on test_CT {
10613 var MSC_ConnHdlr vc_conn;
10614 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10615
10616 f_init(1, true);
10617 f_sleep(1.0);
10618
10619 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10620 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10621
10622 vc_conn := f_start_handler(refers(f_tc_cm_service_during_lcs_loc_req), pars);
10623 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010624 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010625}
10626
10627/* During an ongoing Perform Location Request, do a Handover, an expect a BSSLAP Reset message from the BSC to indicate
10628 * the new lchan after handover. */
10629private function f_tc_ho_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10630 f_sleep(1.0);
10631
10632 f_establish_fully(omit, omit);
10633 f_bssap_le_register_imsi(g_pars.imsi, omit);
10634
10635 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10636 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10637
10638 var PDU_BSSAP_LE plr;
10639 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10640
10641 /* SMLC ponders the Location Request, in the meantime the BSC decides to handover */
10642 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
10643
10644 var HandoverState hs := {
10645 rr_ho_cmpl_seen := false,
10646 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +020010647 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010648 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010649 };
10650 /* issue hand-over command on VTY */
10651 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
10652 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
10653 f_rslem_suspend(RSL1_PROC);
10654
10655 /* From the MGW perspective, a handover is is characterized by
10656 * performing one MDCX operation with the MGW. So we expect to see
10657 * one more MDCX during handover. */
10658 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
10659
10660 alt {
10661 [] as_handover(hs);
10662 }
10663
10664 var PDU_BSSAP_LE rx_bsslap;
10665
10666 interleave {
10667 /* Expect the BSC to inform the MSC about the handover */
10668 [] BSSAP.receive(tr_BSSMAP_HandoverPerformed);
10669
10670 /* Expect the BSC to inform the SMLC about the handover */
10671 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10672 f_match_bsslap(rx_bsslap, tr_BSSLAP_Reset(BSSLAP_CAUSE_INTRA_BSS_HO));
10673 }
10674 }
10675
10676 /* SMLC now responds with geo information data. */
10677 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10678 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10679 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10680
10681 /* lchan still active */
10682 f_mo_l3_transceive(RSL1);
10683
10684 /* MSC decides it is done now. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010685 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010686
10687 f_sleep(2.0);
10688 setverdict(pass);
10689}
10690testcase TC_ho_during_lcs_loc_req() runs on test_CT {
10691 var MSC_ConnHdlr vc_conn;
10692 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10693
10694 f_init(2, true);
10695 f_sleep(1.0);
10696 vc_conn := f_start_handler(refers(f_tc_ho_during_lcs_loc_req), pars);
10697 vc_conn.done;
Oliver Smith39f53072022-10-27 14:44:04 +020010698 f_shutdown_helper(ho := true);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010699}
10700
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010701private function f_tc_emerg_call_and_lcs_loc_req(charstring id) runs on MSC_ConnHdlr
10702{
10703 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
10704 * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
10705 * another lchan. */
Pau Espin Pedrol1809bce2023-01-03 16:54:41 +010010706 g_pars.ra := f_rnd_ra_emerg();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010707 f_assignment_emerg_setup();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +010010708 f_assignment_emerg_setup_exp_bssap();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010709
10710 /* Here would usually be a CC Call Proceeding from the MSC, but what does the BSC care about DTAP. */
10711
10712 /* Do a Location Request in-between the CC call setup */
10713 f_bssap_le_register_imsi(g_pars.imsi, omit);
10714 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10715 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10716 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10717 /* SMLC got the TA from the BSC, now responds with geo information data. */
10718 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10719 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10720 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10721
Pau Espin Pedrol14076d32023-01-03 17:07:59 +010010722 f_assignment_emerg_setup_voice();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010723
10724 setverdict(pass);
10725 f_perform_clear();
10726}
10727
10728testcase TC_emerg_call_and_lcs_loc_req() runs on test_CT {
10729 var MSC_ConnHdlr vc_conn;
10730 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10731
10732 f_init(1, true);
10733 f_sleep(1.0);
10734 f_vty_allow_emerg_msc(true);
10735 f_vty_allow_emerg_bts(true, 0);
10736 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req), pars);
10737 vc_conn.done;
10738 f_shutdown_helper();
10739}
10740
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020010741private altstep no_bssmap_clear_req() runs on MSC_ConnHdlr {
10742 [] BSSAP.receive(tr_BSSMAP_ClearRequest) {
10743 setverdict(fail, "unexpected BSSMAP Clear Request");
10744 mtc.stop;
10745 }
10746}
10747
10748private type enumerated RslRel {
10749 RSLREL_REL_IND,
10750 RSLREL_CONN_FAIL
10751};
10752
10753private function f_emerg_call_and_lcs_loc_req_early_lchan_release(RslRel rsl_rel) runs on MSC_ConnHdlr
10754{
10755 g_pars.ra := f_rnd_ra_emerg();
10756 f_assignment_emerg_setup();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +010010757 f_assignment_emerg_setup_exp_bssap();
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020010758
10759 /* Start a Location Request to locate the emergency */
10760 f_bssap_le_register_imsi(g_pars.imsi, omit);
10761 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10762 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10763 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10764
10765 /* As long as this LCS is going on, the BSC should not send any Clear Request. Later on, it is up to the MSC to
10766 * do a Clear Command when the Location Response arrives. */
10767 activate(no_bssmap_clear_req());
10768
10769 /* the lchan gets interrupted while the Location Request has no response */
10770 select (rsl_rel) {
10771 case (RSLREL_REL_IND) {
10772 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
10773 f_expect_lchan_rel(RSL, RSL_PROC);
10774 }
10775 case (RSLREL_CONN_FAIL) {
10776 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
10777 }
10778 case else {
10779 setverdict(fail, "Unknown RslRel type");
10780 mtc.stop;
10781 }
10782 }
10783
10784 /* Still expect the Location Response to find its way to the MSC. */
10785 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10786 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10787 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10788
10789 setverdict(pass);
10790
10791 select (rsl_rel) {
10792 case (RSLREL_REL_IND) {
10793 f_perform_clear_no_lchan();
10794 }
10795 case (RSLREL_CONN_FAIL) {
10796 f_perform_clear();
10797 }
10798 }
10799}
10800
10801private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind(charstring id) runs on MSC_ConnHdlr
10802{
10803 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_REL_IND);
10804}
10805
10806testcase TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() runs on test_CT {
10807 var MSC_ConnHdlr vc_conn;
10808 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10809
10810 f_init(1, true);
10811 f_sleep(1.0);
10812 f_vty_allow_emerg_msc(true);
10813 f_vty_allow_emerg_bts(true, 0);
10814 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind), pars);
10815 vc_conn.done;
10816 f_shutdown_helper();
10817}
10818
10819private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail(charstring id) runs on MSC_ConnHdlr
10820{
10821 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_CONN_FAIL);
10822}
10823
10824testcase TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() runs on test_CT {
10825 var MSC_ConnHdlr vc_conn;
10826 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10827
10828 f_init(1, true);
10829 f_sleep(1.0);
10830 f_vty_allow_emerg_msc(true);
10831 f_vty_allow_emerg_bts(true, 0);
10832 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail), pars);
10833 vc_conn.done;
10834 f_shutdown_helper();
10835}
10836
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010837/* Attempt Complete Layer 3 without any MSC available (OS#4832) */
10838private function f_tc_no_msc(charstring id) runs on MSC_ConnHdlr {
10839 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10840
10841 /* Also disable attach for the single connected MSC */
10842 f_vty_msc_allow_attach(BSCVTY, { false });
10843
10844 var octetstring l3_enc := enc_PDU_ML3_MS_NW(valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000100001'H)), '00F110'O) ));
10845 f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
10846
10847 /* No MSC is found, expecting a proper release on RSL */
10848 interleave {
10849 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
10850 f_logp(BSCVTY, "Got RSL RR Release");
10851 }
10852 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
10853 f_logp(BSCVTY, "Got RSL Deact SACCH");
10854 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020010855 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010856 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
10857 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020010858 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010859 }
10860 }
10861 setverdict(pass);
10862}
10863testcase TC_no_msc() runs on test_CT {
10864
10865 f_init(1, true);
10866 f_sleep(1.0);
10867 var MSC_ConnHdlr vc_conn;
10868 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10869
10870 f_ctrs_bsc_init(counternames_bsc_mscpool);
10871
10872 vc_conn := f_start_handler(refers(f_tc_no_msc), pars);
10873 vc_conn.done;
10874
10875 f_ctrs_bsc_add("mscpool:subscr:no_msc");
10876 f_ctrs_bsc_verify();
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010877 f_shutdown_helper();
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010878}
10879
Harald Welte0ea2d5e2018-04-07 21:40:29 +020010880/* Dyn PDCH todo:
10881 * activate OSMO as TCH/F
10882 * activate OSMO as TCH/H
10883 * does the BSC-located PCU socket get the updated INFO?
10884 * what if no PCU is connected at the time?
10885 * is the info correct on delayed PCU (re)connect?
10886 */
Harald Welte94e0c342018-04-07 11:33:23 +020010887
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010888private function f_TC_refuse_mode_modif_to_vamos(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +020010889 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020010890 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010891
10892 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
10893 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
10894 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
10895 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
10896 g_pars.ass_codec_list.codecElements[0];
10897 if (isvalue(g_pars.expect_mr_s0_s7)) {
10898 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
10899 g_pars.expect_mr_s0_s7;
10900 }
10901 }
10902 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
10903 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
10904 log("expecting ASS COMPL like this: ", exp_compl);
10905
10906 f_establish_fully(ass_cmd, exp_compl);
10907
Neels Hofmeyr8746b0d2021-06-01 17:25:39 +020010908 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 modify vamos tsc 2 3");
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010909
10910 var RSL_Message rsl;
10911
10912 timer T := 5.0;
10913 T.start;
10914 alt {
10915 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
10916 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
10917 log("Rx L3 from net: ", l3);
10918 if (ischosen(l3.msgs.rrm.channelModeModify)) {
10919 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
10920 mtc.stop;
10921 }
10922 }
10923 [] RSL.receive(tr_RSL_MODE_MODIFY_REQ(g_chan_nr, ?)) -> value rsl {
10924 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
10925 mtc.stop;
10926 }
10927 [] T.timeout {
10928 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related Mode Modify should happen. */
10929 setverdict(pass);
10930 }
10931 }
10932 T.stop;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010933
10934 f_perform_clear();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010935}
10936
10937/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel Mode Modify to VAMOS mode is refused by
10938 * osmo-bsc. */
10939testcase TC_refuse_mode_modif_to_vamos() runs on test_CT {
10940 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10941 var MSC_ConnHdlr vc_conn;
10942
10943 f_init(1, true);
10944 f_sleep(1.0);
10945
10946 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10947 vc_conn := f_start_handler(refers(f_TC_refuse_mode_modif_to_vamos), pars);
10948 vc_conn.done;
10949 f_shutdown_helper();
10950}
10951
10952/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel activation to VAMOS mode is refused by osmo-bsc.
10953 */
10954testcase TC_refuse_chan_act_to_vamos() runs on test_CT {
10955 f_init_vty();
10956
10957 f_init(1, false);
10958 f_sleep(1.0);
10959
10960 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 activate-vamos fr");
10961
10962 var ASP_RSL_Unitdata rx_rsl_ud;
10963 timer T := 5.0;
10964
10965 T.start;
10966 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010967 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(?, IPAC_PROTO_RSL_TRX0)) -> value rx_rsl_ud {
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010968 if (rx_rsl_ud.rsl.msg_type == RSL_MT_CHAN_ACTIV) {
10969 T.stop;
10970 setverdict(fail, "CHANnel ACTivate in VAMOS mode succeeded even though BTS does not support VAMOS");
10971 mtc.stop;
10972 }
10973 repeat;
10974 }
10975 [] T.timeout {
10976 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related CHANnel ACTivate should happen. */
10977 setverdict(pass);
10978 }
10979 }
10980}
10981
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010982private function f_TC_reassignment_codec(charstring id) runs on MSC_ConnHdlr {
10983 /* First fully set up a speech lchan */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010984 f_assignment_codec(id, do_perform_clear := false);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010985
10986 /* Trigger re-assignment to another lchan */
10987 var AssignmentState assignment_st := valueof(ts_AssignmentStateInit);
10988
10989 /* Re-Assignment should tell the MGW endpoint the new lchan's RTP address and port, so expecting to see exactly
10990 * one MDCX on MGCP. */
10991 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].mdcx_seen_exp + 1;
10992
10993 /* The new lchan will see all-new IPAC_CRCX and IPAC_MDCX messages telling the BTS the same RTP address and port
10994 * as the old lchan used. */
10995 g_media.bts.ipa_crcx_seen := false;
10996 g_media.bts.ipa_mdcx_seen := false;
10997
10998 /* Send different BTS side RTP port number for the new lchan */
10999 g_media.bts.bts.port_nr := 4223;
11000
11001 f_rslem_register(0, valueof(ts_RslChanNr_Bm(2))); /* <-- FIXME: can we somehow infer the timeslot that will be used? */
11002
11003 /* Trigger re-assignment. */
11004 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot " & int2str(g_chan_nr.tn) & " sub-slot 0 assignment");
11005
11006 timer T := 5.0;
11007 T.start;
11008 alt {
11009 [] as_assignment(assignment_st);
11010 [] as_Media();
11011 [] T.timeout {
11012 break;
11013 }
11014 }
11015
11016 if (not assignment_st.assignment_done) {
11017 setverdict(fail, "Assignment did not complete");
11018 mtc.stop;
11019 }
11020
11021 f_check_mgcp_expectations()
11022 setverdict(pass);
11023
11024 f_sleep(2.0);
11025 log("show lchan summary: ", f_vty_transceive_ret(BSCVTY, "show lchan summary"));
11026
11027 /* Instruct BSC to clear channel */
11028 var BssmapCause cause := 0;
11029 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
11030 interleave {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011031 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {}
11032 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020011033 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011034 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020011035 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011036 }
11037 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
11038 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
11039 }
11040 }
Neels Hofmeyr40a45d12021-09-23 22:57:12 +020011041 f_expect_dlcx_conns();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011042
11043 f_sleep(0.5);
11044}
11045
11046testcase TC_reassignment_fr() runs on test_CT {
11047 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11048 var MSC_ConnHdlr vc_conn;
11049
11050 f_init(1, true);
11051 f_sleep(1.0);
11052
Neels Hofmeyrac432fa2021-11-02 16:45:56 +010011053 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011054
11055 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11056 vc_conn := f_start_handler(refers(f_TC_reassignment_codec), pars);
11057 vc_conn.done;
11058
11059 /* from f_establish_fully() */
11060 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
11061 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
11062 /* from re-assignment */
11063 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
11064 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
11065 f_ctrs_bsc_and_bts_verify();
11066 f_shutdown_helper();
11067}
11068
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011069const charstring REEST_LOST_CONNECTION := "REEST_LOST_CONNECTION";
11070const charstring REEST_CLEAR := "REEST_CLEAR";
11071const charstring REEST_CLEAR_DONE := "REEST_CLEAR_DONE";
11072
11073/* CM Re-Establishment, 3GPP TS 24.008 4.5.1.6.
11074 * The MS <-> BTS loses radio connection, MS shows up on second BTS and asks for CM Re-Establishment.
11075 * BSC should establish a separate A conn for the same MS, the original A conn is then cleared by
11076 * the MSC as the CM Re-Establishment is handled.
11077 *
11078 * MS bts0 bts1 bsc msc test-component
11079 * |<----->|<----------------->|<-0-->| _1 Establish channel on bts 0
11080 * | | _1 wait a bit, to settle down
11081 * |<-x x--| | _1 "lose connection"
11082 * | | REEST_LOST_CONNECTION
11083 * |----------------->|------->|--1-->| _2 new A-conn: Chan Rqd, Imm Ass, Compl L3 with CM Re-Establishment Req
11084 * | | REEST_CLEAR
11085 * | |<-0---| _1 Clear Command on first A-conn
11086 * | |--0-->| _1 Clear Complete
11087 * | |<----------------->| | _1 Release first channel
11088 * | | REEST_CLEAR_DONE
11089 * |<-----------------|<-------|<-1---| _2 Chan Activ, Assignment Command
11090 * |<-----------------|<-------|<-1---| _2 Clear Command, Release
11091 *
11092 */
11093private function f_tc_cm_reestablishment_1(charstring id) runs on MSC_ConnHdlr {
11094 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
11095 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11096
11097 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11098 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11099
11100 f_establish_fully(ass_cmd, exp_compl);
11101
11102 /* The original channel loses connection, MS attemts CM Re-Establishment on another cell, see
11103 * f_tc_cm_reestablishment_2(). This established channel stays active until MSC sends a Clear Command. The time
11104 * when exactly that happens is determined by f_tc_cm_reestablishment_2(). */
11105 f_sleep(2.0);
11106 COORD.send(REEST_LOST_CONNECTION);
11107
11108 alt {
11109 [] COORD.receive(REEST_CLEAR);
11110 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
11111 setverdict(fail, "Unexpected channel release");
11112 mtc.stop;
11113 }
11114 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
11115 setverdict(fail, "Unexpected channel release");
11116 mtc.stop;
11117 }
11118 }
11119 f_perform_clear()
Neels Hofmeyr969abd02021-09-23 22:24:08 +020011120 f_create_mgcp_delete_ep(g_media.mgcp_ep);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011121 COORD.send(REEST_CLEAR_DONE);
11122}
11123
11124private function f_tc_cm_reestablishment_2(charstring id) runs on MSC_ConnHdlr {
11125 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
11126
11127 /* The MS lost the connection on the first channel, now establishes another one */
11128 COORD.receive(REEST_LOST_CONNECTION);
11129
11130 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
11131 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REESTABL_REQ(mi));
11132 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
11133
11134 f_create_bssmap_exp(l3_enc);
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011135 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, rsl_pt := RSL1, rsl_proc_pt := RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011136 BSSAP.receive(tr_BSSMAP_ComplL3(l3_enc));
11137
11138 /* MSC got the CM Re-Establishment request and first off clears the previous conn. */
11139 COORD.send(REEST_CLEAR);
11140 COORD.receive(REEST_CLEAR_DONE);
11141
11142 f_sleep(2.0);
11143
11144 /* Answer the CM Re-Establishment with an Assignment Command. */
11145 var template PDU_BSSAP expect_assignment_compl := f_gen_exp_compl();
11146 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11147 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11148 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11149
11150 var AssignmentState st := valueof(ts_AssignmentStateInit);
11151 st.voice_call := true;
11152 st.is_assignment := true;
11153
11154 var ExpectCriteria mgcpcrit := {
11155 connid := omit,
11156 endpoint := omit,
11157 transid := omit
11158 };
11159 f_create_mgcp_expect(mgcpcrit);
11160
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011161 f_rslem_dchan_queue_enable(RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011162
11163 BSSAP.send(ass_cmd);
11164
11165 var PDU_BSSAP bssap;
11166
11167 alt {
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011168 [] as_assignment(st, rsl_pt := RSL1, rsl_proc_pt := RSL1_PROC);
11169 [] as_Media_ipacc(RSL1, RSL2);
11170 [] as_Media_mgw();
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011171 [st.assignment_done] BSSAP.receive(expect_assignment_compl) {
11172 break;
11173 }
11174 }
11175
11176 f_sleep(3.0);
11177
11178 f_logp(BSCVTY, "f_tc_cm_reestablishment_2 clearing");
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011179 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011180}
11181
11182testcase TC_cm_reestablishment() runs on test_CT {
11183 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
11184 var MSC_ConnHdlr vc_conn1;
11185
11186 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
11187 var MSC_ConnHdlr vc_conn2;
11188 pars2.imsi := pars1.imsi;
11189 pars2.media_nr := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011190 pars2.expect_tsc := c_BtsParams[1].tsc;
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011191
11192 f_init(2, true, guard_timeout := 40.0);
11193 f_sleep(1.0);
11194
11195 vc_conn1 := f_start_handler_create(pars1);
11196 vc_conn2 := f_start_handler_create(pars2);
11197 connect(vc_conn1:COORD, vc_conn2:COORD);
11198 f_start_handler_run(vc_conn1, refers(f_tc_cm_reestablishment_1), pars1);
11199 f_start_handler_run(vc_conn2, refers(f_tc_cm_reestablishment_2), pars2);
11200 vc_conn1.done;
11201 vc_conn2.done;
11202
11203 f_shutdown_helper();
11204}
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000011205
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011206function f_exp_ipa_rx_nonfatal(template (present) RSL_Message t_rx,
11207 boolean ignore_other_rx := true,
11208 BtsTrxIdx idx := {0, 0},
11209 float Tval := 2.0)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011210runs on test_CT return template (omit) RSL_Message {
11211 var ASP_RSL_Unitdata rx_rsl_ud;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011212 timer T := Tval;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011213
11214 T.start;
11215 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011216 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011217 T.stop;
11218 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011219 [ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
11220 [not ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011221 log("f_exp_ipa_rx_nonfatal(): Got different message than ", t_rx);
11222 T.stop;
11223 return omit;
11224 }
11225 [] T.timeout {
11226 return omit;
11227 }
11228 }
11229 return rx_rsl_ud.rsl;
11230}
11231
11232private function f_vty_set_imm_ass(TELNETasp_PT pt, BtsNr bts_nr := 0, charstring imm_ass_setting := "post-chan-ack") {
11233 f_vty_enter_cfg_bts(pt, bts_nr);
11234 f_vty_transceive(pt, "immediate-assignment " & imm_ass_setting);
11235 f_vty_transceive(pt, "exit");
11236 f_vty_transceive(pt, "exit");
11237 f_vty_transceive(pt, "exit");
11238}
11239
11240private function f_verify_imm_ass(RSL_Message imm_ass, template uint8_t ra := ?, template GsmFrameNumber fn := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +030011241 template (present) RslChannelNr chan_nr := ?,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011242 template (present) uint12_t arfcn := ?,
11243 template (present) uint3_t tsc := ?)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011244{
11245 var RSL_IE_Body full_imm_ass_info;
11246 if (not f_rsl_find_ie(imm_ass, RSL_IE_FULL_IMM_ASS_INFO, full_imm_ass_info)) {
11247 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
11248 mtc.stop;
11249 }
11250
11251 var GsmRrMessage rr_imm_ass := dec_GsmRrMessage(full_imm_ass_info.full_imm_ass_info.payload);
11252 var template GsmRrMessage expect_imm_ass := tr_IMM_ASS(ra := ra,
11253 fn := fn,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011254 ch_desc := tr_ChanDescH0(chan_nr, arfcn, tsc),
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011255 page_mode := ?);
11256 if (not match(rr_imm_ass, expect_imm_ass)) {
11257 log("Error: expected ", expect_imm_ass, " got ", rr_imm_ass);
11258 setverdict(fail, "Failed to match Immediate Assignment");
11259 mtc.stop;
11260 }
11261}
11262
11263testcase TC_imm_ass_post_chan_ack() runs on test_CT {
11264 var RSL_Message chan_act;
11265 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011266 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011267
11268 f_init(1, false);
11269 f_sleep(1.0);
11270
11271 /* (should be the default anyway, just to make things clear) */
11272 f_vty_set_imm_ass(BSCVTY, 0, "post-chan-ack");
11273
11274 /* RA containing reason=LU */
11275 var GsmFrameNumber fn := 2342;
11276 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011277 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011278
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011279 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011280
11281 /* First send the Chan Act ACK */
11282 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011283 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011284 var RSL_IE_Body chan_ident_ie;
11285 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11286 setverdict(fail, "RSL Channel Identification IE is absent");
11287 mtc.stop;
11288 }
11289
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011290 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn + 10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011291
11292 /* Then expect the Immediate Assignment, after we ACKed the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011293 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011294
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011295 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11296 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011297
11298 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011299 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011300
11301 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011302 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011303 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011304 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11305
11306 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011307 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011308 f_shutdown_helper();
11309}
11310
11311testcase TC_imm_ass_pre_chan_ack() runs on test_CT {
11312 var RSL_Message chan_act;
11313 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011314 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011315
11316 f_init(1, false);
11317 f_sleep(1.0);
11318
11319 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11320
11321 /* RA containing reason=LU */
11322 var GsmFrameNumber fn := 2342;
11323 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011324 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011325
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011326 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011327 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011328 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011329 var RSL_IE_Body chan_ident_ie;
11330 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11331 setverdict(fail, "RSL Channel Identification IE is absent");
11332 mtc.stop;
11333 }
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011334
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011335 /* (set bts 0 cfg back to default) */
11336 f_vty_set_imm_ass(BSCVTY);
11337
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011338 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011339 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011340 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11341 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011342
11343 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011344 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011345
11346 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011347 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011348
11349 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011350 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011351 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011352 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11353
11354 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011355 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011356 f_shutdown_helper();
11357}
11358
Neels Hofmeyr23158742021-09-07 19:08:07 +020011359testcase TC_imm_ass_pre_ts_ack() runs on test_CT {
11360 var RSL_Message chan_act;
11361 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011362 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyr23158742021-09-07 19:08:07 +020011363
11364 f_init(1, false);
11365 f_sleep(1.0);
11366
11367 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11368
11369 /* RA containing reason=LU */
11370 var GsmFrameNumber fn := 2342;
11371 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011372 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011373
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011374 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011375 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011376 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr23158742021-09-07 19:08:07 +020011377 var RSL_IE_Body chan_ident_ie;
11378 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11379 setverdict(fail, "RSL Channel Identification IE is absent");
11380 mtc.stop;
11381 }
11382
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011383 /* (set bts 0 cfg back to default) */
11384 f_vty_set_imm_ass(BSCVTY);
11385
Neels Hofmeyr23158742021-09-07 19:08:07 +020011386 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011387 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011388 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11389 chan_ident_ie.chan_ident.ch_desc.v.tsc);
11390
11391 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011392 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011393
11394 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011395 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011396
11397 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011398 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011399 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr23158742021-09-07 19:08:07 +020011400 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11401
11402 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011403 f_perform_clear_test_ct(dt);
Neels Hofmeyr23158742021-09-07 19:08:07 +020011404 f_shutdown_helper();
11405}
11406
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011407testcase TC_imm_ass_pre_chan_ack_dyn_ts() runs on test_CT {
11408 /* change Timeslot 6 before f_init() starts RSL */
11409 f_init_vty();
11410 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11411 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11412
11413 f_init(1, false);
11414 f_sleep(1.0);
11415
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011416 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011417 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11418 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011419 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11420 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011421
11422 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11423 f_ts_set_chcomb(0, 0, 6, "PDCH");
11424
11425 /* block all static timeslots so that the dyn TS will be used */
11426 f_disable_all_tch_f();
11427 f_disable_all_tch_h();
11428 f_disable_all_sdcch();
11429
11430 var RSL_Message chan_act;
11431 var RSL_Message imm_ass;
11432
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011433 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11434
11435 /* RA containing reason=LU */
11436 var GsmFrameNumber fn := 2342;
11437 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011438 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011439
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011440 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011441 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
11442 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011443
11444 /* Now activation as SDCCH8 */
11445 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011446 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011447
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011448 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011449 var RSL_IE_Body chan_ident_ie;
11450 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11451 setverdict(fail, "RSL Channel Identification IE is absent");
11452 mtc.stop;
11453 }
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011454
11455 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011456 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011457 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11458 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011459
11460 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011461 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011462
11463 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011464 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011465
11466 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011467 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011468 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011469 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11470
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011471 /* (set bts 0 cfg back to default) */
11472 f_vty_set_imm_ass(BSCVTY);
11473
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011474 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011475 f_perform_clear_test_ct(dt);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011476 f_shutdown_helper();
11477}
11478
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011479testcase TC_imm_ass_pre_ts_ack_dyn_ts() runs on test_CT {
11480 /* change Timeslot 6 before f_init() starts RSL */
11481 f_init_vty();
11482 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11483 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11484
11485 f_init(1, false);
11486 f_sleep(1.0);
11487
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011488 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011489 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11490 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011491 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11492 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011493
11494 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11495 f_ts_set_chcomb(0, 0, 6, "PDCH");
11496
11497 /* block all static timeslots so that the dyn TS will be used */
11498 f_disable_all_tch_f();
11499 f_disable_all_tch_h();
11500 f_disable_all_sdcch();
11501
11502 var RSL_Message chan_act;
11503 var RSL_Message imm_ass;
11504
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011505 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11506
11507 /* RA containing reason=LU */
11508 var GsmFrameNumber fn := 2342;
11509 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011510 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011511
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011512 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011513 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011514
11515 /* And already the Immediate Assignment even before the PDCH Deact ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011516 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011517
11518 /* continue the Osmo style PDCH Deact (usual chan rel) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011519 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011520
11521 /* Now activation as SDCCH8 */
11522 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011523 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011524
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011525 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011526 var RSL_IE_Body chan_ident_ie;
11527 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11528 setverdict(fail, "RSL Channel Identification IE is absent");
11529 mtc.stop;
11530 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011531 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011532
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011533 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11534 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011535
11536 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011537 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011538
11539 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011540 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011541 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011542 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11543
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011544 /* (set bts 0 cfg back to default) */
11545 f_vty_set_imm_ass(BSCVTY);
11546
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011547 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011548 f_perform_clear_test_ct(dt);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011549 f_shutdown_helper();
11550}
11551
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011552/* GET and SET the bts.N.trx.M.rf_locked CTRL variable */
11553testcase TC_ctrl_trx_rf_locked() runs on test_CT {
11554 var MSC_ConnHdlr vc_conn;
11555
11556 f_init(nr_bts := 2, handler_mode := true, nr_msc := 1);
11557 f_sleep(1.0);
11558
11559 /* BTS 0, 1, 2 are OML unlocked, only BTS 0, 1 are actually connected to RSL. */
11560 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11561 "0,0,operational,unlocked,on,rsl-up;" &
11562 "1,0,operational,unlocked,on,rsl-up;" &
11563 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011564 "2,1,operational,unlocked,on,rsl-down;" &
11565 "2,2,operational,unlocked,on,rsl-down;" &
11566 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011567 "3,0,inoperational,locked,on,rsl-down;");
11568
11569 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock BTS 1 TRX 0");
11570 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11571 /* give it a moment to settle the FSM status */
11572 f_sleep(1.0);
11573
11574 /* Now BTS 1 TRX 0 should reflect "locked". Note the RF policy stays "on", because this is still handled
11575 * globally in osmo-bsc. Probably after sending "rf_locked 1" for a TRX, that TRX should reflect an RF policy
11576 * of "off"? But that's for a future patch if at all. */
11577 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11578 "0,0,operational,unlocked,on,rsl-up;" &
11579 "1,0,operational,locked,on,rsl-up;" &
11580 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011581 "2,1,operational,unlocked,on,rsl-down;" &
11582 "2,2,operational,unlocked,on,rsl-down;" &
11583 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011584 "3,0,inoperational,locked,on,rsl-down;");
11585
11586 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock the already locked TRX, nothing should change");
11587 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11588 f_sleep(1.0);
11589 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11590 "0,0,operational,unlocked,on,rsl-up;" &
11591 "1,0,operational,locked,on,rsl-up;" &
11592 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011593 "2,1,operational,unlocked,on,rsl-down;" &
11594 "2,2,operational,unlocked,on,rsl-down;" &
11595 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011596 "3,0,inoperational,locked,on,rsl-down;");
11597
11598 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock BTS 1 TRX 0");
11599 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "0");
11600 f_sleep(1.0);
11601 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11602 "0,0,operational,unlocked,on,rsl-up;" &
11603 "1,0,operational,unlocked,on,rsl-up;" &
11604 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011605 "2,1,operational,unlocked,on,rsl-down;" &
11606 "2,2,operational,unlocked,on,rsl-down;" &
11607 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011608 "3,0,inoperational,locked,on,rsl-down;");
11609
11610 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an already unlocked TRX, nothing should change");
11611 f_ctrl_set(IPA_CTRL, "bts.0.trx.0.rf_locked", "0");
11612 f_sleep(1.0);
11613 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11614 "0,0,operational,unlocked,on,rsl-up;" &
11615 "1,0,operational,unlocked,on,rsl-up;" &
11616 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011617 "2,1,operational,unlocked,on,rsl-down;" &
11618 "2,2,operational,unlocked,on,rsl-down;" &
11619 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011620 "3,0,inoperational,locked,on,rsl-down;");
11621
11622 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an inoperational TRX");
11623 f_ctrl_set(IPA_CTRL, "bts.3.trx.0.rf_locked", "0");
11624 f_sleep(1.0);
11625 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11626 "0,0,operational,unlocked,on,rsl-up;" &
11627 "1,0,operational,unlocked,on,rsl-up;" &
11628 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011629 "2,1,operational,unlocked,on,rsl-down;" &
11630 "2,2,operational,unlocked,on,rsl-down;" &
11631 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011632 "3,0,inoperational,locked,on,rsl-down;");
11633
11634 f_shutdown_helper();
11635}
11636
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011637const CounterNameVals counternames_cm_serv_rej := {
11638 { "cm_serv_rej", 0 },
11639 { "cm_serv_rej:imsi_unknown_in_hlr", 0 },
11640 { "cm_serv_rej:illegal_ms", 0 },
11641 { "cm_serv_rej:imsi_unknown_in_vlr", 0 },
11642 { "cm_serv_rej:imei_not_accepted", 0 },
11643 { "cm_serv_rej:illegal_me", 0 },
11644 { "cm_serv_rej:plmn_not_allowed", 0 },
11645 { "cm_serv_rej:loc_not_allowed", 0 },
11646 { "cm_serv_rej:roaming_not_allowed", 0 },
11647 { "cm_serv_rej:network_failure", 0 },
11648 { "cm_serv_rej:synch_failure", 0 },
11649 { "cm_serv_rej:congestion", 0 },
11650 { "cm_serv_rej:srv_opt_not_supported", 0 },
11651 { "cm_serv_rej:rqd_srv_opt_not_supported", 0 },
11652 { "cm_serv_rej:srv_opt_tmp_out_of_order", 0 },
11653 { "cm_serv_rej:call_can_not_be_identified", 0 },
11654 { "cm_serv_rej:incorrect_message", 0 },
11655 { "cm_serv_rej:invalid_mandantory_inf", 0 },
11656 { "cm_serv_rej:msg_type_not_implemented", 0 },
11657 { "cm_serv_rej:msg_type_not_compatible", 0 },
11658 { "cm_serv_rej:inf_eleme_not_implemented", 0 },
11659 { "cm_serv_rej:condtional_ie_error", 0 },
11660 { "cm_serv_rej:msg_not_compatible", 0 },
11661 { "cm_serv_rej:protocol_error", 0 },
11662 { "cm_serv_rej:retry_in_new_cell", 0 }
11663};
11664
11665private function f_TC_cm_serv_rej(charstring id) runs on MSC_ConnHdlr
11666{
11667 f_create_chan_and_exp();
Vadim Yanitskiya7fc5a62021-12-04 20:10:08 +030011668 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011669 BSSAP.send(ts_PDU_DTAP_MT(ts_CM_SERV_REJ('02'O), '00'O));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011670 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_CM_SERV_REJ));
11671 f_perform_clear();
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011672 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011673}
11674testcase TC_cm_serv_rej() runs on test_CT {
11675 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11676 var MSC_ConnHdlr vc_conn;
11677
11678 f_init(1, true);
11679 f_sleep(1.0);
11680
11681 f_ctrs_bts_init(1, counternames_cm_serv_rej);
11682
11683 vc_conn := f_start_handler(refers(f_TC_cm_serv_rej), pars);
11684 vc_conn.done;
11685
11686 f_ctrs_bts_add(0, "cm_serv_rej", 1);
11687 f_ctrs_bts_add(0, "cm_serv_rej:imsi_unknown_in_hlr", 1);
11688 f_ctrs_bts_verify();
11689
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011690 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011691 f_shutdown_helper();
11692}
11693
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011694/* Reproduce a segfault happening when the SDCCH (primary) lchan is lost in-between a TCH Channel Activ and its Channel
11695 * Activ Ack (SYS#5627). */
11696private function f_TC_lost_sdcch_during_assignment(charstring id) runs on MSC_ConnHdlr {
11697 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Vadim Yanitskiyf0310e32021-10-26 00:30:59 +030011698
11699 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11700 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011701
11702 var BSSMAP_FIELD_CodecType codecType;
11703 codecType := valueof(ass_cmd.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType);
11704
11705 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
11706
11707 /* First establish a signalling lchan */
11708 f_create_chan_and_exp();
11709 f_rslem_dchan_queue_enable();
11710
11711 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011712
11713 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
Oliver Smith735b47c2023-02-15 16:03:54 +010011714 activate(as_Media_mgw());
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011715
11716 var RslChannelNr chan_nr := { u := { ch0 := RSL_CHAN_NR_Bm_ACCH }, tn := 1 };
11717 f_rslem_register(0, chan_nr);
11718
11719 f_rslem_set_auto_chan_act_ack(RSL_PROC, false);
11720 BSSAP.send(ass_cmd);
11721
11722
11723 /* Wait for the Channel Activ for the TCH channel */
11724 var ASP_RSL_Unitdata rx_rsl_ud;
11725 RSL.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), sid := ?)) -> value rx_rsl_ud;
11726
11727 /* make the original SDCCH disappear */
11728 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
11729
11730 /* and ACK the TCH channel activation. This caused a segfault up to OsmoBSC 1.7.0 (SYS#5627) */
11731 RSL.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_ACK(chan_nr, 23), rx_rsl_ud.streamId));
11732
11733 interleave {
11734 [] BSSAP.receive(tr_BSSMAP_AssignmentFail);
11735 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
11736 }
11737
11738 BSSAP.send(ts_BSSMAP_ClearCommand(0));
11739 BSSAP.receive(tr_BSSMAP_ClearComplete);
11740 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
11741
11742 var MgcpCommand mgcp;
Vadim Yanitskiy6be4cf42022-06-04 21:25:47 +060011743 var MGCP_RecvFrom mrf;
11744 var template MgcpMessage msg_dlcx := { command := tr_DLCX };
11745 alt {
11746 [g_pars.aoip] MGCP.receive(tr_DLCX) -> value mgcp {
11747 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
11748 }
11749 [not g_pars.aoip] MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
11750 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, MgcpMessage:{
11751 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
11752 }));
11753 }
11754 }
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011755
11756 f_sleep(0.5);
11757}
11758testcase TC_lost_sdcch_during_assignment() runs on test_CT {
11759 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11760 var MSC_ConnHdlr vc_conn;
11761
Oliver Smith735b47c2023-02-15 16:03:54 +010011762 pars.fail_on_dlcx := false;
11763
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011764 f_init(1, true);
11765 f_sleep(1.0);
11766
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011767 vc_conn := f_start_handler(refers(f_TC_lost_sdcch_during_assignment), pars);
11768 vc_conn.done;
11769
11770 f_shutdown_helper();
11771}
11772
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011773const CounterNameVals counternames_bsc_bts_all_available_allocated := {
11774 { "all_allocated:sdcch", 0 },
11775 { "all_allocated:static_sdcch", 0 },
11776 { "all_allocated:tch", 0 },
11777 { "all_allocated:static_tch", 0 }
11778}
11779
11780private function f_all_allocated_expect_counter_change(charstring_list expect_changed) runs on test_CT
11781{
11782 /* Make sure counters settle first */
11783 f_sleep(1.0);
11784
11785 /* Take a baseline of counters */
11786 f_ctrs_bsc_and_bts_init(1, counternames_bsc_bts_all_available_allocated);
11787
11788 /* Elapse some time so that we see changes in counters, hopefully where expected */
11789 f_sleep(2.0);
11790
11791 /* Get new counters */
11792 var charstring_list all_changed := {};
11793 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bsc", g_ctr_bsc);
11794 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bts", g_ctr_bts);
11795
11796 /* Compare with expectations */
11797 var charstring_list all_expect_changed := {};
11798 for (var integer i := 0; i < lengthof(expect_changed); i := i + 1) {
11799 all_expect_changed := all_expect_changed & { "bsc.0." & expect_changed[i], "bts.0." & expect_changed[i] };
11800 }
11801 f_counter_name_vals_expect_changed_list(all_changed, all_expect_changed);
11802}
11803
11804testcase TC_ratectr_all_available_allocated() runs on test_CT {
11805 var ASP_RSL_Unitdata rsl_ud;
11806 var integer i;
11807 var integer chreq_total, chreq_nochan;
11808
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011809 f_init(1, guard_timeout := 60.0);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011810 f_sleep(1.0);
11811
11812 /* Exhaust all dedicated SDCCH lchans.
11813 /* GSM 44.018 Table 9.1.8.2:
11814 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11815 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011816 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011817 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011818 chan_cleanup := chan_cleanup & { f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, gen_l3_valid_payload()) };
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011819 }
11820
11821 /* Since only bts 0 is connected, expecting all_allocated to become true for both bts 0 and the "global" bsc
11822 * level.
11823 * All SDCCH are now occupied. */
11824 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11825
11826 /* Also fill up all remaining (TCH) channels */
11827 for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011828 chan_cleanup := chan_cleanup & { f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, gen_l3_valid_payload()) };
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011829 }
11830
11831 /* All TCH are now also occupied */
11832 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11833 "all_allocated:tch", "all_allocated:static_tch"});
11834
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011835 /* Clean up SDCCH lchans */
11836 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
11837 f_perform_clear_test_ct(chan_cleanup[i]);
11838 }
11839
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011840 f_shutdown_helper();
11841}
11842
11843testcase TC_ratectr_all_available_allocated_dyn() runs on test_CT {
11844 var ASP_RSL_Unitdata rsl_ud;
11845 var integer i;
11846 var integer chreq_total, chreq_nochan;
11847
11848 f_init_vty();
11849 f_ts_set_chcomb(0, 0, 2, "TCH/F_TCH/H_PDCH");
11850 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11851 /* Now we have 3 TCH/F, 1 OSMO_DYN, 1 TCH/H */
11852
11853 f_init(1, guard_timeout := 60.0);
11854 f_sleep(1.0);
11855
11856 /* The dyn TS wants to activate PDCH mode, ACK that. */
11857 var RslChannelNr chan_nr;
11858 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011859 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11860 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011861
11862 /* Exhaust all dedicated SDCCH lchans.
11863 /* GSM 44.018 Table 9.1.8.2:
11864 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11865 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011866 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011867 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011868 chan_cleanup := chan_cleanup & { f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, gen_l3_valid_payload()) };
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011869 }
11870
11871 /* The static SDCCH should now be occupied, while still 3x8 dynamic SDCCH potentially remain. So only
11872 * all_allocated:static_sdcch is counted, all_allocated:sdcch remains zero. */
11873 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch"});
11874
11875 /* Request more SDCCH, hence convert the first dyn TS to SDCCH8.
11876 * Will release them later, so remember all the DchanTuples. */
11877 var DchanTuples dyn_sddch := {};
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011878 dyn_sddch := dyn_sddch & { f_est_dchan_dyn('33'O, NUM_SDCCH_PER_BTS + i, gen_l3_valid_payload()) };
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011879
11880 /* Also occupy the seven other SDCCH of the dyn TS */
11881 for (i := 0; i < 7; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011882 dyn_sddch := dyn_sddch & { f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, gen_l3_valid_payload()) };
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011883 }
11884
11885 /* Now all dynamic SDCCH are also occupied, so for the first time all_allocated:sdcch will trigger... */
11886 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11887
11888 /* occupy the remaining TCH, three TCH/F and two TCH/H lchans */
11889 for (i := 0; i < 5; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011890 chan_cleanup := chan_cleanup & { f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, gen_l3_valid_payload()) };
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011891 }
11892
11893 /* All TCH lchans are now also occupied, both static and dynamic */
11894 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11895 "all_allocated:tch", "all_allocated:static_tch"});
11896
11897 /* Starting to release the dyn TS: as soon as the first SDCCH gets released, all_allocated:sdcch stops
11898 * incrementing. */
11899 var BssmapCause cause := 0;
11900 var DchanTuple dt := dyn_sddch[0];
11901 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011902 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011903
11904 /* one dyn TS SDCCH is free again, so only the static_sdcch should increment. For tch, both static and dynamic
11905 * count as occupied, so those still both increment. */
11906 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch",
11907 "all_allocated:tch", "all_allocated:static_tch"});
11908
11909 /* Release the remaining SDCCH of the dyn TS, so it becomes available as TCH again */
11910 for (i := 1; i < lengthof(dyn_sddch); i := i+1) {
11911 dt := dyn_sddch[i];
11912 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011913 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011914 }
11915
11916 /* All SDCCH on the dyn TS are released, the dyn TS wants to activate PDCH again */
11917 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011918 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11919 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011920
11921 /* Now all channels are occupied except the dyn TS, so expecting only the static counters to increment */
11922 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch", "all_allocated:static_tch"});
11923
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011924 /* Clean up SDCCH lchans */
11925 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
11926 f_perform_clear_test_ct(chan_cleanup[i]);
11927 }
11928
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011929 /* clean up config */
11930 f_ts_reset_chcomb(0);
11931
11932 f_shutdown_helper();
11933}
11934
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011935private function f_TC_chan_alloc_algo(DchanTuple dt, BtsTrxIdx idx)
11936runs on test_CT {
11937 /* MSC sends an Assignment Request */
11938 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11939 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11940 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11941 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
11942
11943 /* Expect the BSC to allocate a TCH channel on the given BTS/TRX */
11944 var RSL_Message rsl_chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
11945 /* Send CHAN ACT NACK, so that the requested TCH channel becomes BORKEN */
11946 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(rsl_chan_act.ies[0].body.chan_nr, RSL_ERR_EQUIPMENT_FAIL), idx);
11947 /* Expect to receive an Assignment Failure */
11948 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail));
11949}
11950
11951testcase TC_chan_alloc_algo_ascending() runs on test_CT {
11952 /* We need to access BTS2, which has 4 TRXs */
11953 f_init(nr_bts := 3);
11954
11955 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020011956 vc_MGCP[0].stop;
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011957
11958 f_vty_enter_cfg_bts(BSCVTY, 2);
11959 f_vty_transceive(BSCVTY, "channel allocator ascending");
11960 f_vty_transceive(BSCVTY, "end");
11961
11962 /* Expect the BSC to allocate 4 x TCH/F channels on BTS2/TRX0 */
11963 for (var integer i := 0; i < 4; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011964 var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), {2, 0});
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011965 f_TC_chan_alloc_algo(dt, {2, 0});
11966 f_perform_clear_test_ct(dt);
11967 }
11968
11969 /* At this point all 4 x TCH/F channels are BORKEN, but they will be
11970 * resurrected upon the A-bis/OML link re-establishment. */
11971 f_shutdown_helper();
11972}
11973
11974testcase TC_chan_alloc_algo_descending() runs on test_CT {
11975 /* We need to access BTS2, which has 4 TRXs */
11976 f_init(nr_bts := 3);
11977
11978 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020011979 vc_MGCP[0].stop;
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011980
11981 f_vty_enter_cfg_bts(BSCVTY, 2);
11982 f_vty_transceive(BSCVTY, "channel allocator descending");
11983 f_vty_transceive(BSCVTY, "end");
11984
11985 /* Expect the BSC to allocate 5 x TCH/F channels on BTS2/TRX3 */
11986 for (var integer i := 0; i < 5; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011987 var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), {2, 0});
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011988 f_TC_chan_alloc_algo(dt, {2, 3});
11989 f_perform_clear_test_ct(dt);
11990 }
11991
11992 /* At this point all 5 x TCH/F channels are BORKEN, but they will be
11993 * resurrected upon the A-bis/OML link re-establishment. */
11994 f_shutdown_helper();
11995}
11996
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011997testcase TC_chan_alloc_algo_ass_dynamic() runs on test_CT {
11998 const BtsTrxIdx TRX0 := {2, 0};
11999 const BtsTrxIdx TRX3 := {2, 3};
12000
12001 /* We need to access BTS2, which has 4 TRXs */
12002 f_init(nr_bts := 3);
12003
12004 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020012005 vc_MGCP[0].stop;
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012006
12007 f_vty_enter_cfg_bts(BSCVTY, 2);
12008 f_vty_transceive(BSCVTY, "channel allocator mode assignment dynamic");
12009 f_vty_transceive(BSCVTY, "channel allocator dynamic-param ul-rxlev thresh 50 avg-num 2");
12010 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 0");
12011 f_vty_transceive(BSCVTY, "end");
12012
12013 var DchanTuple dt;
12014
12015 f_logp(BSCVTY, "Case a) Unknown Uplink RxLev, fall-back to ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012016 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012017 f_TC_chan_alloc_algo(dt, TRX0);
12018 f_perform_clear_test_ct(dt);
12019
12020 f_logp(BSCVTY, "Case b) Not enough RxLev samples, use ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012021 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012022 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12023 ts_RSL_IE_UplinkMeas(30, 0),
12024 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012025 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012026 f_TC_chan_alloc_algo(dt, TRX0);
12027 f_perform_clear_test_ct(dt);
12028
12029 f_logp(BSCVTY, "Case c) Uplink RxLev below the threshold, use ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012030 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012031 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12032 ts_RSL_IE_UplinkMeas(45, 0),
12033 ts_RSL_IE_BS_Power(0)), TRX0);
12034 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
12035 ts_RSL_IE_UplinkMeas(48, 0),
12036 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012037 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012038 f_TC_chan_alloc_algo(dt, TRX0);
12039 f_perform_clear_test_ct(dt);
12040
12041 f_logp(BSCVTY, "Case d) Uplink RxLev above the threshold, use descending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012042 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012043 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12044 ts_RSL_IE_UplinkMeas(50, 0),
12045 ts_RSL_IE_BS_Power(0)), TRX0);
12046 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
12047 ts_RSL_IE_UplinkMeas(58, 0),
12048 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012049 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012050 f_TC_chan_alloc_algo(dt, TRX3);
12051 f_perform_clear_test_ct(dt);
12052
12053 f_vty_enter_cfg_bts(BSCVTY, 2);
12054 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 90");
12055 f_vty_transceive(BSCVTY, "end");
12056
12057 f_logp(BSCVTY, "Case e) Uplink RxLev above the threshold, but C0 load is not");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012058 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012059 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12060 ts_RSL_IE_UplinkMeas(50, 0),
12061 ts_RSL_IE_BS_Power(0)), TRX0);
12062 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
12063 ts_RSL_IE_UplinkMeas(58, 0),
12064 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012065 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012066 f_TC_chan_alloc_algo(dt, TRX0);
12067 f_perform_clear_test_ct(dt);
12068
12069 f_vty_enter_cfg_bts(BSCVTY, 2);
12070 f_vty_transceive(BSCVTY, "channel allocator ascending");
12071 f_vty_transceive(BSCVTY, "end");
12072
12073 /* At this point some TCH/F channels are BORKEN, but they will be
12074 * resurrected upon the A-bis/OML link re-establishment. */
12075 f_shutdown_helper();
12076}
12077
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012078private function f_vty_mgw_enable(integer mgw_nr := 1) runs on test_CT {
12079 var rof_charstring cmds := {
12080 "remote-ip " & mp_test_ip,
12081 "remote-port " & int2str(2427 + mgw_nr)
12082 };
12083 f_vty_config3(BSCVTY, {"network", "mgw " & int2str(mgw_nr)}, cmds);
12084 f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " reconnect")
12085}
12086private function f_vty_mgw_disable(integer mgw_nr := 1) runs on test_CT {
12087 f_vty_config3(BSCVTY, {"network"}, { "no mgw " &int2str(mgw_nr) });
12088}
12089private function f_vty_mgw_block(integer mgw_nr := 1, boolean blocked := true) runs on test_CT {
12090 var charstring arg;
12091 if (blocked) {
12092 arg := "block";
12093 } else {
12094 arg := "unblock";
12095 }
12096 f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " " & arg);
12097}
12098private const charstring COORD_CMD_ESTABLISHED := "COORD_CMD_ESTABLISHED";
12099private function f_TC_mgwpool_call_seq_1(charstring id) runs on MSC_ConnHdlr {
12100 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12101 var PDU_BSSAP ass_cmd := f_gen_ass_req();
12102 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12103 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12104
12105 f_establish_fully(ass_cmd, exp_compl);
12106 COORD.send(COORD_CMD_ESTABLISHED);
12107
12108 COORD.receive(COORD_CMD_ESTABLISHED);
12109 f_perform_clear()
12110 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12111}
12112private function f_TC_mgwpool_call_seq_2(charstring id) runs on MSC_ConnHdlr {
12113 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12114 var PDU_BSSAP ass_cmd := f_gen_ass_req();
12115 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12116 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12117
12118
12119 COORD.receive(COORD_CMD_ESTABLISHED);
12120 f_establish_fully(ass_cmd, exp_compl);
12121 COORD.send(COORD_CMD_ESTABLISHED);
12122
12123 f_perform_clear()
12124 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12125}
12126/* Test load is spread around 2 available MGWs */
12127testcase TC_mgwpool_all_used() runs on test_CT {
12128 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12129 var MSC_ConnHdlr vc_conn1;
12130 pars1.mgwpool_idx := 0;
12131
12132 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12133 var MSC_ConnHdlr vc_conn2;
12134 pars2.mgwpool_idx := 1;
12135
12136 f_init(1, true, nr_mgw := 2);
12137 f_sleep(1.0);
12138
12139 f_vty_mgw_enable(1);
12140
12141 vc_conn1 := f_start_handler_create(pars1);
12142 vc_conn2 := f_start_handler_create(pars2);
12143 connect(vc_conn1:COORD, vc_conn2:COORD);
12144 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12145 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12146 vc_conn1.done;
12147 vc_conn2.done;
12148
12149 f_vty_mgw_disable(1);
12150
12151 f_shutdown_helper();
12152}
12153
12154/* Test blocked MGW in the pool are not selected */
12155testcase TC_mgwpool_blocked_not_used() runs on test_CT {
12156 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12157 var MSC_ConnHdlr vc_conn1;
12158 pars1.mgwpool_idx := 0;
12159
12160 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12161 var MSC_ConnHdlr vc_conn2;
12162 pars2.mgwpool_idx := 0; /* expect it in the first one, since the second will be blocked */
12163 pars2.media_nr := 2;
12164
12165 f_init(1, true, nr_mgw := 2);
12166 f_sleep(1.0);
12167
12168 f_vty_mgw_enable(1);
12169 f_vty_mgw_block(1, true);
12170
12171 vc_conn1 := f_start_handler_create(pars1);
12172 vc_conn2 := f_start_handler_create(pars2);
12173 connect(vc_conn1:COORD, vc_conn2:COORD);
12174 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12175 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12176 vc_conn1.done;
12177 vc_conn2.done;
12178
12179 f_vty_mgw_disable(1);
12180
12181 f_shutdown_helper();
12182}
12183
Pau Espin Pedrol3f41e322022-10-20 19:34:43 +020012184/* Test BTS pinning to an MGW is applied */
12185testcase TC_mgwpool_pin_bts() runs on test_CT {
12186 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12187 var MSC_ConnHdlr vc_conn1;
12188 pars1.mgwpool_idx := 0;
12189
12190 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12191 var MSC_ConnHdlr vc_conn2;
12192 pars2.mgwpool_idx := 0; /* expect it in the first one, since the BTS is pinned to the first MGW */
12193 pars2.media_nr := 2;
12194
12195 f_init(1, true, nr_mgw := 2);
12196 f_sleep(1.0);
12197
12198 f_vty_mgw_enable(1);
12199 f_vty_cfg_bts(BSCVTY, 0, { "mgw pool-target 0" });
12200
12201 vc_conn1 := f_start_handler_create(pars1);
12202 vc_conn2 := f_start_handler_create(pars2);
12203 connect(vc_conn1:COORD, vc_conn2:COORD);
12204 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12205 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12206 vc_conn1.done;
12207 vc_conn2.done;
12208
12209 f_vty_cfg_bts(BSCVTY, 0, { "no mgw pool-target" } );
Vadim Yanitskiy389d7e02022-10-25 17:44:05 +070012210 f_vty_mgw_disable(1);
Pau Espin Pedrol3f41e322022-10-20 19:34:43 +020012211
12212 f_shutdown_helper();
12213}
12214
Oliver Smithc9a5f532022-10-21 11:32:23 +020012215private function f_tc_ho_meas_rep_multi_band(charstring id) runs on MSC_ConnHdlr {
12216 g_pars := f_gen_test_hdlr_pars();
12217 var PDU_BSSAP ass_req := f_gen_ass_req();
12218 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12219 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12220 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12221 f_establish_fully(ass_req, exp_compl);
12222
12223 /* Send a measurement report with bad rxlev except on 3rd entry. The
12224 * measurement report is divided into two sub lists, as described in
12225 * 3GPP TS 04.08 § 10.5.2.20. */
12226 var NcellReports neighbor_rep := {
12227 /* Sub list 1: same band */
Oliver Smitha6773042022-10-24 12:56:30 +020012228 { rxlev := 0, bcch_freq := 0, bsic := 12 }, /* ARFCN 800, band 1800, LAC 98 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012229 /* Sub list 2: different band */
Oliver Smitha6773042022-10-24 12:56:30 +020012230 { rxlev := 0, bcch_freq := 1, bsic := 13 }, /* ARFCN 200, band 850, LAC 97 */
12231 { rxlev := 40, bcch_freq := 2, bsic := 14 }, /* ARFCN 1000, band 900, LAC 99 */
12232 { rxlev := 0, bcch_freq := 3, bsic := 11 } /* ARFCN 0, band 900, LAC 96 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012233 };
12234 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
12235 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
12236 l3_mr, 0));
12237
12238 /* Expect a handover to the third entry. If the BSC parsed the report
Oliver Smitha6773042022-10-24 12:56:30 +020012239 * correctly, the third entry has LAC 99. */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012240 var template BSSMAP_FIELD_CellIdentificationList cid_list := {
Oliver Smitha6773042022-10-24 12:56:30 +020012241 cIl_LAC := { ts_BSSMAP_CI_LAC(99) }
Oliver Smithc9a5f532022-10-21 11:32:23 +020012242 };
12243 alt {
12244 [] BSSAP.receive(tr_BSSMAP_HandoverRequired(cid_list := cid_list)) {
12245 setverdict(pass);
12246 }
12247 [] BSSAP.receive(tr_BSSMAP_HandoverRequired()) {
12248 setverdict(fail, "Handover has unexpected LAC in Cell Identification List. The BSC probably"
12249 & " didn't parse the multi-band measurement report correctly.");
12250 }
12251 }
12252
12253 f_ho_out_of_this_bsc(skip_meas_rep := true);
12254}
12255testcase TC_ho_meas_rep_multi_band() runs on test_CT {
12256 /* Verify that the BSC parses the measurement report correctly when
12257 * neighbors in multiple bands are configured (OS#5717). See
12258 * gsm_arfcn2band_rc() in libosmocore src/gsm/gsm_utils.c for the
12259 * ARFCN -> band mapping. The MS is connected to band 1800. */
12260 var MSC_ConnHdlr vc_conn;
12261
12262 f_init_vty();
12263 f_bts_0_cfg(BSCVTY,
12264 {"neighbor-list mode automatic",
12265 "handover 1",
12266 "handover algorithm 2",
12267 "handover2 window rxlev averaging 1",
12268 "no neighbors",
12269 "neighbor lac 99 arfcn 1000 bsic any", /* band 900 */
12270 "neighbor lac 98 arfcn 800 bsic any", /* band 1800 */
12271 "neighbor lac 97 arfcn 200 bsic any", /* band 850 */
Oliver Smitha6773042022-10-24 12:56:30 +020012272 "neighbor lac 96 arfcn 0 bsic any"}); /* band 900 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012273 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
12274
12275 f_init(1, true);
12276 f_sleep(1.0);
12277
12278 f_ctrs_bsc_and_bts_handover_init();
12279
12280 vc_conn := f_start_handler(refers(f_tc_ho_meas_rep_multi_band));
12281 vc_conn.done;
12282
12283 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
12284 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
12285 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
12286 f_ctrs_bsc_and_bts_add(0, "handover:completed");
12287 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
12288 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
12289 f_ctrs_bsc_and_bts_verify();
12290 f_shutdown_helper(ho := true);
12291}
12292
Harald Welte28d943e2017-11-25 15:00:50 +010012293control {
Harald Welte898113b2018-01-31 18:32:21 +010012294 /* CTRL interface testing */
Harald Welte4003d112017-12-09 22:35:39 +010012295 execute( TC_ctrl_msc_connection_status() );
Stefan Sperlingb041b3d2018-01-03 17:14:55 +010012296 execute( TC_ctrl_msc0_connection_status() );
Neels Hofmeyrf65ce872021-09-23 18:40:10 +020012297 /* In SCCPlite tests, only one MSC is configured. These tests assume that three MSCs are configured, so only run
12298 * these in the AoIP test suite. */
12299 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12300 execute( TC_stat_num_msc_connected_1() );
12301 execute( TC_stat_num_msc_connected_2() );
12302 execute( TC_stat_num_msc_connected_3() );
12303 }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +020012304 execute( TC_stat_num_bts_connected_1() );
12305 execute( TC_stat_num_bts_connected_2() );
12306 execute( TC_stat_num_bts_connected_3() );
Harald Welte96c94412017-12-09 03:12:45 +010012307 execute( TC_ctrl() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012308 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER) {
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +020012309 execute( TC_ctrl_location() );
12310 }
Harald Welte898113b2018-01-31 18:32:21 +010012311
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020012312 execute( TC_si_default() );
Neels Hofmeyr66aeba42020-07-06 02:21:21 +020012313 execute( TC_si2quater_2_earfcns() );
12314 execute( TC_si2quater_3_earfcns() );
12315 execute( TC_si2quater_4_earfcns() );
12316 execute( TC_si2quater_5_earfcns() );
12317 execute( TC_si2quater_6_earfcns() );
Neels Hofmeyrad132f22020-07-08 02:20:16 +020012318 execute( TC_si2quater_12_earfcns() );
12319 execute( TC_si2quater_23_earfcns() );
12320 execute( TC_si2quater_32_earfcns() );
12321 execute( TC_si2quater_33_earfcns() );
12322 execute( TC_si2quater_42_earfcns() );
12323 execute( TC_si2quater_48_earfcns() );
12324 execute( TC_si2quater_49_earfcns() );
Pau Espin Pedrol85a84432020-07-20 18:45:03 +020012325 execute( TC_si_acc_rotate() );
Alexander Couzens4ad3a352020-09-10 22:29:12 +020012326 execute( TC_si_acc_ramp_rotate() );
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020012327
Harald Welte898113b2018-01-31 18:32:21 +010012328 /* RSL DCHAN Channel ACtivation / Deactivation */
Harald Welteae026692017-12-09 01:03:01 +010012329 execute( TC_chan_act_noreply() );
Harald Welte4003d112017-12-09 22:35:39 +010012330 execute( TC_chan_act_counter() );
Harald Welteae026692017-12-09 01:03:01 +010012331 execute( TC_chan_act_ack_noest() );
Philipp Maier9c60a622020-07-09 15:08:46 +020012332 execute( TC_chan_act_ack_noest_emerg() );
Philipp Maier606f07d2020-08-12 17:21:58 +020012333 execute( TC_chan_rqd_emerg_deny() );
Harald Welteae026692017-12-09 01:03:01 +010012334 execute( TC_chan_act_ack_est_ind_noreply() );
12335 execute( TC_chan_act_ack_est_ind_refused() );
Harald Welte618ef642017-12-14 14:58:20 +010012336 execute( TC_chan_act_nack() );
Harald Welte799c97b2017-12-14 17:50:30 +010012337 execute( TC_chan_exhaustion() );
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +070012338 execute( TC_chan_deact_silence() );
Harald Welte4003d112017-12-09 22:35:39 +010012339 execute( TC_chan_rel_rll_rel_ind() );
12340 execute( TC_chan_rel_conn_fail() );
12341 execute( TC_chan_rel_hard_clear() );
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +020012342 execute( TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() );
12343 execute( TC_chan_rel_last_eutran_plmn_hard_clear_csfb() );
Harald Welte99787102019-02-04 10:41:36 +010012344 execute( TC_chan_rel_hard_clear_csfb() );
Harald Welted8c36cd2017-12-09 23:05:31 +010012345 execute( TC_chan_rel_hard_rlsd() );
Harald Welte550daf92018-06-11 19:22:13 +020012346 execute( TC_chan_rel_hard_rlsd_ms_dead() );
Harald Welte85804d42017-12-10 14:11:58 +010012347 execute( TC_chan_rel_a_reset() );
Pau Espin Pedrolc675b612020-01-09 19:55:40 +010012348 execute( TC_chan_rel_sccp_tiar_timeout() );
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +020012349 execute( TC_chan_rel_rr_cause() );
Harald Welte6f521d82017-12-11 19:52:02 +010012350
Harald Weltecfe2c962017-12-15 12:09:32 +010012351 execute( TC_outbound_connect() );
Harald Welte898113b2018-01-31 18:32:21 +010012352
12353 /* Assignment related */
Harald Welte16a4adf2017-12-14 18:54:01 +010012354 execute( TC_assignment_cic_only() );
Harald Welte235ebf12017-12-15 14:18:16 +010012355 execute( TC_assignment_csd() );
12356 execute( TC_assignment_ctm() );
12357 execute( TC_assignment_sign() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020012358 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12359 execute( TC_assignment_aoip_tla_v6() );
12360 }
Harald Welte235ebf12017-12-15 14:18:16 +010012361 execute( TC_assignment_fr_a5_0() );
12362 execute( TC_assignment_fr_a5_1() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012363 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte8f67d1d2018-05-25 20:38:42 +020012364 execute( TC_assignment_fr_a5_1_codec_missing() );
12365 }
Harald Welte235ebf12017-12-15 14:18:16 +010012366 execute( TC_assignment_fr_a5_3() );
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +020012367 execute( TC_assignment_fr_a5_4() );
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +020012368 execute( TC_assignment_fr_a5_4_fail() );
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +020012369 execute( TC_assignment_fr_a5_not_sup() );
Harald Welte3c86ea02018-05-10 22:28:05 +020012370 execute( TC_ciph_mode_a5_0() );
12371 execute( TC_ciph_mode_a5_1() );
Oliver Smith50b98122021-07-09 15:00:28 +020012372 execute( TC_ciph_mode_a5_2_0() );
Oliver Smith1dff88d2021-07-09 08:45:51 +020012373 execute( TC_ciph_mode_a5_2_1() );
Harald Welte3c86ea02018-05-10 22:28:05 +020012374 execute( TC_ciph_mode_a5_3() );
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +020012375 execute( TC_ciph_mode_a5_4() );
Harald Welte16a4adf2017-12-14 18:54:01 +010012376
Harald Welte60aa5762018-03-21 19:33:13 +010012377 execute( TC_assignment_codec_fr() );
Neels Hofmeyr559d5d02021-04-16 16:50:49 +020012378 execute( TC_assignment_codec_fr_by_mode_modify() );
Harald Welte60aa5762018-03-21 19:33:13 +010012379 execute( TC_assignment_codec_hr() );
12380 execute( TC_assignment_codec_efr() );
12381 execute( TC_assignment_codec_amr_f() );
12382 execute( TC_assignment_codec_amr_h() );
Philipp Maier8a581d22019-03-26 18:32:48 +010012383
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012384 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier8a581d22019-03-26 18:32:48 +010012385 execute( TC_assignment_codec_amr_f_S1() );
12386 execute( TC_assignment_codec_amr_h_S1() );
12387 execute( TC_assignment_codec_amr_f_S124() );
12388 execute( TC_assignment_codec_amr_h_S124() );
12389 execute( TC_assignment_codec_amr_f_S0() );
12390 execute( TC_assignment_codec_amr_f_S02() );
12391 execute( TC_assignment_codec_amr_f_S024() );
12392 execute( TC_assignment_codec_amr_f_S0247() );
12393 execute( TC_assignment_codec_amr_h_S0() );
12394 execute( TC_assignment_codec_amr_h_S02() );
12395 execute( TC_assignment_codec_amr_h_S024() );
12396 execute( TC_assignment_codec_amr_h_S0247() );
12397 execute( TC_assignment_codec_amr_f_S01234567() );
12398 execute( TC_assignment_codec_amr_f_S0234567() );
12399 execute( TC_assignment_codec_amr_f_zero() );
12400 execute( TC_assignment_codec_amr_f_unsupp() );
12401 execute( TC_assignment_codec_amr_h_S7() );
Neels Hofmeyr21863562020-11-26 00:34:33 +000012402 execute( TC_assignment_codec_amr_f_start_mode_auto() );
12403 execute( TC_assignment_codec_amr_h_start_mode_auto() );
Neels Hofmeyr3eb94562020-11-26 02:40:26 +000012404 execute( TC_assignment_codec_amr_f_start_mode_4() );
12405 execute( TC_assignment_codec_amr_h_start_mode_4() );
Neels Hofmeyr454d7922020-11-26 02:24:57 +000012406 execute( TC_assignment_codec_amr_startmode_cruft() );
Philipp Maier8a581d22019-03-26 18:32:48 +010012407 }
Harald Welte60aa5762018-03-21 19:33:13 +010012408
Philipp Maierac09bfc2019-01-08 13:41:39 +010012409 execute( TC_assignment_codec_fr_exhausted_req_hr() );
12410 execute( TC_assignment_codec_fr_exhausted_req_fr() );
12411 execute( TC_assignment_codec_fr_exhausted_req_fr_hr() );
12412 execute( TC_assignment_codec_fr_exhausted_req_hr_fr() );
12413 execute( TC_assignment_codec_hr_exhausted_req_fr() );
12414 execute( TC_assignment_codec_hr_exhausted_req_hr() );
12415 execute( TC_assignment_codec_hr_exhausted_req_hr_fr() );
12416 execute( TC_assignment_codec_hr_exhausted_req_fr_hr() );
12417 execute( TC_assignment_codec_req_hr_fr() );
12418 execute( TC_assignment_codec_req_fr_hr() );
Pau Espin Pedrol14475352021-07-22 15:48:16 +020012419 execute( TC_assignment_sdcch_exhausted_req_signalling() );
12420 execute( TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() );
12421 execute( TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() );
Philipp Maierac09bfc2019-01-08 13:41:39 +010012422
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +020012423 execute( TC_assignment_codec_hr_osmux_on() );
Pau Espin Pedrol23510fb2021-07-20 17:00:38 +020012424 execute( TC_assignment_osmux() );
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020012425 execute( TC_assignment_osmux_cn() );
12426 execute( TC_assignment_osmux_bts() );
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +020012427
Harald Welte898113b2018-01-31 18:32:21 +010012428 /* RLL Establish Indication on inactive DCHAN / SAPI */
Harald Welte5cd20ed2017-12-13 21:03:20 +010012429 execute( TC_rll_est_ind_inact_lchan() );
12430 execute( TC_rll_est_ind_inval_sapi1() );
12431 execute( TC_rll_est_ind_inval_sapi3() );
12432 execute( TC_rll_est_ind_inval_sacch() );
12433
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +070012434 /* DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
12435 execute( TC_tch_dlci_link_id_sapi() );
12436
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070012437 /* SAPI N Reject triggered by RLL establishment failures */
12438 execute( TC_rll_rel_ind_sapi_n_reject() );
12439 execute( TC_rll_err_ind_sapi_n_reject() );
12440 execute( TC_rll_timeout_sapi_n_reject() );
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +070012441 execute( TC_rll_sapi_n_reject_dlci_cc() );
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070012442
Harald Welte898113b2018-01-31 18:32:21 +010012443 /* Paging related tests */
Harald Welte6f521d82017-12-11 19:52:02 +010012444 execute( TC_paging_imsi_nochan() );
12445 execute( TC_paging_tmsi_nochan() );
12446 execute( TC_paging_tmsi_any() );
12447 execute( TC_paging_tmsi_sdcch() );
12448 execute( TC_paging_tmsi_tch_f() );
12449 execute( TC_paging_tmsi_tch_hf() );
12450 execute( TC_paging_imsi_nochan_cgi() );
12451 execute( TC_paging_imsi_nochan_lac_ci() );
12452 execute( TC_paging_imsi_nochan_ci() );
12453 execute( TC_paging_imsi_nochan_lai() );
12454 execute( TC_paging_imsi_nochan_lac() );
12455 execute( TC_paging_imsi_nochan_all() );
Harald Welte751d3eb2018-01-31 15:51:06 +010012456 execute( TC_paging_imsi_nochan_plmn_lac_rnc() );
12457 execute( TC_paging_imsi_nochan_rnc() );
12458 execute( TC_paging_imsi_nochan_lac_rnc() );
12459 execute( TC_paging_imsi_nochan_lacs() );
12460 execute( TC_paging_imsi_nochan_lacs_empty() );
Stefan Sperling049a86e2018-03-20 15:51:00 +010012461 execute( TC_paging_imsi_nochan_cgi_unknown_cid() );
Harald Welte10985002017-12-12 09:29:15 +010012462 execute( TC_paging_imsi_a_reset() );
Harald Weltee65d40e2017-12-13 00:09:06 +010012463 execute( TC_paging_imsi_load() );
Philipp Maier779a7922018-02-16 11:00:37 +010012464 execute( TC_paging_counter() );
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +010012465 execute( TC_paging_resp_unsol() );
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +020012466 execute( TC_paging_500req() );
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +020012467 execute( TC_paging_450req_no_paging_load_ind() );
Pau Espin Pedrol07657ae2023-01-03 12:08:05 +010012468 execute( TC_paging_imsi_nochan_ci_resp_invalid_mi() );
Harald Welte4e9b9cc2017-12-14 18:31:02 +010012469
12470 execute( TC_rsl_drop_counter() );
Stefan Sperling830dc9d2018-02-12 21:08:28 +010012471 execute( TC_rsl_unknown_unit_id() );
12472
12473 execute( TC_oml_unknown_unit_id() );
Harald Welte898113b2018-01-31 18:32:21 +010012474
12475 execute( TC_classmark() );
Harald Welteeddf0e92020-06-21 19:42:15 +020012476 execute( TC_common_id() );
Harald Welte898113b2018-01-31 18:32:21 +010012477 execute( TC_unsol_ass_fail() );
Harald Welteea99a002018-01-31 20:46:43 +010012478 execute( TC_unsol_ass_compl() );
Harald Weltefbf9b5e2018-01-31 20:41:23 +010012479 execute( TC_unsol_ho_fail() );
Harald Weltee3bd6582018-01-31 22:51:25 +010012480 execute( TC_err_82_short_msg() );
Harald Weltee9e02e42018-01-31 23:36:25 +010012481 execute( TC_err_84_unknown_msg() );
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012482
Harald Welte261af4b2018-02-12 21:20:39 +010012483 execute( TC_ho_int() );
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +020012484 execute( TC_ho_int_a5_0() );
12485 execute( TC_ho_int_a5_1() );
12486 execute( TC_ho_int_a5_3() );
12487 execute( TC_ho_int_a5_4() );
Neels Hofmeyr5f144212020-11-03 15:41:58 +000012488 execute( TC_ho_int_radio_link_failure() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012489
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012490 /* TC_ho_out_of_this_bsc is run last, see comment below */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +020012491 execute( TC_ho_out_fail_no_msc_response() );
12492 execute( TC_ho_out_fail_rr_ho_failure() );
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +020012493 execute( TC_ho_out_fail_no_result_after_ho_cmd() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012494
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012495 execute( TC_ho_into_this_bsc() );
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +020012496 execute( TC_ho_into_this_bsc_a5_0() );
12497 execute( TC_ho_into_this_bsc_a5_1() );
12498 execute( TC_ho_into_this_bsc_a5_3() );
12499 execute( TC_ho_into_this_bsc_a5_4() );
Neels Hofmeyr93182e02022-02-17 21:59:07 +010012500 execute( TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() );
12501 execute( TC_ho_into_this_bsc_a5_1_3() );
Neels Hofmeyr907b23b2022-02-17 21:58:47 +010012502 execute( TC_ho_into_this_bsc_a5_mismatch() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020012503 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12504 execute( TC_ho_into_this_bsc_tla_v6() );
12505 }
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +020012506 execute( TC_srvcc_eutran_to_geran() );
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +030012507 execute( TC_srvcc_eutran_to_geran_a5_3() );
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +010012508 execute( TC_srvcc_eutran_to_geran_src_sai() );
Pau Espin Pedrol35801c32021-04-19 13:03:20 +020012509 execute( TC_srvcc_eutran_to_geran_ho_out() );
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +020012510 execute( TC_srvcc_eutran_to_geran_forbid_fast_return() );
12511 execute( TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012512 execute( TC_ho_in_fail_msc_clears() );
12513 execute( TC_ho_in_fail_msc_clears_after_ho_detect() );
12514 execute( TC_ho_in_fail_no_detect() );
12515 execute( TC_ho_in_fail_no_detect2() );
Oliver Smith7a8594a2023-02-13 14:30:49 +010012516 execute( TC_ho_in_fail_mgw_mdcx_timeout() );
Oliver Smith4eed06f2023-02-15 15:43:19 +010012517 execute( TC_ho_in_fail_ipa_crcx_timeout() );
Neels Hofmeyra23f3b12022-03-02 19:57:12 +010012518 execute( TC_ho_into_this_bsc_sccp_cr_without_bssap() );
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012519
Neels Hofmeyr91401012019-07-11 00:42:35 +020012520 execute( TC_ho_neighbor_config_1() );
12521 execute( TC_ho_neighbor_config_2() );
12522 execute( TC_ho_neighbor_config_3() );
12523 execute( TC_ho_neighbor_config_4() );
12524 execute( TC_ho_neighbor_config_5() );
12525 execute( TC_ho_neighbor_config_6() );
12526 execute( TC_ho_neighbor_config_7() );
12527
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012528 execute( TC_bssap_rlsd_does_not_cause_bssmap_reset() );
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010012529 execute( TC_bssmap_clear_does_not_cause_bssmap_reset() );
Neels Hofmeyrfd445c32018-03-09 15:39:31 +010012530 execute( TC_ms_rel_ind_does_not_cause_bssmap_reset() );
Harald Welte94e0c342018-04-07 11:33:23 +020012531
12532 execute( TC_dyn_pdch_ipa_act_deact() );
12533 execute( TC_dyn_pdch_ipa_act_nack() );
12534 execute( TC_dyn_pdch_osmo_act_deact() );
12535 execute( TC_dyn_pdch_osmo_act_nack() );
Pau Espin Pedrol37a4c152021-11-16 19:02:23 +010012536 execute( TC_dyn_ts_sdcch8_act_deact() );
12537 execute( TC_dyn_ts_sdcch8_all_subslots_used() );
12538 execute( TC_dyn_ts_sdcch8_tch_call_act_deact() );
12539 execute( TC_dyn_ts_sdcch8_act_nack() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012540
Stefan Sperling0796a822018-10-05 13:01:39 +020012541 execute( TC_chopped_ipa_ping() );
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +020012542 execute( TC_chopped_ipa_payload() );
Stefan Sperling0796a822018-10-05 13:01:39 +020012543
Pau Espin Pedrol8f773632019-11-05 11:46:53 +010012544 /* Power control related */
12545 execute( TC_assignment_verify_ms_power_params_ie() );
Vadim Yanitskiy4b233042021-06-30 00:58:43 +020012546 execute( TC_c0_power_red_mode() );
Neels Hofmeyr4f118412020-06-04 15:25:10 +020012547
12548 /* MSC pooling */
12549 /* FIXME: in SCCPlite, indicating how many MSCs should be connected does currently not work. Since
12550 * RESET->RESET-ACK is unconditionally negotiated for all configured MSCs, they always all appear as connected
12551 * to osmo-bsc. The MSC pooling tests however require disconnecting selected MSCs, and hence don't work out as
12552 * intended on SCCPlite. So for now, run these only for SCCP/M3UA. */
12553 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12554 execute( TC_mscpool_L3Compl_on_1_msc() );
12555 execute( TC_mscpool_L3Complete_by_imsi_round_robin() );
12556 execute( TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() );
12557 execute( TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() );
12558 execute( TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() );
12559 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() );
12560 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_1() );
12561 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_2() );
12562 execute( TC_mscpool_LU_by_tmsi_from_other_PLMN() );
12563 execute( TC_mscpool_paging_and_response_imsi() );
12564 execute( TC_mscpool_paging_and_response_tmsi() );
12565 execute( TC_mscpool_no_allow_attach_round_robin() );
12566 execute( TC_mscpool_no_allow_attach_valid_nri() );
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +020012567
12568 execute( TC_mscpool_sccp_n_pcstate_detaches_msc() );
Neels Hofmeyr38632aa2023-04-05 03:50:51 +020012569 execute( TC_mscpool_sccp_n_pcstate_attaches_msc() );
Neels Hofmeyr4f118412020-06-04 15:25:10 +020012570 }
12571
Harald Welte99f3ca02018-06-14 13:40:29 +020012572 execute( TC_early_conn_fail() );
12573 execute( TC_late_conn_fail() );
Oliver Smithaf03bef2021-08-24 15:34:51 +020012574 execute( TC_stats_conn_fail() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012575
Philipp Maier783681c2020-07-16 16:47:06 +020012576 /* Emergency call handling (deny / allow) */
12577 execute( TC_assignment_emerg_setup_allow() );
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +010012578 execute( TC_assignment_emerg_setup_allow_imei() );
Philipp Maier783681c2020-07-16 16:47:06 +020012579 execute( TC_assignment_emerg_setup_deny_msc() );
12580 execute( TC_assignment_emerg_setup_deny_bts() );
Philipp Maier82812002020-08-13 18:48:27 +020012581 execute( TC_emerg_premption() );
12582
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +070012583 /* Frequency hopping parameters handling */
12584 execute( TC_fh_params_chan_activ() );
12585 execute( TC_fh_params_imm_ass() );
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070012586 execute( TC_fh_params_assignment_cmd() );
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070012587 execute( TC_fh_params_handover_cmd() );
Vadim Yanitskiyca974032020-09-01 07:20:39 +070012588 execute( TC_fh_params_si4_cbch() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012589
12590 if (mp_enable_lcs_tests) {
12591 execute( TC_lcs_loc_req_for_active_ms() );
12592 execute( TC_lcs_loc_req_for_active_ms_ta_req() );
12593 execute( TC_lcs_loc_req_for_idle_ms() );
12594 execute( TC_lcs_loc_req_no_subscriber() );
12595 execute( TC_lcs_loc_req_for_active_ms_le_timeout() );
12596 execute( TC_lcs_loc_req_for_active_ms_le_timeout2() );
12597 execute( TC_lcs_loc_req_for_idle_ms_no_pag_resp() );
12598 execute( TC_cm_service_during_lcs_loc_req() );
12599 execute( TC_ho_during_lcs_loc_req() );
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020012600 execute( TC_emerg_call_and_lcs_loc_req() );
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020012601 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() );
12602 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012603 }
Neels Hofmeyrbf037052020-10-28 22:52:02 +000012604
12605 execute( TC_no_msc() );
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000012606
12607 execute( TC_refuse_chan_act_to_vamos() );
12608 execute( TC_refuse_mode_modif_to_vamos() );
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000012609
12610 execute( TC_reassignment_fr() );
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020012611
12612 execute( TC_cm_reestablishment() );
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020012613
12614 execute( TC_imm_ass_post_chan_ack() );
12615 execute( TC_imm_ass_pre_chan_ack() );
Neels Hofmeyr23158742021-09-07 19:08:07 +020012616 execute( TC_imm_ass_pre_ts_ack() );
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020012617 execute( TC_imm_ass_pre_chan_ack_dyn_ts() );
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020012618 execute( TC_imm_ass_pre_ts_ack_dyn_ts() );
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020012619
12620 execute( TC_ctrl_trx_rf_locked() );
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012621
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020012622 execute( TC_ratectr_all_available_allocated() );
12623 execute( TC_ratectr_all_available_allocated_dyn() );
12624
Neels Hofmeyrb7581872021-11-07 14:02:49 +010012625 execute( TC_cm_serv_rej() );
12626
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012627 execute( TC_lost_sdcch_during_assignment() );
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012628
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012629 /* Channel allocator */
12630 execute( TC_chan_alloc_algo_ascending() );
12631 execute( TC_chan_alloc_algo_descending() );
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012632 execute( TC_chan_alloc_algo_ass_dynamic() );
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012633
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012634 /* MGW pool */
Pau Espin Pedrol4e431832023-02-08 12:43:47 +010012635 execute( TC_mgwpool_all_used() );
12636 execute( TC_mgwpool_blocked_not_used() );
12637 execute( TC_mgwpool_pin_bts() );
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012638
Oliver Smithc9a5f532022-10-21 11:32:23 +020012639 execute( TC_ho_meas_rep_multi_band() );
12640
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012641 /* Run TC_ho_out_of_this_bsc last, because it may trigger a segfault before osmo-bsc's patch
12642 * with change-id I5a3345ab0005a73597f5c27207480912a2f5aae6 */
12643 execute( TC_ho_out_of_this_bsc() );
Harald Welte28d943e2017-11-25 15:00:50 +010012644}
12645
12646}