blob: 5a22c00a3337ae4e6a1c2cfabd41e01fcd5094a8 [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
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200649 /* Osmux is enabled through VTY */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200650 var boolean g_osmux_enabled_cn := false;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +0200651 var boolean g_osmux_enabled_bts := false;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200652
Pau Espin Pedrolc675b612020-01-09 19:55:40 +0100653 /*Configure T(tias) over VTY, seconds */
654 var integer g_bsc_sccp_timer_ias := 7 * 60;
655 /*Configure T(tiar) over VTY, seconds */
656 var integer g_bsc_sccp_timer_iar := 15 * 60;
657
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +0200658 /* global test case guard timer (actual timeout value is set in f_init()) */
Harald Welteae026692017-12-09 01:03:01 +0100659 timer T_guard := 30.0;
660
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200661 var CounterNameValsList g_ctr_msc;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000662 var CounterNameValsList g_ctr_bsc;
663 var CounterNameValsList g_ctr_bts;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200664
665 /* System Information bytes as received during RSL startup, for each RSL[idx]. */
666 var SystemInformationConfig_list g_system_information := {};
Harald Welte28d943e2017-11-25 15:00:50 +0100667}
668
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200669type record of charstring phys_chan_configs;
Harald Welte28d943e2017-11-25 15:00:50 +0100670modulepar {
Harald Welte21b46bd2017-12-17 19:46:32 +0100671 /* IP address at which the BSC can be reached */
Harald Welte696ddb62017-12-08 14:01:43 +0100672 charstring mp_bsc_ip := "127.0.0.1";
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100673 /* port number to which to establish the IPA OML connections */
674 integer mp_bsc_oml_port := 3002;
Harald Welte21b46bd2017-12-17 19:46:32 +0100675 /* port number to which to establish the IPA RSL connections */
Harald Welte696ddb62017-12-08 14:01:43 +0100676 integer mp_bsc_rsl_port := 3003;
Harald Welte21b46bd2017-12-17 19:46:32 +0100677 /* port number to which to establish the IPA CTRL connection */
Harald Welte96c94412017-12-09 03:12:45 +0100678 integer mp_bsc_ctrl_port := 4249;
Daniel Willmannebdecc02020-08-12 15:30:17 +0200679 /* port number to which to listen for STATSD metrics */
680 integer mp_bsc_statsd_port := 8125;
Daniel Willmann191e0d92018-01-17 12:44:35 +0100681 /* IP address at which the test binds */
682 charstring mp_test_ip := "127.0.0.1";
Harald Weltea4ca4462018-02-09 00:17:14 +0100683
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200684 RAN_Configurations mp_bssap_cfg := {
685 {
686 transport := BSSAP_TRANSPORT_AoIP,
687 sccp_service_type := "mtp3_itu",
688 sctp_addr := { 23905, "127.0.0.1", 2905, "127.0.0.1" },
689 own_pc := 185, /* 0.23.1 first MSC emulation */
690 own_ssn := 254,
691 peer_pc := 187, /* 0.23.3 osmo-bsc */
692 peer_ssn := 254,
693 sio := '83'O,
Harald Weltecb0cc432020-06-21 19:42:31 +0200694 rctx := 1
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200695 },
696 {
697 transport := BSSAP_TRANSPORT_AoIP,
698 sccp_service_type := "mtp3_itu",
699 sctp_addr := { 23906, "127.0.0.1", 2905, "127.0.0.1" },
700 own_pc := 2, /* 0.0.2 second MSC emulation */
701 own_ssn := 254,
702 peer_pc := 187, /* 0.23.3 osmo-bsc */
703 peer_ssn := 254,
704 sio := '83'O,
705 rctx := 2
706 },
707 {
708 transport := BSSAP_TRANSPORT_AoIP,
709 sccp_service_type := "mtp3_itu",
710 sctp_addr := { 23907, "127.0.0.1", 2905, "127.0.0.1" },
711 own_pc := 3, /* 0.0.3 third MSC emulation */
712 own_ssn := 254,
713 peer_pc := 187, /* 0.23.3 osmo-bsc */
714 peer_ssn := 254,
715 sio := '83'O,
716 rctx := 3
717 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100718 };
Pau Espin Pedrol58cf6822019-05-28 18:11:33 +0200719
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200720 /* Must match per BTS config in osmo-bsc.cfg */
721 phys_chan_configs phys_chan_config := {
722 "CCCH+SDCCH4+CBCH",
723 "TCH/F",
724 "TCH/F",
725 "TCH/F",
726 "TCH/F",
Vadim Yanitskiy343c9eb2021-07-16 18:36:01 +0600727 "TCH/H",
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200728 "PDCH",
729 "PDCH"
730 };
731
Harald Welte47cd0e32020-08-21 12:39:11 +0200732 BSSAP_LE_Configuration mp_bssap_le_cfg := {
733 sccp_service_type := "mtp3_itu",
734 sctp_addr := { 23908, "127.0.0.1", 2905, "127.0.0.1" },
Neels Hofmeyrac086c12020-09-18 23:46:42 +0200735 own_pc := 190, /* 0.23.6 SMLC emulation */
Harald Welte47cd0e32020-08-21 12:39:11 +0200736 own_ssn := 252, /* SMLC side SSN */
737 peer_pc := 187, /* 0.23.3 osmo-bsc */
738 peer_ssn := 250, /* BSC side SSN */
739 sio := '83'O,
740 rctx := 6
741 };
Neels Hofmeyrcfe44062020-10-15 02:28:08 +0200742 boolean mp_enable_lcs_tests := true;
Harald Welte47cd0e32020-08-21 12:39:11 +0200743
Pau Espin Pedrol8f30ccd2019-11-01 17:30:57 +0100744 /* Value set in osmo-bsc.cfg "ms max power" */
745 uint8_t mp_exp_ms_power_level := 7;
Vadim Yanitskiy6e068012022-02-05 21:35:43 +0600746
747 /* Whether to check for memory leaks */
748 boolean mp_verify_talloc_count := true;
Harald Weltea4ca4462018-02-09 00:17:14 +0100749}
750
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200751friend function f_gen_test_hdlr_pars(integer bssap_idx := 0) return TestHdlrParams {
Philipp Maier48604732018-10-09 15:00:37 +0200752
753 var TestHdlrParams pars := valueof(t_def_TestHdlrPars);
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200754 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier48604732018-10-09 15:00:37 +0200755 pars.aoip := true;
756 } else {
757 pars.aoip := false;
758 }
Pau Espin Pedrol8f30ccd2019-11-01 17:30:57 +0100759 pars.exp_ms_power_level := mp_exp_ms_power_level;
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200760 pars.mscpool.bssap_idx := bssap_idx;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600761 pars.expect_tsc := c_BtsParams[0].tsc;
Vadim Yanitskiy96bb9cb2021-12-10 21:14:15 +0300762 pars.imsi := f_rnd_imsi('00101'H);
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +0100763 pars.imei := f_rnd_imei('00101'H);
Vadim Yanitskiy96bb9cb2021-12-10 21:14:15 +0300764
765 log(testcasename(), ": using IMSI ", pars.imsi);
Neels Hofmeyrb5b7a6e2021-06-04 19:03:45 +0200766
Philipp Maier48604732018-10-09 15:00:37 +0200767 return pars;
768}
769
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200770/* Convenience functions for rate counters using g_ctr_msc. */
771
772private function f_ctrs_msc_init(integer mscs_count := NUM_MSC, CounterNameVals counternames := counternames_msc_mscpool) runs on test_CT {
773 g_ctr_msc := f_counter_name_vals_get_n(IPA_CTRL, "msc", mscs_count, counternames);
774 log("initial msc rate counters: ", g_ctr_msc);
775}
776
777private function f_ctrs_msc_add(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
Neels Hofmeyr9656e922020-06-30 01:27:01 +0200778 f_counter_name_vals_list_add(g_ctr_msc, msc_nr, countername, val);
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200779}
780
781/* f_ctrs_msc_init();
782 * f_do_thing(on_msc := 0);
783 * f_do_thing(on_msc := 0);
784 * f_do_other(on_msc := 1);
785 * f_ctrs_msc_add(0, "thing", 2);
786 * f_ctrs_msc_add(1, "other");
787 * f_ctrs_msc_verify();
788 */
789private function f_ctrs_msc_verify() runs on test_CT {
790 log("verifying msc rate counters: ", g_ctr_msc);
791 f_counter_name_vals_expect_n(IPA_CTRL, "msc", g_ctr_msc);
792}
793
794/* convenience: f_ctrs_msc_add() and f_ctrs_msc_verify() in one call.
795 * f_ctrs_msc_init();
796 * f_do_thing(on_msc := 0);
797 * f_do_thing(on_msc := 0);
798 * f_do_thing(on_msc := 0);
799 * f_ctrs_msc_expect(0, "thing", 3);
800 */
801private function f_ctrs_msc_expect(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
802 f_ctrs_msc_add(msc_nr, countername, val);
803 f_ctrs_msc_verify();
804}
805
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000806/* Convenience functions for rate counters using g_ctr_bts, always also including g_ctr_bsc. */
807
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100808private 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 +0000809 g_ctr_bts := f_counter_name_vals_get_n(IPA_CTRL, "bts", bts_count, counternames);
Neels Hofmeyr4dec8cc2021-11-29 15:59:44 +0100810 log("initial bts rate counters: ", g_ctr_bts);
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100811}
812
813function f_ctrs_bsc_and_bts_init(integer bts_count := NUM_BTS, CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
814 f_ctrs_bts_init(bts_count, counternames);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000815 f_ctrs_bsc_init(counternames);
816}
817
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100818private function f_ctrs_bsc_and_bts_handover_init(integer bts_count := NUM_BTS) runs on test_CT {
819 var CounterNameVals bts_names := counternames_bsc_bts_handover & counternames_bts_handover;
Neels Hofmeyr4dec8cc2021-11-29 15:59:44 +0100820 f_ctrs_bts_init(bts_count, bts_names);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100821 f_ctrs_bsc_init(counternames_bsc_bts_handover);
822}
823
824private function f_ctrs_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000825 f_counter_name_vals_list_add(g_ctr_bts, bts_nr, countername, val);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100826}
827
828private function f_ctrs_bsc_and_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
829 f_ctrs_bts_add(bts_nr, countername, val);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000830 f_ctrs_bsc_add(countername, val);
831}
832
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100833function f_ctrs_bts_verify() runs on test_CT {
834 f_counter_name_vals_expect_n(IPA_CTRL, "bts", g_ctr_bts);
835}
836
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000837/* f_ctrs_bsc_and_bts_init();
838 * f_do_thing(on_bts := 0);
839 * f_do_thing(on_bts := 0);
840 * f_do_other(on_bts := 1);
841 * f_ctrs_bsc_and_bts_add(0, "thing", 2);
842 * f_ctrs_bsc_and_bts_add(1, "other");
843 * f_ctrs_bsc_and_bts_verify();
844 */
845private function f_ctrs_bsc_and_bts_verify() runs on test_CT {
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100846 f_ctrs_bts_verify();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000847 f_ctrs_bsc_verify();
848}
849
850/* convenience: f_ctrs_bsc_and_bts_add() and f_ctrs_bsc_and_bts_verify() in one call.
851 * f_ctrs_bsc_and_bts_init();
852 * f_do_thing(on_bts := 0);
853 * f_do_thing(on_bts := 0);
854 * f_do_thing(on_bts := 0);
855 * f_ctrs_bsc_and_bts_expect(0, "thing", 3);
856 */
857private function f_ctrs_bsc_and_bts_expect(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
858 f_ctrs_bsc_and_bts_add(bts_nr, countername, val);
859 f_ctrs_bsc_and_bts_verify();
860}
861
862
863/* Convenience functions for rate counters using g_ctr_bsc. */
864
865private function f_ctrs_bsc_init(CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
866 g_ctr_bsc := f_counter_name_vals_get_n(IPA_CTRL, "bsc", 1, counternames);
867 log("initial bsc rate counters: ", g_ctr_bsc);
868}
869
870private function f_ctrs_bsc_add(charstring countername, integer val := 1) runs on test_CT {
871 f_counter_name_vals_list_add(g_ctr_bsc, 0, countername, val);
872}
873
874/* f_ctrs_bsc_init();
875 * f_do_thing();
876 * f_do_thing();
877 * f_do_other();
878 * f_ctrs_bsc_add("thing", 2);
879 * f_ctrs_bsc_add("other");
880 * f_ctrs_bsc_verify();
881 */
882private function f_ctrs_bsc_verify() runs on test_CT {
883 f_counter_name_vals_expect_n(IPA_CTRL, "bsc", g_ctr_bsc);
884}
885
886/* convenience: f_ctrs_bsc_add() and f_ctrs_bsc_verify() in one call.
887 * f_ctrs_bsc_init();
888 * f_do_thing();
889 * f_ctrs_bsc_expect("thing", 1);
890 */
891private function f_ctrs_bsc_expect(charstring countername, integer val := 1) runs on test_CT {
892 f_ctrs_bsc_add(countername, val);
893 f_ctrs_bsc_verify();
894}
895
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200896
Oliver Smith39f53072022-10-27 14:44:04 +0200897friend function f_shutdown_helper(boolean ho := false) runs on test_CT {
Neels Hofmeyr18997492021-12-13 17:30:35 +0100898 /* Run the subscr and conn leak test only when the VTY is initialized */
Vadim Yanitskiy6e068012022-02-05 21:35:43 +0600899 if (BSCVTY.checkstate("Mapped") and mp_verify_talloc_count) {
Neels Hofmeyr18997492021-12-13 17:30:35 +0100900 f_verify_talloc_count(BSCVTY, {"struct bsc_subscr", "struct gsm_subscriber_connection"});
901 }
902
Oliver Smith39f53072022-10-27 14:44:04 +0200903 /* Reset handover related configuration */
904 if (ho) {
905 f_bts_0_cfg(BSCVTY,
906 {"no neighbors",
907 "neighbor-list mode manual-si5",
908 "neighbor-list add arfcn 100",
909 "neighbor-list add arfcn 200",
910 "si5 neighbor-list add arfcn 10",
911 "si5 neighbor-list add arfcn 20",
912 "handover algorithm 1"});
913 }
914
Daniel Willmann637ef6c2018-07-25 10:49:09 +0200915 all component.stop;
Philipp Maier282ca4b2018-02-27 17:17:00 +0100916 setverdict(pass);
Daniel Willmannafce8662018-07-06 23:11:32 +0200917 mtc.stop;
Philipp Maier282ca4b2018-02-27 17:17:00 +0100918}
919
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200920private function f_legacy_bssap_reset(integer bssap_idx := 0) runs on test_CT {
Harald Weltea4ca4462018-02-09 00:17:14 +0100921 var BSSAP_N_UNITDATA_ind ud_ind;
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200922 var boolean reset_received := false;
Harald Weltea4ca4462018-02-09 00:17:14 +0100923 timer T := 5.0;
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200924 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 +0200925 ts_BSSMAP_Reset(0, g_osmux_enabled_cn)));
Harald Weltea4ca4462018-02-09 00:17:14 +0100926 T.start;
927 alt {
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200928 [] 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 +0200929 tr_BSSMAP_ResetAck(g_osmux_enabled_cn))) {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200930 log("BSSMAP: Received RESET-ACK in response to RESET, we're ready to go!");
Harald Weltea4ca4462018-02-09 00:17:14 +0100931 }
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200932 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) -> value ud_ind {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200933 log("BSSMAP: Respoding to inbound RESET with RESET-ACK");
Harald Weltea4ca4462018-02-09 00:17:14 +0100934 BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200935 ts_BSSMAP_ResetAck(g_osmux_enabled_cn)));
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200936 reset_received := true;
Harald Weltea4ca4462018-02-09 00:17:14 +0100937 repeat;
938 }
939 [] BSSAP.receive { repeat; }
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200940 [] T.timeout {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200941 log("BSSMAP: Timeout waiting for RESET-ACK after sending RESET");
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200942 /* If we received a RESET after ours was sent, it
943 may be a race condition where the other peer beacame
944 available after we sent it, but we are in a desired
945 state anyway, so go forward. */
946 if (not reset_received) {
947 setverdict(fail);
948 }
949 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100950 }
Harald Welte28d943e2017-11-25 15:00:50 +0100951}
952
Harald Welteae026692017-12-09 01:03:01 +0100953type record IPA_Client {
Harald Welte21b46bd2017-12-17 19:46:32 +0100954 /* IPA Emulation component reference */
Harald Welteae026692017-12-09 01:03:01 +0100955 IPA_Emulation_CT vc_IPA,
Harald Welte21b46bd2017-12-17 19:46:32 +0100956 /* Unit-ID and other CCM parameters to use for IPA client emulation */
Harald Welteae026692017-12-09 01:03:01 +0100957 IPA_CCM_Parameters ccm_pars,
Harald Welte21b46bd2017-12-17 19:46:32 +0100958 /* String identifier for this IPA Client */
Harald Welte624f9632017-12-16 19:26:04 +0100959 charstring id,
Harald Welte21b46bd2017-12-17 19:46:32 +0100960 /* Associated RSL Emulation Component (if any). Only used in "Handler mode" */
Harald Welte624f9632017-12-16 19:26:04 +0100961 RSL_Emulation_CT vc_RSL optional
Harald Welte28d943e2017-11-25 15:00:50 +0100962}
963
Harald Welte21b46bd2017-12-17 19:46:32 +0100964/*! Start the IPA/RSL related bits for one IPA_Client.
965 * \param clnt IPA_Client for which to establish
966 * \param bsc_host IP address / hostname of the BSC
967 * \param bsc_port TCP port number of the BSC
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600968 * \param idx BTS/TRX index values
Harald Welte21b46bd2017-12-17 19:46:32 +0100969 * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600970function f_ipa_rsl_start(inout IPA_Client clnt, charstring bsc_host, PortNumber bsc_port,
971 BtsTrxIdx idx := {0, 0}, boolean handler_mode := false)
Harald Welte28d943e2017-11-25 15:00:50 +0100972runs on test_CT {
Harald Welteae026692017-12-09 01:03:01 +0100973 timer T := 10.0;
974
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600975 clnt.id := "IPA-BTS" & int2str(idx.bts) & "-TRX" & int2str(idx.trx) & "-RSL";
Harald Welte71389132021-12-09 21:58:18 +0100976 clnt.vc_IPA := IPA_Emulation_CT.create(clnt.id & "-IPA") alive;
Harald Welteae026692017-12-09 01:03:01 +0100977 clnt.ccm_pars := c_IPA_default_ccm_pars;
978 clnt.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600979 clnt.ccm_pars.unit_id := int2str(1234 + idx.bts) & "/0/" & int2str(idx.trx);
Harald Welte624f9632017-12-16 19:26:04 +0100980 if (handler_mode) {
Harald Welte71389132021-12-09 21:58:18 +0100981 clnt.vc_RSL := RSL_Emulation_CT.create(clnt.id & "-RSL") alive;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600982 connect(clnt.vc_RSL:CCHAN_PT, self:RSL_CCHAN[idx.bts]);
Harald Welte624f9632017-12-16 19:26:04 +0100983 }
Harald Welteae026692017-12-09 01:03:01 +0100984
985 map(clnt.vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +0200986 connect(clnt.vc_IPA:CFG_PORT, self:IPA_CFG_PORT[idx.bts][idx.trx]);
Harald Welte624f9632017-12-16 19:26:04 +0100987 if (handler_mode) {
988 connect(clnt.vc_IPA:IPA_RSL_PORT, clnt.vc_RSL:IPA_PT);
989 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600990 connect(clnt.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[idx.bts][idx.trx]);
Harald Welte624f9632017-12-16 19:26:04 +0100991 }
Harald Welteae026692017-12-09 01:03:01 +0100992
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600993 var integer local_port := 10000 + idx.bts * 1000 + idx.trx;
994 clnt.vc_IPA.start(IPA_Emulation.main_client(bsc_host, bsc_port, "", local_port, clnt.ccm_pars));
Harald Welte624f9632017-12-16 19:26:04 +0100995 if (handler_mode) {
996 clnt.vc_RSL.start(RSL_Emulation.main());
997 return;
998 }
Harald Welteae026692017-12-09 01:03:01 +0100999
1000 /* wait for IPA RSL link to connect and send ID ACK */
1001 T.start;
1002 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001003 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK)) {
Harald Welteae026692017-12-09 01:03:01 +01001004 T.stop;
Harald Welteae026692017-12-09 01:03:01 +01001005 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001006 [] IPA_RSL[idx.bts][idx.trx].receive(ASP_IPA_Event:?) { repeat }
1007 [] IPA_RSL[idx.bts][idx.trx].receive { repeat }
Harald Welteae026692017-12-09 01:03:01 +01001008 [] T.timeout {
Harald Welte96c94412017-12-09 03:12:45 +01001009 setverdict(fail, "Timeout RSL waiting for ASP_IPA_EVENT_ID_ACK");
Daniel Willmannafce8662018-07-06 23:11:32 +02001010 mtc.stop;
Harald Welteae026692017-12-09 01:03:01 +01001011 }
1012 }
1013}
1014
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +02001015function f_ipa_rsl_stop(inout IPA_Client clnt, BtsTrxIdx idx := {0, 0}) runs on test_CT {
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001016 var IPL4asp_Types.Result res := {
1017 errorCode := omit,
1018 connId := omit,
1019 os_error_code := omit,
1020 os_error_text := omit
1021 };
1022
Harald Welte12055472018-03-17 20:10:08 +01001023 if (not isbound(clnt) or not isbound(clnt.vc_IPA)) {
1024 return;
1025 }
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001026
1027 /* Alive components don't finish sockets (TCP FIN) when they are
1028 * stopped. Hence, we need to manually call close() on them to make sure
1029 * the IUT knows about it. */
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +02001030 f_ipa_cfg_disconnect(IPA_CFG_PORT[idx.bts][idx.trx], res);
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001031
Harald Welte12055472018-03-17 20:10:08 +01001032 clnt.vc_IPA.stop;
1033 if (isbound(clnt.vc_RSL)) {
1034 clnt.vc_RSL.stop;
1035 }
1036}
1037
Harald Welte21b46bd2017-12-17 19:46:32 +01001038/* Wait for the OML connection to be brought up by the external osmo-bts-omldummy */
Harald Weltea5d2ab22017-12-09 14:21:42 +01001039function f_wait_oml(integer bts_nr, charstring status, float secs_max) runs on test_CT {
1040 timer T := secs_max;
1041 T.start;
1042 while (true) {
1043 if (f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-connection-state") == status) {
1044 T.stop;
Harald Weltebd868bd2017-12-10 18:28:40 +01001045 /* the 'degraded' state exists from OML connection time, and we have to wait
1046 * until all MO's are initialized */
1047 T.start(1.0);
1048 T.timeout;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001049 return;
1050 }
Harald Weltef0d6ac62017-12-17 17:02:21 +01001051 f_sleep(0.1);
Harald Weltea5d2ab22017-12-09 14:21:42 +01001052 if (not T.running) {
Max99253902018-11-16 17:57:39 +01001053 setverdict(fail, "Timeout waiting for BTS" & int2str(bts_nr) & " oml-connection-state ", status);
Daniel Willmannafce8662018-07-06 23:11:32 +02001054 mtc.stop;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001055 }
1056 }
1057}
1058
Harald Welte21b46bd2017-12-17 19:46:32 +01001059/* global altstep for global guard timer; also takes care of responding RESET witH RESET-ACK */
Harald Welteae026692017-12-09 01:03:01 +01001060altstep as_Tguard() runs on test_CT {
Harald Welte60e823a2017-12-10 14:10:59 +01001061 var BSSAP_N_UNITDATA_ind ud_ind;
Neels Hofmeyrcc3f76a2018-03-12 01:43:25 +01001062 [] T_guard.timeout {
1063 setverdict(fail, "Timeout of T_guard");
Daniel Willmannafce8662018-07-06 23:11:32 +02001064 mtc.stop;
Neels Hofmeyrcc3f76a2018-03-12 01:43:25 +01001065 }
Harald Welte60e823a2017-12-10 14:10:59 +01001066 /* always respond with RESET ACK to RESET */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001067 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) -> value ud_ind {
Harald Welte60e823a2017-12-10 14:10:59 +01001068 BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001069 ts_BSSMAP_ResetAck(g_osmux_enabled_cn)));
Harald Welte69c1c262017-12-13 21:02:08 +01001070 repeat;
Harald Welte60e823a2017-12-10 14:10:59 +01001071 }
Harald Welte28d943e2017-11-25 15:00:50 +01001072}
1073
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001074altstep no_bssmap_reset() runs on test_CT {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001075 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001076 setverdict(fail, "unexpected BSSMAP Reset");
Daniel Willmannafce8662018-07-06 23:11:32 +02001077 mtc.stop;
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001078 }
1079}
1080
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001081function f_init_mgcp(integer mgw_nr, charstring id) runs on test_CT {
1082 id := id & "-MGCP-" & int2str(mgw_nr);
Daniel Willmann191e0d92018-01-17 12:44:35 +01001083
1084 var MGCPOps ops := {
1085 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
1086 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
1087 };
1088 var MGCP_conn_parameters mgcp_pars := {
1089 callagent_ip := mp_bsc_ip,
Harald Welte9e4273e2018-01-29 22:01:22 +01001090 callagent_udp_port := -1,
Daniel Willmann191e0d92018-01-17 12:44:35 +01001091 mgw_ip := mp_test_ip,
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001092 mgw_udp_port := 2427 + mgw_nr,
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02001093 /* Enable it for SCCPlite, since we have 2 MGCP sockets towards MGW (UDP one +
Pau Espin Pedrol36eeaf72022-10-20 16:50:31 +02001094 the one with MGCP over IPA forwarded from MSC one) */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001095 multi_conn_mode := (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER)
Daniel Willmann191e0d92018-01-17 12:44:35 +01001096 };
1097
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001098 vc_MGCP[mgw_nr] := MGCP_Emulation_CT.create(id) alive;
1099 vc_MGCP[mgw_nr].start(MGCP_Emulation.main(ops, mgcp_pars, id));
Daniel Willmann191e0d92018-01-17 12:44:35 +01001100}
1101
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001102/* Enable or disable (current default) Osmux. When enabling, BSSMAP Reset
1103 * contains extra IE (OsmuxSupport) and osmo-bsc will handle AssignReq with
1104 * OsmuxCID IE.
1105 */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001106private function f_vty_allow_osmux_cn(boolean allow) runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001107 f_vty_enter_cfg_msc(BSCVTY, 0);
1108 if (allow) {
1109 f_vty_transceive(BSCVTY, "osmux on");
1110 } else {
1111 f_vty_transceive(BSCVTY, "osmux off");
1112 }
1113 f_vty_transceive(BSCVTY, "exit");
1114 f_vty_transceive(BSCVTY, "exit");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001115}
1116
Max2253c0b2018-11-06 19:28:05 +01001117function f_init_vty(charstring id := "foo") runs on test_CT {
Harald Welte94e0c342018-04-07 11:33:23 +02001118 if (BSCVTY.checkstate("Mapped")) {
1119 /* skip initialization if already executed once */
1120 return;
1121 }
Harald Weltebc03c762018-02-12 18:09:38 +01001122 map(self:BSCVTY, system:BSCVTY);
1123 f_vty_set_prompts(BSCVTY);
1124 f_vty_transceive(BSCVTY, "enable");
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01001125 f_cs7_inst_0_cfg(BSCVTY, {"sccp-timer ias " & int2str(g_bsc_sccp_timer_ias),
1126 "sccp-timer iar " & int2str(g_bsc_sccp_timer_iar)});
Harald Weltebc03c762018-02-12 18:09:38 +01001127}
1128
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +02001129friend function f_logp(TELNETasp_PT pt, charstring log_msg)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02001130{
1131 // log on TTCN3 log output
1132 log(log_msg);
1133 // log in stderr log
Neels Hofmeyr8bdafe52021-12-14 17:25:48 +01001134 if (pt.checkstate("Mapped")) {
1135 f_vty_transceive(pt, "logp lglobal notice TTCN3 f_logp(): " & log_msg);
1136 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02001137}
1138
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001139private function f_sysinfo_seen(integer rsl_idx, RSL_Message rsl) runs on test_CT
1140{
1141 if (rsl_idx >= lengthof(g_system_information)) {
1142 g_system_information[rsl_idx] := SystemInformationConfig_omit
1143 }
1144 f_sysinfo_dec_raw(g_system_information[rsl_idx], rsl);
1145}
1146
1147altstep as_catch_RSL_sysinfo(integer rsl_idx) runs on test_CT {
1148 var ASP_RSL_Unitdata rx_rsl_ud;
1149
1150 /* For handler_mode := false, receiving the RSL bootstrap messages directly on IPA_RSL */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001151 [] 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 +02001152 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1153 repeat;
1154 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001155 [] 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 +02001156 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1157 repeat;
1158 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001159 [] 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 +02001160 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1161 repeat;
1162 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001163 [] 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 +02001164 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1165 repeat;
1166 }
1167
1168 /* For handler_mode := true, receiving the RSL bootstrap messages via RSL_Emulation */
1169 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_BCCH_INFO)) -> value rx_rsl_ud {
1170 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1171 repeat;
1172 }
1173 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO)) -> value rx_rsl_ud {
1174 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1175 repeat;
1176 }
1177 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_SACCH_FILL)) -> value rx_rsl_ud {
1178 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1179 repeat;
1180 }
1181 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_SACCH_FILL)) -> value rx_rsl_ud {
1182 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1183 repeat;
1184 }
1185}
1186
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001187/* TODO: use BooleanList from COMMON/src/General_Types.ttcn */
1188private type record of boolean my_BooleanList;
1189
1190private function f_vty_msc_allow_attach(TELNETasp_PT pt, my_BooleanList allow_attach_list)
1191{
Neels Hofmeyr8f576712020-08-12 22:49:53 +00001192 var charstring config := f_vty_transceive_ret(pt, "show running-config");
1193
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001194 for (var integer msc_nr := 0; msc_nr < sizeof(allow_attach_list); msc_nr := msc_nr+1) {
Neels Hofmeyr8f576712020-08-12 22:49:53 +00001195 if (f_strstr(config, "\nmsc " & int2str(msc_nr) & "\n") < 0) {
1196 /* There is no 'msc N' for this msc_nr in the running config, so don't create an empty msc by
1197 * stepping into that config node. */
1198 log("msc ", msc_nr, " is not configured, skipping");
1199 continue;
1200 }
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001201 f_vty_enter_cfg_msc(pt, msc_nr);
1202 if (allow_attach_list[msc_nr]) {
1203 /* strict := false: ignore if osmo-bsc does not support this config option (latest build) */
1204 f_vty_transceive(pt, "allow-attach", strict := false);
1205 } else {
1206 f_vty_transceive(pt, "no allow-attach", strict := false);
1207 }
1208 f_vty_transceive(pt, "exit");
1209 f_vty_transceive(pt, "exit");
1210 }
1211}
1212
Harald Welte21b46bd2017-12-17 19:46:32 +01001213/* global initialization function
1214 * \param nr_bts Number of BTSs we should start/bring up
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001215 * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false).
1216 * \param nr_msc Number of virtual MSCs to bring up to connect to osmo-bsc.
1217 */
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02001218function f_init(integer nr_bts := NUM_BTS, boolean handler_mode := false,
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001219 integer nr_msc := 1, integer nr_mgw := 1, float guard_timeout := 30.0) runs on test_CT {
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001220 var integer bssap_idx;
Harald Welte28d943e2017-11-25 15:00:50 +01001221
Harald Welteae026692017-12-09 01:03:01 +01001222 if (g_initialized) {
1223 return;
Harald Welte28d943e2017-11-25 15:00:50 +01001224 }
Harald Welteae026692017-12-09 01:03:01 +01001225 g_initialized := true;
1226
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +02001227 T_guard.start(guard_timeout);
Daniel Willmanne68f9272018-11-27 15:15:28 +01001228 activate(as_Tguard());
1229
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001230 f_init_vty("VirtMSC");
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02001231 f_vty_allow_osmux_cn(g_osmux_enabled_cn);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001232
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001233 var my_BooleanList allow_attach := { false, false, false };
Daniel Willmannebdecc02020-08-12 15:30:17 +02001234 f_init_statsd("VirtMSC", vc_STATSD, mp_test_ip, mp_bsc_statsd_port);
1235
Neels Hofmeyr9db8e0e2021-08-23 20:45:58 +02001236 /* Make sure each MSC's internal state is "DISCONNECTED" at first */
1237 for (bssap_idx := 0; bssap_idx < NUM_MSC; bssap_idx := bssap_idx+1) {
1238 f_vty_transceive(BSCVTY, "msc " & int2str(bssap_idx) & " bssmap reset", strict := false);
1239 }
1240
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001241 for (bssap_idx := 0; bssap_idx < nr_msc; bssap_idx := bssap_idx+1) {
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001242 allow_attach[bssap_idx] := true;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001243 /* Call a function of our 'parent component' RAN_Adapter_CT to start the
1244 * MSC-side BSSAP emulation */
1245 if (handler_mode) {
1246 var RanOps ranops := MSC_RanOps;
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001247 ranops.use_osmux := g_osmux_enabled_cn;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001248 f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", ranops);
1249 connect(self:SCCPLITE_IPA_CTRL, g_bssap[bssap_idx].vc_RAN:CTRL_CLIENT);
1250 f_ran_adapter_start(g_bssap[bssap_idx]);
1251 } else {
1252 f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", omit);
1253 connect(self:BSSAP, g_bssap[bssap_idx].vc_SCCP:SCCP_SP_PORT);
1254 f_ran_adapter_start(g_bssap[bssap_idx]);
1255 f_legacy_bssap_reset();
1256 }
Harald Welte67089ee2018-01-17 22:19:03 +01001257 }
Harald Welted5833a82018-05-27 16:52:56 +02001258
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02001259 if (mp_enable_lcs_tests) {
1260 if (handler_mode) {
1261 f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", SMLC_BssapLeOps);
1262 } else {
1263 f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", omit);
1264 connect(self:BSSAP_LE, g_bssap_le.vc_SCCP:SCCP_SP_PORT);
1265 }
1266 f_bssap_le_adapter_start(g_bssap_le);
Harald Welte47cd0e32020-08-21 12:39:11 +02001267 }
Harald Welte47cd0e32020-08-21 12:39:11 +02001268
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001269 /* start the test with exactly all enabled MSCs allowed to attach */
1270 f_vty_msc_allow_attach(BSCVTY, allow_attach);
1271
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01001272 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Harald Welte28d943e2017-11-25 15:00:50 +01001273
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001274 g_nr_mgw := nr_mgw;
1275 for (var integer i := 0; i < g_nr_mgw; i := i+1) {
1276 f_init_mgcp(i, "VirtMGW");
1277 }
Daniel Willmann191e0d92018-01-17 12:44:35 +01001278
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001279 for (var integer i := 0; i < nr_bts; i := i+1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001280 f_init_bts(i, c_BtsParams[i].trx_num, handler_mode);
Harald Welte696ddb62017-12-08 14:01:43 +01001281 }
Neels Hofmeyr9c0f9c82022-01-23 01:20:28 +01001282
1283 /* Emit a marker to appear in the SUT's own logging output */
1284 f_logp(BSCVTY, testcasename() & "() start");
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001285}
Harald Welte696ddb62017-12-08 14:01:43 +01001286
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001287function f_init_bts(integer bts_idx := 0,
1288 integer trx_num := NUM_TRX_CFG,
1289 boolean handler_mode := false)
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001290runs on test_CT {
1291 /* wait until osmo-bts-omldummy has respawned */
1292 f_wait_oml(bts_idx, "degraded", 5.0);
1293
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001294 /* start RSL connection(s) */
1295 for (var integer trx_idx := 0; trx_idx < trx_num; trx_idx := trx_idx + 1) {
1296 f_ipa_rsl_start(bts[bts_idx][trx_idx].rsl,
1297 mp_bsc_ip, mp_bsc_rsl_port,
1298 {bts_idx, trx_idx}, handler_mode);
1299 }
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001300 /* wait until BSC tells us "connected" */
1301 f_wait_oml(bts_idx, "connected", 5.0);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001302
1303 /* Set up BTS with VTY commands: */
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01001304 f_vty_enter_cfg_bts(BSCVTY, bts_idx);
1305 if (g_osmux_enabled_bts) {
1306 f_vty_transceive(BSCVTY, "osmux on");
1307 } else {
1308 f_vty_transceive(BSCVTY, "osmux off");
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001309 }
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01001310 f_vty_transceive(BSCVTY, "end");
Harald Welte28d943e2017-11-25 15:00:50 +01001311}
1312
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001313function f_init_bts_and_check_sysinfo(integer bts_idx := 0,
1314 integer trx_num := NUM_TRX_CFG,
1315 boolean handler_mode := false,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001316 template SystemInformationConfig expect_si)
1317runs on test_CT {
1318 var default sysinfo := activate(as_catch_RSL_sysinfo(bts_idx));
1319
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001320 f_init_bts(bts_idx, trx_num, handler_mode);
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001321
1322 /* Give some time to (hopefully/most likely) collect all system informations from RSL startup.
1323 * We could stop as soon as all expected SI are received, but then we might miss SI that we don't expect and
1324 * that might be sent afterwards. So rather give a generous timeout and be quite sure to catch all SI.
1325 */
1326 f_sleep(5.0);
1327 log("RSL ", bts_idx, " SYSTEM INFORMATION: ", g_system_information[bts_idx]);
1328
1329 deactivate(sysinfo);
1330
1331 if (match(g_system_information[bts_idx], expect_si)) {
1332 setverdict(pass);
1333 } else {
1334 log("RSL ", bts_idx, ": EXPECTED SI: ", expect_si);
1335 log("RSL ", bts_idx, ": GOT SI: ", g_system_information[bts_idx]);
1336 setverdict(fail, "received SI does not match expectations");
1337 return;
1338 }
1339}
1340
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001341/* expect to receive a RSL message matching a specified template on a given BTS / TRX */
1342function f_exp_ipa_rx(template (present) RSL_Message t_rx,
1343 BtsTrxIdx idx := {0, 0},
1344 float Tval := 2.0)
Harald Welteae026692017-12-09 01:03:01 +01001345runs on test_CT return RSL_Message {
1346 var ASP_RSL_Unitdata rx_rsl_ud;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001347 timer T := Tval;
Harald Welteae026692017-12-09 01:03:01 +01001348
1349 T.start;
1350 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001351 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
Harald Welteae026692017-12-09 01:03:01 +01001352 T.stop;
1353 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001354 [] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
Harald Welteb2917702017-12-10 15:48:52 +01001355 [] T.timeout {
1356 setverdict(fail, "Timeout expecting ", t_rx);
Daniel Willmannafce8662018-07-06 23:11:32 +02001357 mtc.stop;
Harald Welteb2917702017-12-10 15:48:52 +01001358 }
Harald Welteae026692017-12-09 01:03:01 +01001359 }
1360 return rx_rsl_ud.rsl;
1361}
1362
Harald Welte21b46bd2017-12-17 19:46:32 +01001363/* helper function to transmit RSL on a given BTS/stream */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001364function f_ipa_tx(template (value) RSL_Message t_tx,
1365 BtsTrxIdx idx := {0, 0},
1366 IpaStreamId sid := IPAC_PROTO_RSL_TRX0)
Harald Welteae026692017-12-09 01:03:01 +01001367runs on test_CT {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001368 IPA_RSL[idx.bts][idx.trx].send(ts_ASP_RSL_UD(t_tx, sid));
Harald Welteae026692017-12-09 01:03:01 +01001369}
1370
1371
Harald Welte4003d112017-12-09 22:35:39 +01001372/* verify we get a CHAN_ACT after CHAN RQD */
Harald Welteae026692017-12-09 01:03:01 +01001373testcase TC_chan_act_noreply() runs on test_CT {
1374 var BSSAP_N_UNITDATA_ind ud_ind;
Harald Welte930d0a72018-03-22 22:08:40 +01001375 var RSL_Message rsl_unused;
Harald Welte28d943e2017-11-25 15:00:50 +01001376
Harald Welte89d42e82017-12-17 16:42:41 +01001377 f_init(1);
Harald Welte28d943e2017-11-25 15:00:50 +01001378
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001379 f_ipa_tx(ts_RSL_CHAN_RQD('23'O, 23));
1380 rsl_unused := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001381 f_shutdown_helper();
Harald Welte28d943e2017-11-25 15:00:50 +01001382}
1383
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001384const CounterNameVals counternames_bts_chreq := {
1385 { "chreq:total", 0 },
1386 { "chreq:attempted_emerg", 0 },
1387 { "chreq:attempted_call", 0 },
1388 { "chreq:attempted_location_upd", 0 },
1389 { "chreq:attempted_pag", 0 },
1390 { "chreq:attempted_pdch", 0 },
1391 { "chreq:attempted_other", 0 },
1392 { "chreq:attempted_unknown", 0 },
1393 { "chreq:successful", 0 },
1394 { "chreq:successful_emerg", 0 },
1395 { "chreq:successful_call", 0 },
1396 { "chreq:successful_location_upd", 0 },
1397 { "chreq:successful_pag", 0 },
1398 { "chreq:successful_pdch", 0 },
1399 { "chreq:successful_other", 0 },
1400 { "chreq:successful_unknown", 0 },
1401 { "chreq:no_channel", 0 },
1402 { "chreq:max_delay_exceeded", 0 }
1403};
1404
1405/* verify the "chreq:*" counters */
1406private function f_chan_act_counter(OCT1 ra, charstring chreq_ctr_suffix) runs on test_CT
1407{
1408 var GsmFrameNumber fn := 23;
1409
1410 f_logp(BSCVTY, "f_chan_act_counter(" & chreq_ctr_suffix & ")");
1411
1412 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001413 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn));
1414 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001415 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1416
1417 f_ctrs_bts_add(0, "chreq:total");
1418 f_ctrs_bts_add(0, "chreq:attempted_" & chreq_ctr_suffix);
1419 f_ctrs_bts_verify();
1420
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001421 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
1422 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001423
1424 f_ctrs_bts_add(0, "chreq:successful");
1425 f_ctrs_bts_add(0, "chreq:successful_" & chreq_ctr_suffix);
1426 f_ctrs_bts_verify();
1427
1428 /* test is done, release RSL Conn Fail Ind to clean up */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001429 f_ipa_tx(ts_RSL_CONN_FAIL_IND(chan_nr, RSL_ERR_RADIO_LINK_FAIL));
1430 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
1431 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001432 f_sleep(1.0);
1433}
1434
Harald Welte4003d112017-12-09 22:35:39 +01001435testcase TC_chan_act_counter() runs on test_CT {
1436 var BSSAP_N_UNITDATA_ind ud_ind;
1437 var integer chreq_total;
Harald Welte930d0a72018-03-22 22:08:40 +01001438 var RSL_Message rsl_unused;
Harald Welte4003d112017-12-09 22:35:39 +01001439
Harald Welte89d42e82017-12-17 16:42:41 +01001440 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01001441
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001442 f_vty_allow_emerg_bts(true, 0);
1443
1444 f_ctrs_bts_init(1, counternames_bts_chreq);
1445
1446 /* emergency call: RA & 0xe0 == 0xa0 --> CHREQ_T_EMERG_CALL */
1447 f_chan_act_counter('a3'O, "emerg");
1448
1449 /* voice TCH/H: RA & 0xf0 == 0x40 --> CHREQ_T_VOICE_CALL_TCH_H */
1450 f_chan_act_counter('43'O, "call");
1451
1452 /* LU: RA & 0xf0 == 0x00 --> CHREQ_T_LOCATION_UPD */
1453 f_chan_act_counter('03'O, "location_upd");
1454
1455 /* Paging: RA & 0xf0 == 0x20 --> CHREQ_T_PAG_R_TCH_F */
1456 f_chan_act_counter('23'O, "pag");
1457 /* Paging: RA & 0xf0 == 0x30 --> CHREQ_T_PAG_R_TCH_FH */
1458 f_chan_act_counter('33'O, "pag");
1459
1460 /* LU: RA & 0xfc == 0x78 --> CHREQ_T_PDCH_TWO_PHASE */
1461 /* no PCU, so PDCH not allowed. Skip this test for now. */
1462 /* f_chan_act_counter('7b'O, "pdch"); */
1463
1464 /* LU: RA & 0xf0 == 0x10 --> CHREQ_T_SDCCH */
1465 f_chan_act_counter('13'O, "other");
Harald Welte4003d112017-12-09 22:35:39 +01001466
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001467 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01001468}
1469
Harald Welteae026692017-12-09 01:03:01 +01001470/* CHAN RQD -> CHAN ACT -> CHAN ACT ACK -> RF CHAN REL */
Philipp Maier9c60a622020-07-09 15:08:46 +02001471private function f_TC_chan_act_ack_noest(OCT1 ra := '23'O) runs on test_CT {
Harald Welteae026692017-12-09 01:03:01 +01001472 var RSL_Message rx_rsl;
1473
Harald Welteae026692017-12-09 01:03:01 +01001474 /* Send CHAN RQD and wait for allocation; acknowledge it */
Philipp Maier9c60a622020-07-09 15:08:46 +02001475 var RslChannelNr chan_nr := f_chreq_act_ack(ra);
Harald Welteae026692017-12-09 01:03:01 +01001476
1477 /* expect BSC to disable the channel again if there's no RLL EST IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001478 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := T3101_MAX);
Harald Welteae026692017-12-09 01:03:01 +01001479
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001480 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001481}
1482
Philipp Maier9c60a622020-07-09 15:08:46 +02001483/* Normal variant */
1484testcase TC_chan_act_ack_noest() runs on test_CT {
Philipp Maieraf58db22020-08-12 17:24:40 +02001485 f_init(1);
Philipp Maier9c60a622020-07-09 15:08:46 +02001486 f_TC_chan_act_ack_noest();
1487}
1488
1489/* Emergency call variant */
1490testcase TC_chan_act_ack_noest_emerg() runs on test_CT {
1491 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
Philipp Maieraf58db22020-08-12 17:24:40 +02001492 f_init(1);
1493 f_vty_allow_emerg_bts(true, 0);
Philipp Maier9c60a622020-07-09 15:08:46 +02001494 f_TC_chan_act_ack_noest(ra := 'A5'O);
1495}
1496
Philipp Maier606f07d2020-08-12 17:21:58 +02001497/* Emergency call variant, but emergency calls are not allowed */
1498testcase TC_chan_rqd_emerg_deny() runs on test_CT {
1499 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
1500
1501 var RSL_Message rx_rsl;
1502 var GsmRrMessage rr;
1503
1504 f_init(1);
1505 f_vty_allow_emerg_bts(false, 0);
1506
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001507 IPA_RSL[0][0].clear;
1508 f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
Philipp Maier606f07d2020-08-12 17:21:58 +02001509
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001510 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
Philipp Maier606f07d2020-08-12 17:21:58 +02001511 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
1512 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1513 setverdict(pass);
1514 } else {
1515 setverdict(fail, "immediate assignment not rejected");
1516 }
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01001517
1518 f_shutdown_helper();
Philipp Maier606f07d2020-08-12 17:21:58 +02001519}
1520
Harald Welteae026692017-12-09 01:03:01 +01001521/* Test behavior if MSC never answers to CR */
1522testcase TC_chan_act_ack_est_ind_noreply() runs on test_CT {
Harald Weltef77aef62018-01-28 15:35:42 +01001523 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
1524 var IpaStreamId sid := IPAC_PROTO_RSL_TRX0;
Harald Welteae026692017-12-09 01:03:01 +01001525 var RSL_Message rx_rsl;
Harald Weltef77aef62018-01-28 15:35:42 +01001526 var ASP_RSL_Unitdata rx_rsl_ud;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001527 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welteae026692017-12-09 01:03:01 +01001528
Harald Welte89d42e82017-12-17 16:42:41 +01001529 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001530
1531 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001532 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001533
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001534 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welteae026692017-12-09 01:03:01 +01001535
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001536 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload)));
Harald Welteae026692017-12-09 01:03:01 +01001537
1538 /* expect BSC to disable the channel again if there's no response from MSC */
Harald Weltef77aef62018-01-28 15:35:42 +01001539 /* MS waits 20s (T3210) at LU; 10s (T3230) at CM SERV REQ and 5s (T3220) AT detach */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001540 f_expect_chan_rel(chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001541 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001542}
1543
1544/* Test behavior if MSC answers with CREF to CR */
1545testcase TC_chan_act_ack_est_ind_refused() runs on test_CT {
1546 var BSSAP_N_CONNECT_ind rx_c_ind;
1547 var RSL_Message rx_rsl;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001548 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welteae026692017-12-09 01:03:01 +01001549
Harald Welte89d42e82017-12-17 16:42:41 +01001550 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001551
1552 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001553 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001554
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001555 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welteae026692017-12-09 01:03:01 +01001556
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001557 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Harald Welteae026692017-12-09 01:03:01 +01001558 BSSAP.send(ts_BSSAP_DISC_req(rx_c_ind.connectionId, 0));
1559
1560 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001561 f_expect_chan_rel(chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001562 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001563}
1564
Harald Welte618ef642017-12-14 14:58:20 +01001565/* CHAN RQD -> CHAN ACT -> CHAN ACT NACK -> RF CHAN REL */
1566testcase TC_chan_act_nack() runs on test_CT {
1567 var RSL_Message rx_rsl;
1568 var integer chact_nack;
1569
Harald Welte89d42e82017-12-17 16:42:41 +01001570 f_init(1);
Harald Welte618ef642017-12-14 14:58:20 +01001571
1572 chact_nack := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack");
1573
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001574 f_ipa_tx(ts_RSL_CHAN_RQD('33'O, 33));
1575 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Harald Welte618ef642017-12-14 14:58:20 +01001576 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1577
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001578 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
Harald Welte618ef642017-12-14 14:58:20 +01001579
1580 /* wait for some time to hope the NACK arrives before the CTRL GET below */
1581 f_sleep(0.5);
1582
1583 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack", chact_nack+1);
1584
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001585 f_shutdown_helper();
Harald Welte618ef642017-12-14 14:58:20 +01001586}
1587
Harald Welte799c97b2017-12-14 17:50:30 +01001588/* Test for channel exhaustion due to RACH overload */
1589testcase TC_chan_exhaustion() runs on test_CT {
1590 var ASP_RSL_Unitdata rsl_ud;
1591 var integer i;
1592 var integer chreq_total, chreq_nochan;
1593
Harald Welte89d42e82017-12-17 16:42:41 +01001594 f_init(1);
Harald Welte799c97b2017-12-14 17:50:30 +01001595
1596 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
1597 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
1598
Neels Hofmeyr85fa37f2021-10-06 13:50:38 +02001599 /* GSM 44.018 Table 9.1.8.2:
Pau Espin Pedrolfe200d72018-12-10 12:41:04 +01001600 * RA = '33'O -> Establishment cause = 0011xxxx (MS dual rate capable and asks for "TCH/H or TCH/F").
1601 * With current setup, expect 4xSDCCH + 4xTCH/F + 1xTCH/H to succeed */
Philipp Maiercb6cc482018-03-26 13:08:00 +02001602 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 +01001603 var RslChannelNr chan_nr := f_chreq_act_ack('33'O, i);
Harald Welte799c97b2017-12-14 17:50:30 +01001604 }
1605
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001606 IPA_RSL[0][0].clear;
Harald Welte799c97b2017-12-14 17:50:30 +01001607
Harald Weltedd8cbf32018-01-28 12:07:52 +01001608 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001609 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
Harald Welte799c97b2017-12-14 17:50:30 +01001610
1611 /* now expect additional channel activations to fail */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001612 f_ipa_tx(ts_RSL_CHAN_RQD('42'O, 42));
Harald Welte799c97b2017-12-14 17:50:30 +01001613
1614 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001615 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV))) {
Harald Welte799c97b2017-12-14 17:50:30 +01001616 setverdict(fail, "Received CHAN ACT ACK without resources?!?");
1617 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001618 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) -> value rsl_ud {
Harald Welte799c97b2017-12-14 17:50:30 +01001619 var GsmRrMessage rr;
1620 /* match on IMM ASS REJ */
1621 rr := dec_GsmRrMessage(rsl_ud.rsl.ies[1].body.full_imm_ass_info.payload);
1622 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1623 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001624 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS+1);
Harald Welte799c97b2017-12-14 17:50:30 +01001625 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel",
1626 chreq_nochan+1);
1627 setverdict(pass);
1628 } else {
1629 repeat;
1630 }
1631 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001632 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte799c97b2017-12-14 17:50:30 +01001633 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001634 f_shutdown_helper();
Harald Welte799c97b2017-12-14 17:50:30 +01001635}
1636
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001637/* Test channel deactivation due to silence from MS */
1638testcase TC_chan_deact_silence() runs on test_CT {
1639 var RslChannelNr chan_nr;
1640
1641 f_init(1);
1642
1643 /* Request for a dedicated channel */
1644 chan_nr := f_chreq_act_ack('23'O);
1645
1646 /* Wait some time until the channel is released */
1647 f_sleep(2.0);
1648
1649 /* Expect CHANnel RELease */
1650 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001651 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001652 log("Received CHANnel RELease");
1653 setverdict(pass);
1654 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001655 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001656 /* See OS#3709, OsmoBSC should not send Immediate
1657 * Assignment Reject since a dedicated channel was
1658 * already allocated, and Immediate Assignment was
1659 * already sent. */
1660 setverdict(fail, "Unexpected Immediate Assignment!");
1661 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001662 [] IPA_RSL[0][0].receive {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001663 setverdict(fail, "Unexpected RSL message!");
1664 }
1665 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001666 f_shutdown_helper();
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001667}
1668
Harald Weltecfe2c962017-12-15 12:09:32 +01001669/***********************************************************************
1670 * Assignment Testing
1671 ***********************************************************************/
1672
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02001673/* Verify that the BSC refuses any BSSAP connection from the MSC (They are all BSC->MSC direction,
1674 * except for the inter-BSC handover, MT side) */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001675testcase TC_outbound_connect(integer bssap_idx := 0) runs on test_CT {
Harald Welte89d42e82017-12-17 16:42:41 +01001676 f_init(1);
Harald Weltecfe2c962017-12-15 12:09:32 +01001677
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001678 BSSAP.send(ts_BSSAP_CONNECT_req(g_bssap[bssap_idx].sccp_addr_peer, g_bssap[bssap_idx].sccp_addr_own,
1679 2342, ts_BSSMAP_AssignmentReq));
Harald Weltecfe2c962017-12-15 12:09:32 +01001680 BSSAP.receive(tr_BSSAP_DISC_ind(2342, ?, ?));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001681 f_shutdown_helper();
Harald Weltecfe2c962017-12-15 12:09:32 +01001682}
1683
Harald Welte16a4adf2017-12-14 18:54:01 +01001684/* Test behavior if MSC answers with CREF to CR */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001685testcase TC_assignment_cic_only(integer bssap_idx := 0) runs on test_CT {
Harald Welte16a4adf2017-12-14 18:54:01 +01001686 var BSSAP_N_CONNECT_ind rx_c_ind;
1687 var RSL_Message rx_rsl;
1688 var DchanTuple dt;
1689
Harald Welte89d42e82017-12-17 16:42:41 +01001690 f_init(1);
Harald Welte16a4adf2017-12-14 18:54:01 +01001691
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001692 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001693 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte17b27da2018-05-25 20:33:53 +02001694 /* send assignment without AoIP IEs */
1695 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(ts_BSSMAP_IE_CIC(0, 1))));
1696 } else {
Pau Espin Pedrol35609792023-01-03 16:56:59 +01001697 /* Send assignment without CIC in IPA case */
Harald Welte17b27da2018-05-25 20:33:53 +02001698 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
1699 valueof(ts_BSSMAP_IE_AoIP_TLA4('01020304'O, 2342));
1700 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(omit, tla)));
1701 }
Harald Welte16a4adf2017-12-14 18:54:01 +01001702 alt {
1703 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1704 setverdict(fail, "AoIP BSC cannot accept ASSIGNMENT without AoIP Transport IE");
1705 }
Harald Welte235ebf12017-12-15 14:18:16 +01001706 /* TODO: Actually expect GSM0808_CAUSE_REQ_A_IF_TYPE_NOT_SUPP */
Harald Welte16a4adf2017-12-14 18:54:01 +01001707 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1708 setverdict(pass);
1709 }
1710 [] BSSAP.receive { repeat; }
1711 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001712 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001713 f_shutdown_helper();
Harald Welte16a4adf2017-12-14 18:54:01 +01001714}
1715
Harald Welteed848512018-05-24 22:27:58 +02001716/* generate an assignment request for either AoIP or SCCPlite */
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001717function 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 +02001718 var PDU_BSSAP ass_cmd;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001719 var BSSMAP_IE_Osmo_OsmuxCID osmux_cid := valueof(ts_OsmuxCID(0));
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001720 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welteed848512018-05-24 22:27:58 +02001721 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001722 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001723 if (osmux_enabled) {
1724 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla, osmux_cid));
1725 } else {
1726 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla));
1727 }
Harald Welteed848512018-05-24 22:27:58 +02001728 } else {
1729 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Pau Espin Pedrol096d73d2019-06-06 12:49:17 +02001730 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(cic, omit));
Harald Welteed848512018-05-24 22:27:58 +02001731 }
1732 return ass_cmd;
1733}
1734
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02001735function f_gen_handover_req(integer bssap_idx := 0, charstring aoip_tla := "1.2.3.4",
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001736 template (value) BSSMAP_IE_CellIdentifier cell_id_source := ts_CellID_LAC_CI(1, 1),
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001737 template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit,
1738 template (omit) TestHdlrEncrParams enc := omit) return PDU_BSSAP {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001739 var PDU_BSSAP ho_req;
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001740
1741 var BSSMAP_IE_EncryptionInformation encryptionInformation :=
1742 valueof(ts_BSSMAP_IE_EncrInfo('0000000000000000'O,'01'O));
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03001743 var template (omit) BSSMAP_IE_ChosenEncryptionAlgorithm chosenEncryptionAlgorithm := omit;
1744 var template (omit) BSSMAP_IE_KC128 kc128 := omit;
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001745 if (ispresent(enc)) {
1746 var TestHdlrEncrParams v_enc := valueof(enc);
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01001747 encryptionInformation := valueof(ts_BSSMAP_IE_EncrInfo(v_enc.enc_key, v_enc.enc_alg_permitted));
1748 if (ispresent(v_enc.enc_alg_chosen)) {
1749 chosenEncryptionAlgorithm := valueof(
1750 ts_BSSMAP_IE_ChosenEncryptionAlgorithm(int2oct(enum2int(
1751 f_cipher_mode_bssmap_to_rsl(v_enc.enc_alg_chosen)), 1)));
1752 }
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001753 if (ispresent(v_enc.enc_kc128)) {
1754 kc128 := ts_BSSMAP_IE_Kc128(v_enc.enc_kc128);
1755 }
1756 }
1757
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001758 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001759 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001760 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001761 ho_req := valueof(ts_BSSMAP_HandoverRequest(omit, tla,
1762 cell_id_source := cell_id_source,
1763 oldToNewBSSIEs := oldToNewBSSIEs,
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001764 encryptionInformation := encryptionInformation,
1765 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
Neels Hofmeyr9fe13202022-03-04 00:05:43 +01001766 kC128 := kc128,
1767 /* on AoIP, allow "all" codecs (until we add more concise
1768 * tests) */
1769 codecList := ts_BSSMAP_IE_CodecList(
1770 {ts_CodecAMR_F, ts_CodecAMR_H,
1771 ts_CodecEFR, ts_CodecFR, ts_CodecHR})));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001772 } else {
1773 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001774 ho_req := valueof(ts_BSSMAP_HandoverRequest(cic, omit,
1775 cell_id_source := cell_id_source,
1776 oldToNewBSSIEs := oldToNewBSSIEs,
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001777 encryptionInformation := encryptionInformation,
1778 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
1779 kC128 := kc128));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001780 }
1781 return ho_req;
1782}
1783
Harald Welteed848512018-05-24 22:27:58 +02001784/* generate an assignment complete template for either AoIP or SCCPlite */
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001785function f_gen_exp_compl(integer bssap_idx := 0)
1786runs on MSC_ConnHdlr return template PDU_BSSAP {
Harald Welteed848512018-05-24 22:27:58 +02001787 var template PDU_BSSAP exp_compl;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001788 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001789 var template BSSMAP_IE_Osmo_OsmuxCID exp_osmux_cid := omit;
1790 if (g_pars.use_osmux_cn) {
1791 var template (present) INT1 exp_cid := ?;
1792 if (isbound(g_media.mgcp_conn[0].local_osmux_cid) and isbound(g_media.mgcp_conn[1].local_osmux_cid)) {
1793 exp_cid := (g_media.mgcp_conn[0].local_osmux_cid, g_media.mgcp_conn[1].local_osmux_cid);
1794 } else if (isbound(g_media.mgcp_conn[0].local_osmux_cid)) {
1795 exp_cid := g_media.mgcp_conn[0].local_osmux_cid;
1796 } else if (isbound(g_media.mgcp_conn[1].local_osmux_cid)) {
1797 exp_cid := g_media.mgcp_conn[1].local_osmux_cid;
1798 }
1799 exp_osmux_cid := tr_OsmuxCID(exp_cid);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001800 }
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001801 exp_compl := tr_BSSMAP_AssignmentComplete(omit, ?, exp_osmux_cid);
Harald Welteed848512018-05-24 22:27:58 +02001802 } else {
1803 /* CIC is optional "*" as the MSC allocated it */
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001804 exp_compl := tr_BSSMAP_AssignmentComplete(*, omit, omit);
Harald Welteed848512018-05-24 22:27:58 +02001805 }
1806 return exp_compl;
1807}
1808
Harald Welte235ebf12017-12-15 14:18:16 +01001809/* Run everything required up to sending a caller-specified assignment command and expect response */
1810function f_assignment_exp(PDU_BSSAP ass_cmd, template PDU_BSSAP exp, charstring fail_text)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001811runs on test_CT return DchanTuple {
Harald Welte235ebf12017-12-15 14:18:16 +01001812 var BSSAP_N_CONNECT_ind rx_c_ind;
1813 var RSL_Message rx_rsl;
1814 var DchanTuple dt;
1815
Harald Welte89d42e82017-12-17 16:42:41 +01001816 f_init(1);
Harald Welte235ebf12017-12-15 14:18:16 +01001817
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001818 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte235ebf12017-12-15 14:18:16 +01001819 /* send assignment without AoIP IEs */
1820 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
1821 alt {
1822 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1823 if (ischosen(exp.pdu.bssmap.assignmentComplete)) {
1824 setverdict(pass);
1825 } else {
1826 setverdict(fail, fail_text);
1827 }
1828 }
1829 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1830 if (ischosen(exp.pdu.bssmap.assignmentFailure)) {
1831 setverdict(pass);
1832 } else {
1833 setverdict(fail, fail_text);
1834 }
1835 }
1836 [] BSSAP.receive { repeat; }
1837 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001838 return dt;
Harald Welte235ebf12017-12-15 14:18:16 +01001839}
Oliver Smithdd002752023-02-21 13:35:00 +01001840
1841private function f_tc_assignment_csd(charstring id) runs on MSC_ConnHdlr {
1842 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Harald Welteed848512018-05-24 22:27:58 +02001843 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Oliver Smithdd002752023-02-21 13:35:00 +01001844
Harald Welte235ebf12017-12-15 14:18:16 +01001845 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
Oliver Smithdd002752023-02-21 13:35:00 +01001846 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecCSData}));
1847
1848 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := GSM0808_DATA_RATE_TRANSP_4k8;
1849
1850 f_establish_fully(ass_cmd, exp_compl);
1851 f_perform_clear();
1852}
1853testcase TC_assignment_csd() runs on test_CT {
1854 if (Misc_Helpers.f_osmo_repo_is("nightly")) { /* osmo-bsc > 1.10.0 */
1855 var MSC_ConnHdlr vc_conn;
1856 var TestHdlrParams pars := f_gen_test_hdlr_pars();
1857 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
1858
1859 f_init(1, true);
1860 f_sleep(1.0);
1861 vc_conn := f_start_handler(refers(f_tc_assignment_csd), pars);
1862 vc_conn.done;
1863 } else {
1864 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
1865 var PDU_BSSAP ass_cmd := f_gen_ass_req();
1866 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
1867 //exp_fail.pdu.bssmap.assignmentFailure.cause.causeValue := int2bit(enum2int(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_UNAVAIL), 7);
1868 var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for CSD");
1869 f_perform_clear_test_ct(dt);
1870 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001871 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001872}
1873
1874testcase TC_assignment_ctm() runs on test_CT {
1875 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02001876 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte235ebf12017-12-15 14:18:16 +01001877 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCTM);
1878 //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 +01001879 var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for Speech+CTM");
1880 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001881 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001882}
1883
Harald Welte4003d112017-12-09 22:35:39 +01001884type record DchanTuple {
1885 integer sccp_conn_id,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001886 RslChannelNr rsl_chan_nr,
1887 BtsTrxIdx idx
Harald Weltea5d2ab22017-12-09 14:21:42 +01001888}
1889
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +02001890type record of DchanTuple DchanTuples;
1891
Harald Welted6939652017-12-13 21:02:46 +01001892/* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001893private function f_chreq_act_ack(OCT1 ra := '23'O,
1894 GsmFrameNumber fn := 23,
1895 BtsTrxIdx idx := {0, 0})
Harald Welted6939652017-12-13 21:02:46 +01001896runs on test_CT return RslChannelNr {
1897 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001898 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
1899 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Harald Welted6939652017-12-13 21:02:46 +01001900 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001901 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10), idx);
1902 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Harald Welted6939652017-12-13 21:02:46 +01001903 return chan_nr;
1904}
1905
Harald Welte4003d112017-12-09 22:35:39 +01001906/* helper function to establish a dedicated channel via BTS and MSC */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001907function f_est_dchan(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1908 BtsTrxIdx idx := {0, 0})
Harald Welte4003d112017-12-09 22:35:39 +01001909runs on test_CT return DchanTuple {
1910 var BSSAP_N_CONNECT_ind rx_c_ind;
Harald Welte4003d112017-12-09 22:35:39 +01001911 var DchanTuple dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001912
Harald Welte4003d112017-12-09 22:35:39 +01001913 /* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001914 dt.rsl_chan_nr := f_chreq_act_ack(ra, fn, idx);
Harald Welte4003d112017-12-09 22:35:39 +01001915
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001916 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 +01001917
1918 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1919 dt.sccp_conn_id := rx_c_ind.connectionId;
1920 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1921
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001922 dt.idx := idx;
Harald Welte4003d112017-12-09 22:35:39 +01001923 return dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001924}
1925
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001926/* 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 +06001927function f_est_dchan_dyn(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1928 BtsTrxIdx idx := {0, 0})
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001929runs on test_CT return DchanTuple {
1930 var BSSAP_N_CONNECT_ind rx_c_ind;
1931 var DchanTuple dt;
1932
1933 /* Send CHAN RQD */
1934 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001935 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001936
1937 /* The dyn TS first deactivates PDCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001938 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 +02001939 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001940 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001941
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001942 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001943 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
1944
1945 /* Now activates the signalling channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001946 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, fn+10), idx);
1947 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001948
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001949 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 +02001950
1951 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1952 dt.sccp_conn_id := rx_c_ind.connectionId;
1953 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1954
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001955 dt.idx := idx;
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001956 return dt;
1957}
1958
Harald Welte641fcbe2018-06-14 10:58:35 +02001959/* expect RF CAN REL from BTS, acknowledge it and clear the MSC side */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001960private function f_exp_chan_rel_and_clear(DchanTuple dt)
1961runs on test_CT {
Harald Welte641fcbe2018-06-14 10:58:35 +02001962 var RSL_Message rx_rsl;
1963 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001964 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 +02001965 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001966 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), dt.idx);
Harald Welte641fcbe2018-06-14 10:58:35 +02001967
1968 /* expect Clear Complete from BSC */
1969 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
1970
1971 /* MSC disconnects as instructed. */
1972 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
1973}
1974
Harald Welte4003d112017-12-09 22:35:39 +01001975/* Test behavior of channel release after unilateral RLL REL IND (DISC from MS) */
1976testcase TC_chan_rel_rll_rel_ind() runs on test_CT {
Neels Hofmeyr27f64362018-03-12 01:44:00 +01001977 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01001978 var DchanTuple dt;
Harald Welte96c94412017-12-09 03:12:45 +01001979
Harald Welte89d42e82017-12-17 16:42:41 +01001980 f_init(1);
Harald Welte96c94412017-12-09 03:12:45 +01001981
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001982 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01001983
1984 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001985 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Harald Welte4003d112017-12-09 22:35:39 +01001986
Neels Hofmeyr27f64362018-03-12 01:44:00 +01001987 /* expect Clear Request on MSC side */
1988 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
1989
1990 /* Instruct BSC to clear channel */
1991 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
1992 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
1993
Harald Welte4003d112017-12-09 22:35:39 +01001994 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001995 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr27f64362018-03-12 01:44:00 +01001996
1997 /* wait for SCCP emulation to do its job */
1998 f_sleep(1.0);
Harald Welte4003d112017-12-09 22:35:39 +01001999
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002000 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002001}
2002
2003/* Test behavior of channel release after CONN FAIL IND from BTS */
2004testcase TC_chan_rel_conn_fail() runs on test_CT {
2005 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002006 var DchanTuple dt;
2007
Harald Welte89d42e82017-12-17 16:42:41 +01002008 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002009
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002010 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002011
Vadim Yanitskiy01d0a902022-12-14 22:41:42 +07002012 /* Sending CONN FAIL IND immediately may trigger a race condition.
2013 * Give the BSC some time to process a new SCCP connection (OS#5823). */
2014 f_sleep(0.2);
2015
Harald Welte4003d112017-12-09 22:35:39 +01002016 /* simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002017 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte4003d112017-12-09 22:35:39 +01002018 /* TODO: different cause values? */
2019
Harald Welte4003d112017-12-09 22:35:39 +01002020 /* expect Clear Request from BSC */
2021 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
2022
2023 /* Instruct BSC to clear channel */
2024 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
2025 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2026
Harald Welte6ff76ea2018-01-28 13:08:01 +01002027 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002028 f_exp_chan_rel_and_clear(dt);
Harald Welte4003d112017-12-09 22:35:39 +01002029
2030 /* wait for SCCP emulation to do its job */
2031 f_sleep(1.0);
2032
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002033 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002034}
2035
Harald Welte99f3ca02018-06-14 13:40:29 +02002036/* Test behavior of early CONN FAIL IND from BTS (before EST IND!) */
2037/* See also https://www.osmocom.org/issues/3182 */
2038testcase TC_early_conn_fail() runs on test_CT {
2039 var RSL_Message rx_rsl;
2040 var DchanTuple dt;
2041
2042 f_init(1);
2043
2044 /* BTS->BSC: Send CHAN RQD and wait for allocation; acknowledge it */
Harald Weltec46ea3c2020-10-10 18:46:12 +02002045 dt.rsl_chan_nr := f_chreq_act_ack(f_rnd_ra_cs(), 23);
Harald Welte99f3ca02018-06-14 13:40:29 +02002046
2047 /* BTS->BSC: simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002048 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02002049
2050 /* BTS->BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002051 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02002052
2053 /* BTS<-BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002054 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002055
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002056 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002057}
2058
2059/* Test behavior of late CONN FAIL IND from BTS (ater REL IND!) */
2060/* See also https://www.osmocom.org/issues/3182 */
2061testcase TC_late_conn_fail() runs on test_CT {
2062 var RSL_Message rx_rsl;
2063 var DchanTuple dt;
2064
2065 f_init(1);
2066
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002067 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte99f3ca02018-06-14 13:40:29 +02002068
2069 /* BSC<-MSC: Instruct BSC to clear connection */
2070 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(0)));
2071
2072 /* BTS->BSC: expect BSC to deactivate SACCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002073 rx_rsl := f_exp_ipa_rx(tr_RSL_DEACT_SACCH(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002074
2075 /* BTS->BSC: simulate a late CONN FAIL IND from BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002076 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02002077
2078 /* BTS<-BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002079 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02002080 /* BTS->BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002081 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002082
2083 /* BSC->MSC: expect Clear Complete from BSC */
2084 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
2085
2086 /* BSC<-MSC: MSC disconnects as requested. */
2087 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2088
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002089 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002090}
2091
Oliver Smithaf03bef2021-08-24 15:34:51 +02002092private function f_TC_stats_conn_fail(charstring id) runs on MSC_ConnHdlr {
2093 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
2094 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2095
2096 f_statsd_reset();
2097
2098 /* Establish SDCCH */
2099 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
2100 f_establish_fully(ass_cmd, exp_fail);
2101
2102 /* Expect stats to be 0 */
2103 var StatsDExpects expect := {
2104 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 0, max := 0},
2105 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 0, max := 0}
2106 };
2107 f_statsd_expect(expect);
2108
2109 /* Simulate CONN FAIL IND on SDCCH */
2110 RSL.send(ts_ASP_RSL_UD(
2111 ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL),
2112 IPAC_PROTO_RSL_TRX0));
2113
Neels Hofmeyr58be48a2021-09-07 18:39:21 +02002114 f_sleep(1.0);
2115
Oliver Smithaf03bef2021-08-24 15:34:51 +02002116 /* Expect stats to be 1 */
2117 expect := {
2118 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 1, max := 1},
2119 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 1, max := 1}
2120 };
2121 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002122 BSSAP.receive(tr_BSSMAP_ClearRequest);
2123 f_perform_clear();
Oliver Smithaf03bef2021-08-24 15:34:51 +02002124}
2125testcase TC_stats_conn_fail() runs on test_CT {
2126 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2127 var MSC_ConnHdlr vc_conn;
2128
2129 f_init(1, true);
2130 f_sleep(1.0);
2131
2132 vc_conn := f_start_handler(refers(f_TC_stats_conn_fail), pars);
2133 vc_conn.done;
2134
2135 f_shutdown_helper();
2136}
2137
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002138function f_expect_chan_rel(RslChannelNr rsl_chan_nr,
2139 BtsTrxIdx idx := {0, 0},
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002140 boolean expect_deact_sacch := true,
2141 boolean expect_rr_chan_rel := true,
2142 boolean expect_rll_rel_req := true,
Harald Welte99787102019-02-04 10:41:36 +01002143 boolean handle_rll_rel := true,
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002144 template CellSelIndValue expect_cells := omit,
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002145 template (present) RR_Cause expect_rr_cause := ?
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002146 ) runs on test_CT {
Harald Welte91d54a52018-01-28 15:35:07 +01002147
2148 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002149 var boolean got_deact_sacch := false;
2150 var boolean got_rr_chan_rel := false;
2151 var boolean got_rll_rel_req := false;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002152 var ASP_RSL_Unitdata ud;
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002153 var RSL_IE_Body l3_ie;
2154 var PDU_ML3_NW_MS l3;
2155 var RR_Cause got_cause;
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002156 log("f_expect_chan_rel() expecting: expect_deact_sacch=", expect_deact_sacch, " expect_rr_chan_rel=", expect_rr_chan_rel,
2157 " expect_rll_rel_req=", expect_rll_rel_req);
Harald Welte91d54a52018-01-28 15:35:07 +01002158 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002159 [] 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 +01002160 got_deact_sacch := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002161 repeat;
2162 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002163 [] 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 +01002164 got_rr_chan_rel := true;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002165
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002166 if (f_rsl_find_ie(ud.rsl, RSL_IE_L3_INFO, l3_ie) == false) {
2167 setverdict(fail, "cannot find L3");
2168 mtc.stop;
2169 }
2170 l3 := dec_PDU_ML3_NW_MS(l3_ie.l3_info.payload);
2171
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002172 if (not istemplatekind(expect_cells, "omit")) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002173 var CellSelIndValue cells := dec_CellSelIndValue(
2174 l3.msgs.rrm.channelRelease.cellSelectionIndicator.cellSelectionIndicatorValue);
2175
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002176 log("GOT RR CHANNEL RELEASE WITH CELLS: ", cells);
2177 if (match(cells, expect_cells)) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002178 setverdict(pass);
2179 } else {
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002180 log("EXPECTED CELLS: ", expect_cells);
2181 setverdict(fail, "Received cells list on RR Channel Release does not match expectations");
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002182 }
2183 }
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002184
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002185 int2enum(oct2int(l3.msgs.rrm.channelRelease.rRCause.valuePart), got_cause);
2186 log("GOT CAUSE CODE: ", l3.msgs.rrm.channelRelease.rRCause.valuePart, " = ", got_cause);
2187 if (match(got_cause, expect_rr_cause)) {
2188 setverdict(pass);
2189 } else {
2190 log("EXPECTED CAUSE CODE: ", expect_rr_cause);
2191 setverdict(fail, "Received RR Channel Release Cause code does not match expectations");
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002192 }
Harald Welte99787102019-02-04 10:41:36 +01002193 repeat;
2194 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002195 [] 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 +01002196 got_rll_rel_req := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002197 /* FIXME: Why are we getting this for LinkID SACCH? */
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002198 if (handle_rll_rel) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002199 f_ipa_tx(ts_RSL_REL_CONF(rsl_chan_nr, main_dcch));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002200 }
Harald Welte91d54a52018-01-28 15:35:07 +01002201 repeat;
2202 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002203 [] 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 +01002204 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002205 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(rsl_chan_nr));
Harald Welte91d54a52018-01-28 15:35:07 +01002206 }
2207 /* ignore any user data */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002208 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeR(?))) {
Harald Welte91d54a52018-01-28 15:35:07 +01002209 repeat;
2210 }
2211 }
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002212
2213 log("f_expect_chan_rel() summary: got_deact_sacch=", got_deact_sacch, " got_rr_chan_rel=", got_rr_chan_rel,
2214 " got_rll_rel_req=", got_rll_rel_req);
2215
2216 if (expect_deact_sacch != got_deact_sacch) {
2217 setverdict(fail, "f_expect_chan_rel(): expect_deact_sacch=", expect_deact_sacch, " got_deact_sacch=", got_deact_sacch);
2218 }
2219 if (expect_rr_chan_rel != got_rr_chan_rel) {
2220 setverdict(fail, "f_expect_chan_rel(): expect_rr_chan_rel=", expect_rr_chan_rel, " got_rr_chan_rel=", got_rr_chan_rel);
2221 }
2222 if (expect_rll_rel_req != got_rll_rel_req) {
2223 setverdict(fail, "f_expect_chan_rel(): expect_rll_rel_req=", expect_rll_rel_req, " got_rll_rel_req=", got_rll_rel_req);
2224 }
Harald Welte91d54a52018-01-28 15:35:07 +01002225}
2226
Harald Welte4003d112017-12-09 22:35:39 +01002227/* Test behavior of channel release after hard Clear Command from MSC */
2228testcase TC_chan_rel_hard_clear() runs on test_CT {
2229 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002230 var DchanTuple dt;
Harald Welte4003d112017-12-09 22:35:39 +01002231
Harald Welte89d42e82017-12-17 16:42:41 +01002232 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002233
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002234 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002235
2236 /* Instruct BSC to clear channel */
2237 var BssmapCause cause := 0;
2238 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2239
2240 /* expect Clear Complete from BSC on A */
2241 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2242 /* release the SCCP connection */
2243 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2244 }
2245
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002246 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002247 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002248}
2249
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002250function f_TC_chan_rel_last_eutran_plmn_hard_clear(boolean tx_csfb_ind) runs on test_CT {
2251 var BSSAP_N_DATA_ind rx_di;
2252 var DchanTuple dt;
2253
2254 f_init(1);
2255
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002256 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002257 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2258 /* yet when generating the EUTRAN neigh list in RR CHannel Release) */
2259 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
2260
2261 /* Instruct BSC to clear channel */
2262 var BssmapCause cause := 0;
2263 if (tx_csfb_ind) {
2264 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2265 } else {
2266 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2267 }
2268
2269 /* expect Clear Complete from BSC on A */
2270 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2271 /* release the SCCP connection */
2272 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2273 }
2274
2275 /* 1 neighbor is added by default in osmo-bts.cfg and
2276 SystemInformationConfig_default, use that: */
2277 var template CellSelIndValue exp_cells := f_tr_rr_chan_rel_earfcns(1);
2278
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002279 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 +02002280 f_shutdown_helper();
2281}
2282
2283/* Test behavior of RR Channel rRelease after Clear Command without CSFB indicator
2284 from MSC, previously receiving any CommonID containing the "Last Used E-UTRAN
2285 PLMN Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2286 EUTRAN neighbor list sent later on by BSC in RR Channel, so receiving CSFB
2287 Indicator or not shouldn't matter at all. */
2288testcase TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() runs on test_CT {
2289 f_TC_chan_rel_last_eutran_plmn_hard_clear(false);
2290}
2291
2292/* Test behavior of RR Channel rRelease after Clear Command with CSFB indicator from
2293 MSC, previously receiving any CommonID containing the "Last Used E-UTRAN PLMN
2294 Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2295 EUTRAN neighbor list sent later on by BSC in RR Channel. */
2296testcase TC_chan_rel_last_eutran_plmn_hard_clear_csfb() runs on test_CT {
2297 f_TC_chan_rel_last_eutran_plmn_hard_clear(true);
2298}
2299
2300/* Test behavior of RR Channel Release after Clear Command with CSFB indicator from
2301 MSC, without receiving any CommonID containing the "Last Used E-UTRAN PLMN
2302 Id". According to spec (TS 48.008 version 16.0.0 Release 16 "3.2.1.21") the
2303 CSFB Indicator should not be used anymore, and hence, there should be no
2304 EUTRAN neighbor list sent by BSC in RR Channel release since no CommonId with
2305 Last Used E-UTRAN PLMN Id" IE was sent for this conn. */
Harald Welte99787102019-02-04 10:41:36 +01002306testcase TC_chan_rel_hard_clear_csfb() runs on test_CT {
2307 var BSSAP_N_DATA_ind rx_di;
2308 var DchanTuple dt;
2309
2310 f_init(1);
2311
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002312 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte99787102019-02-04 10:41:36 +01002313
2314 /* Instruct BSC to clear channel */
2315 var BssmapCause cause := 0;
2316 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2317
2318 /* expect Clear Complete from BSC on A */
2319 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2320 /* release the SCCP connection */
2321 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2322 }
2323
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002324 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002325 f_shutdown_helper();
Harald Welte99787102019-02-04 10:41:36 +01002326}
2327
Harald Welted8c36cd2017-12-09 23:05:31 +01002328/* Test behavior of channel release after hard RLSD from MSC */
2329testcase TC_chan_rel_hard_rlsd() runs on test_CT {
Harald Welted8c36cd2017-12-09 23:05:31 +01002330 var DchanTuple dt;
Harald Welted8c36cd2017-12-09 23:05:31 +01002331
Harald Welte89d42e82017-12-17 16:42:41 +01002332 f_init(1);
Harald Welted8c36cd2017-12-09 23:05:31 +01002333
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002334 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welted8c36cd2017-12-09 23:05:31 +01002335
2336 /* release the SCCP connection */
2337 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2338
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002339 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002340 f_shutdown_helper();
Harald Welted8c36cd2017-12-09 23:05:31 +01002341}
2342
Harald Welte550daf92018-06-11 19:22:13 +02002343/* Test behavior of channel release after hard RLSD from MSC and MS is not responding to RLL REL REQ */
2344testcase TC_chan_rel_hard_rlsd_ms_dead() runs on test_CT {
2345 var DchanTuple dt;
2346
2347 f_init(1);
2348
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002349 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte550daf92018-06-11 19:22:13 +02002350
2351 /* release the SCCP connection */
2352 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2353
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002354 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002355 f_shutdown_helper();
Harald Welte550daf92018-06-11 19:22:13 +02002356}
2357
Harald Welte85804d42017-12-10 14:11:58 +01002358/* Test behavior of channel release after BSSMAP RESET from MSC */
2359testcase TC_chan_rel_a_reset() runs on test_CT {
Harald Welte85804d42017-12-10 14:11:58 +01002360 var DchanTuple dt;
Harald Welte85804d42017-12-10 14:11:58 +01002361
Harald Welte89d42e82017-12-17 16:42:41 +01002362 f_init(1);
Harald Welte85804d42017-12-10 14:11:58 +01002363
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002364 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte85804d42017-12-10 14:11:58 +01002365
2366 /* Clear the queue, it might still contain stuff like IMMEDIATE ASSIGN */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002367 IPA_RSL[0][0].clear;
Harald Welte85804d42017-12-10 14:11:58 +01002368
2369 /* perform BSSAP RESET, expect RESET ACK and DISC.ind on connection */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002370 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 +01002371 interleave {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002372 [] 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 +01002373 [] BSSAP.receive(tr_BSSAP_DISC_ind(dt.sccp_conn_id, ?, ?)) { }
2374 }
2375
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002376 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002377 f_shutdown_helper();
Harald Welte85804d42017-12-10 14:11:58 +01002378}
2379
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002380/* Verify T(iar) triggers and releases the channel */
2381testcase TC_chan_rel_sccp_tiar_timeout() runs on test_CT {
2382 var DchanTuple dt;
2383
2384 /* Set T(iar) in BSC low enough that it will trigger before other side
2385 has time to keep alive with a T(ias). Keep recommended ratio of
2386 T(iar) >= T(ias)*2 */
2387 g_bsc_sccp_timer_ias := 2;
2388 g_bsc_sccp_timer_iar := 5;
2389
2390 f_init(1);
2391
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002392 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002393 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002394 f_shutdown_helper();
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002395}
2396
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002397private function f_tc_chan_rel_rr_cause(myBSSMAP_Cause clear_cmd_cause,
2398 template (present) RR_Cause expect_rr_cause)
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002399runs on test_CT
2400{
2401 var DchanTuple dt;
2402
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002403 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002404 var BssmapCause cause := 0;
2405 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(clear_cmd_cause))));
2406 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2407 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2408 }
2409
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002410 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 +02002411}
2412
2413/* Test that Clear Command cause codes affect the RR Channel Release cause code */
2414testcase TC_chan_rel_rr_cause() runs on test_CT {
2415 f_init(1);
2416
2417 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_CALL_CONTROL, GSM48_RR_CAUSE_NORMAL);
2418 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_HANDOVER_SUCCESSFUL, GSM48_RR_CAUSE_NORMAL);
2419 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_PREEMPTION, GSM48_RR_CAUSE_PREMPTIVE_REL);
2420 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, GSM48_RR_CAUSE_PROT_ERROR_UNSPC);
2421 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
2422 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_EQUIPMENT_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
Vadim Yanitskiye18aebb2021-01-03 13:10:43 +01002423
2424 f_shutdown_helper();
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002425}
2426
Harald Welte5cd20ed2017-12-13 21:03:20 +01002427/* Test behavior if RSL EST IND for non-active channel */
2428testcase TC_rll_est_ind_inact_lchan() runs on test_CT {
2429 timer T := 2.0;
2430
Harald Welte89d42e82017-12-17 16:42:41 +01002431 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002432
Harald Welte5cd20ed2017-12-13 21:03:20 +01002433 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002434 var octetstring l3_payload := gen_l3_valid_payload();
2435 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002436
2437 T.start;
2438 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002439 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002440 setverdict(fail, "MSC received COMPL L3 for non-active lchan");
2441 }
2442 [] BSSAP.receive {}
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002443 [] IPA_RSL[0][0].receive {}
Harald Welte5cd20ed2017-12-13 21:03:20 +01002444 [] T.timeout {}
2445 }
2446
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002447 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002448}
2449
2450/* Test behavior if RSL EST IND for invalid SAPI */
2451testcase TC_rll_est_ind_inval_sapi1() runs on test_CT {
2452 var RslChannelNr chan_nr;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002453 var octetstring l3_payload;
Harald Welte5cd20ed2017-12-13 21:03:20 +01002454
Harald Welte89d42e82017-12-17 16:42:41 +01002455 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002456
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002457 chan_nr := f_chreq_act_ack();
2458 l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002459
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002460 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(1)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002461
2462 timer T := 2.0;
2463 T.start;
2464 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002465 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002466 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 1");
2467 }
2468 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002469 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002470 [] T.timeout {}
2471 }
2472
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002473 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002474}
2475
2476/* Test behavior if RSL EST IND for invalid SAPI */
2477testcase TC_rll_est_ind_inval_sapi3() runs on test_CT {
2478 timer T := 2.0;
2479
Harald Welte89d42e82017-12-17 16:42:41 +01002480 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002481
2482 var RslChannelNr chan_nr := f_chreq_act_ack();
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002483 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002484
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002485 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(3)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002486
2487 T.start;
2488 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002489 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002490 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 3");
2491 }
2492 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002493 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002494 [] T.timeout {}
2495 }
2496
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002497 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002498}
2499
2500/* Test behavior if RSL EST IND for invalid SACCH */
2501testcase TC_rll_est_ind_inval_sacch() runs on test_CT {
2502 timer T := 2.0;
2503
Harald Welte89d42e82017-12-17 16:42:41 +01002504 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002505
2506 var RslChannelNr chan_nr := f_chreq_act_ack();
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002507 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002508
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002509 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_SACCH(0)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002510
2511 T.start;
2512 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002513 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002514 setverdict(fail, "MSC received COMPL L3 for invalid Link SACCH");
2515 }
2516 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002517 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002518 [] T.timeout {}
2519 }
2520
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002521 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002522}
2523
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002524/* Verify DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
2525private function f_TC_tch_dlci_link_id_sapi(charstring id) runs on MSC_ConnHdlr {
2526 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
2527 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2528
2529 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
2530 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
2531
2532 f_establish_fully(ass_cmd, exp_compl);
2533
2534 /* SAPI0 has already been established by f_establish_fully(), establish SAPI3 */
2535 RSL.send(ts_RSL_EST_IND(g_chan_nr, ts_RslLinkID_SACCH(3), '0904'O));
2536 /* Expect BSSAP/DTAP on SAPI3 (DLCI IE) */
2537 BSSAP.receive(PDU_BSSAP:{
2538 discriminator := '1'B,
2539 spare := '0000000'B,
2540 dlci := 'C3'O,
2541 lengthIndicator := ?,
2542 pdu := { dtap := '0904'O }
2543 });
2544
2545 /* Send messages on DCCH/SAPI0 and ACCH/SAPI3 */
2546 for (var integer i := 0; i < 32; i := i + 1) {
2547 var octetstring l3 := '09'O & f_rnd_octstring(14);
2548 var template (value) RslLinkId link_id;
2549 var template (value) OCT1 dlci;
2550
2551 if (i mod 2 == 0) {
2552 /* SAPI0 on FACCH or SDCCH */
2553 link_id := ts_RslLinkID_DCCH(0);
2554 dlci := '80'O;
2555 } else {
2556 /* SAPI3 on SACCH */
2557 link_id := ts_RslLinkID_SACCH(3);
2558 dlci := 'C3'O;
2559 }
2560
2561 /* Send MO message: RSL -> BSSAP */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002562 f_mo_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002563 /* Send MT message: BSSAP -> RSL */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002564 f_mt_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002565 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002566 f_perform_clear();
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002567}
2568testcase TC_tch_dlci_link_id_sapi() runs on test_CT {
2569 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2570 var MSC_ConnHdlr vc_conn;
2571
2572 f_init(1, true);
2573 f_sleep(1.0);
2574
2575 vc_conn := f_start_handler(refers(f_TC_tch_dlci_link_id_sapi), pars);
2576 vc_conn.done;
2577
2578 f_shutdown_helper();
2579}
2580
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002581private function f_exp_sapi_n_reject(template (present) GsmSapi sapi := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002582 template (present) myBSSMAP_Cause cause := ?,
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002583 template (present) BIT2 cc := ?,
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002584 float T_val := 2.0)
2585runs on test_CT {
2586 var BSSAP_N_DATA_ind rx_di;
2587 timer T;
2588
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002589 var template (present) BSSMAP_IE_Cause tr_cause := tr_BSSMAP_IE_Cause(cause);
2590 var template (present) PDU_BSSAP tr_pdu := tr_BSSMAP_SAPInReject(sapi);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002591
2592 T.start(T_val);
2593 alt {
2594 [] BSSAP.receive(tr_BSSAP_DATA_ind(?, tr_pdu)) -> value rx_di {
2595 var BSSMAP_IE_Cause rx_cause := rx_di.userData.pdu.bssmap.sAPInReject.cause;
2596 if (not match(rx_cause, tr_cause)) {
2597 setverdict(fail, "Rx unexpected Cause IE: ",
2598 rx_cause, " vs expected ", tr_cause);
2599 }
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002600
2601 /* Who ever on the earth decided to define this field as two separate bits?!? */
2602 var BIT2 rx_cc := rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c2
2603 & rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c1;
2604 if (not match(rx_cc, cc)) {
2605 setverdict(fail, "Rx unexpected Control Channel type: ",
2606 rx_cc, " vs expected ", cc);
2607 }
2608
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002609 setverdict(pass);
2610 }
2611 [] BSSAP.receive(BSSAP_N_DATA_ind:?) -> value rx_di {
2612 setverdict(fail, "Rx unexpected BSSAP PDU: ", rx_di);
2613 }
2614 [] T.timeout {
2615 setverdict(fail, "Timeout waiting for BSSMAP SAPI N Reject");
2616 }
2617 }
2618}
2619
2620/* Check if we get SAPI N Reject on receipt of unexpected RLL RELease INDication */
2621testcase TC_rll_rel_ind_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002622 var RSL_Message rx_rsl;
2623 var DchanTuple dt;
2624
2625 f_init(1);
2626
2627 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002628 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002629
2630 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002631 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 +07002632 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002633 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 +07002634
2635 /* MS sends unexpected RELease INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002636 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002637 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2638 f_exp_sapi_n_reject(3, GSM0808_CAUSE_MS_NOT_EQUIPPED);
2639
2640 /* Clean up the connection */
2641 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002642 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002643
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002644 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002645}
2646
2647/* Check if we get SAPI N Reject on receipt of unexpected RLL ERROR INDication */
2648testcase TC_rll_err_ind_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002649 var RSL_Message rx_rsl;
2650 var DchanTuple dt;
2651
2652 f_init(1);
2653
2654 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002655 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002656
2657 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002658 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 +07002659 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002660 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 +07002661
2662 /* BTS sends unexpected ERROR INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002663 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002664 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2665 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED);
2666
2667 /* Clean up the connection */
2668 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002669 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002670
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002671 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002672}
2673
2674/* Check if we get SAPI N Reject due to a SAPI=3 link establishment timeout */
2675testcase TC_rll_timeout_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002676 var RSL_Message rx_rsl;
2677 var DchanTuple dt;
2678
2679 f_init(1);
2680
2681 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002682 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002683
2684 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002685 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 +07002686 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002687 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 +07002688
2689 /* MS does not respond, so the link establishment timeout triggers SAPI N Reject */
2690 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, T_val := 8.0);
2691
2692 /* Clean up the connection */
2693 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002694 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002695
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002696 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002697}
2698
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002699/* Check DLCI CC (Control Channel type) bits in SAPI N Reject */
2700testcase TC_rll_sapi_n_reject_dlci_cc() runs on test_CT {
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002701 var RSL_Message rx_rsl;
2702 var DchanTuple dt;
2703
2704 f_init(1);
2705
2706 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002707 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002708
2709 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002710 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 +07002711 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002712 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 +07002713
2714 /* MS sends unexpected ERROR INDication on DCCH/ACCH SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002715 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Pau Espin Pedrol121f27f2022-01-12 12:02:10 +01002716 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, '10'B);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002717
2718 /* Clean up the connection */
2719 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002720 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002721
2722 f_shutdown_helper();
2723}
2724
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002725testcase TC_si_default() runs on test_CT {
2726 f_init(0);
2727 f_init_bts_and_check_sysinfo(0, expect_si := SystemInformationConfig_default);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002728 f_shutdown_helper();
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002729}
Harald Welte4003d112017-12-09 22:35:39 +01002730
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002731/* We're testing SI2quater with lists of EARFCNs. Instead of just incrementing EARFCNs, also pick some from the edges of
2732 * the entire value range. This function provides the same EARFCN numbers for the same earfcn_index */
2733private function f_test_si2quater_earfcn_by_idx(integer earfcn_index) return uint16_t
2734{
2735 select (earfcn_index) {
2736 case (0) {
2737 /* E-ARFCN 111 is already added in the osmo-bsc.cfg */
2738 return 111;
2739 }
2740 case (1) {
2741 return 1;
2742 }
2743 case (2) {
2744 return 0;
2745 }
2746 case (3) {
2747 return 65535;
2748 }
2749 case else {
2750 return 23 * (earfcn_index - 3);
2751 }
2752 }
2753}
2754
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002755function f_test_si2quater(integer total_earfcns, template SystemInformationConfig expect_si,
2756 template CellSelIndValue expect_cells := omit) runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002757
2758 f_init(0);
2759
2760 /* E-ARFCN 111 is already added in the osmo-bsc.cfg, so only add more arfcns if total_earfcns > 1 */
2761 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002762 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2763 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002764 }
2765
2766 f_init_bts_and_check_sysinfo(0, expect_si := expect_si);
2767
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002768 if (not istemplatekind(expect_cells, "omit")) {
2769 /* Also check that RR Channel Release contains these EARFCNs.
2770 * (copied code from TC_chan_rel_hard_clear_csfb) */
2771 var BSSAP_N_DATA_ind rx_di;
2772 var DchanTuple dt;
2773
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002774 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Pau Espin Pedrold0046312021-04-19 16:35:58 +02002775 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2776 * yet when generating the EUTRAN neigh list in RR CHannel Release) */
2777 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002778
2779 /* Instruct BSC to clear channel */
2780 var BssmapCause cause := 0;
2781 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2782
2783 /* expect Clear Complete from BSC on A */
2784 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2785 /* release the SCCP connection */
2786 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2787 }
2788
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002789 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false, expect_cells := expect_cells);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002790 }
2791
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002792 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002793 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 +02002794 }
2795}
2796
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002797private function f_tr_si2quater_earfcns(integer count) return template SI2quaterRestOctetsList
2798{
2799 var template SI2quaterRestOctetsList si2quater := {};
2800 var integer si2quater_count := (count + 2) / 3;
2801
2802 for (var integer i := 0; i < count; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002803 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002804 var integer index := i / 3;
2805 var integer earfcn_index := i mod 3;
2806 if (index >= lengthof(si2quater)) {
2807 si2quater[index] := tr_SI2quaterRestOctets_EUTRAN(index := index, count := si2quater_count - 1);
2808 }
2809 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);
2810 }
2811
2812 return si2quater;
2813}
2814
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002815private function f_tr_rr_chan_rel_earfcns(integer count) return template CellSelIndValue
2816{
2817 var template CellSelIndValue_EUTRAN_Descrs cells := {};
2818
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002819 /* the lte neighbors must match the config & vty to pass this test */
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002820 for (var integer i := 0; i < count; i := i + 1) {
2821 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002822 cells[i] := tr_CellSelIndValue_EUTRAN_Descr(earfcn, '1'B, 3);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002823 }
2824
2825 return tr_CellSelIndValue_EUTRAN(cells);
2826}
2827
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002828private function f_tc_si2quater_n_earfcns(integer n) runs on test_CT
2829{
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002830 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrol8ab62e42020-12-18 16:19:11 +01002831 sic.si2quater := f_tr_si2quater_earfcns(n);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002832 var template CellSelIndValue cells := f_tr_rr_chan_rel_earfcns(n);
2833 f_test_si2quater(n, sic, cells);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002834}
2835
2836testcase TC_si2quater_2_earfcns() runs on test_CT {
2837 f_tc_si2quater_n_earfcns(2);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002838 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002839}
2840
2841testcase TC_si2quater_3_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002842 f_tc_si2quater_n_earfcns(3);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002843 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002844}
2845
2846testcase TC_si2quater_4_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002847 f_tc_si2quater_n_earfcns(4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002848 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002849}
2850
2851testcase TC_si2quater_5_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002852 f_tc_si2quater_n_earfcns(5);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002853 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002854}
2855
2856testcase TC_si2quater_6_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002857 f_tc_si2quater_n_earfcns(6);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002858 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002859}
2860
2861testcase TC_si2quater_12_earfcns() runs on test_CT {
2862 f_tc_si2quater_n_earfcns(12);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002863 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002864}
2865
2866testcase TC_si2quater_23_earfcns() runs on test_CT {
2867 f_tc_si2quater_n_earfcns(23);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002868 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002869}
2870
2871testcase TC_si2quater_32_earfcns() runs on test_CT {
2872 f_tc_si2quater_n_earfcns(32);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002873 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002874}
2875
2876testcase TC_si2quater_33_earfcns() runs on test_CT {
2877 f_tc_si2quater_n_earfcns(33);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002878 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002879}
2880
2881testcase TC_si2quater_42_earfcns() runs on test_CT {
2882 f_tc_si2quater_n_earfcns(42);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002883 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002884}
2885
2886testcase TC_si2quater_48_earfcns() runs on test_CT {
2887 f_tc_si2quater_n_earfcns(48);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002888 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002889}
2890
2891/* verify the VTY error response when adding too many EARFCNs, and showing that osmo-bsc still sends 16 SI2quater with
2892 * 48 EARFCNs. */
2893testcase TC_si2quater_49_earfcns() runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002894 var template SystemInformationConfig sic := SystemInformationConfig_default;
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002895 sic.si2quater := f_tr_si2quater_earfcns(48); /* 48, not 49! */
2896 f_init(0);
2897
2898 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002899 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2900 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002901 }
2902
2903 /* The 49th EARFCN no longer fits, expect VTY error */
2904 f_vty_enter_cfg_bts(BSCVTY, 0);
2905 var charstring vty_error;
2906 vty_error := f_vty_transceive_ret(BSCVTY,
2907 "si2quater neighbor-list add earfcn 70 thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3")
2908 f_vty_transceive(BSCVTY, "end");
2909
2910 if (f_strstr(vty_error, "Unable to add ARFCN 70") >= 0) {
2911 log("Got expected VTY error: ", vty_error);
2912 setverdict(pass);
2913 } else {
2914 setverdict(fail, "Expected the 49th EUTRAN ARFCN to be rejected by vty config, got: ", vty_error);
2915 }
2916
2917 f_init_bts_and_check_sysinfo(0, expect_si := sic);
2918
2919 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002920 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 +02002921 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002922 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002923}
2924
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002925private function f_acc09_count_allowed(AccessControlClass acc) return uint8_t
2926{
2927 var uint8_t count := 0;
2928 for (var integer i := 5; i < 16; i := i + 1) {
2929 if (acc[i] == '0'B) { /* the list marks barred, we count allowed */
2930 count := count + 1;
2931 }
2932 }
2933 return count;
2934}
2935
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002936private function f_recv_next_si1(integer rsl_idx := 0) runs on test_CT return SystemInformationType1
2937{
2938 var ASP_RSL_Unitdata rx_rsl_ud;
2939 var SystemInformationType1 last_si1;
2940
2941 timer T := 30.0;
2942 T.start;
2943 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002944 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD((tr_RSL_NO_BCCH_INFO,
2945 tr_RSL_BCCH_INFO,
2946 tr_RSL_NO_SACCH_FILL,
2947 tr_RSL_SACCH_FILL))) -> value rx_rsl_ud {
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002948 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
2949 if (g_system_information[rsl_idx].si1 == omit) {
2950 repeat;
2951 }
2952 last_si1 := g_system_information[rsl_idx].si1;
2953 g_system_information[rsl_idx].si1 := omit;
2954 T.stop;
2955 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002956 [] IPA_RSL[rsl_idx][0].receive { repeat; }
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002957 [] T.timeout { setverdict(fail, "Timeout receiving next SI1"); }
2958 }
2959 return last_si1;
2960}
2961
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002962/* verify ACC rotate feature */
2963testcase TC_si_acc_rotate() runs on test_CT {
2964 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002965 var SystemInformationType1 last_si1;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002966 var AccessControlClass acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002967 var uint8_t count;
2968 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2969
2970 f_init(0, guard_timeout := 60.0);
2971
2972 f_bts_0_cfg(BSCVTY, {"rach access-control-class 5 barred",
2973 "access-control-class-rotate 3",
2974 "access-control-class-rotate-quantum 1"});
2975
2976 /* Init and get first sysinfo */
2977 f_init_bts_and_check_sysinfo(0, expect_si := ?);
2978
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002979 for (var integer i:= 0; i < 20; i := i + 1) {
2980 last_si1 := f_recv_next_si1(0);
2981 acc := last_si1.rach_control.acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002982 count := f_acc09_count_allowed(acc);
2983 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
2984
2985 if (count != 3) {
2986 log("RSL: EXPECTED SI ACC len=3");
2987 setverdict(fail, "received SI does not match expectations");
2988 break;
2989 }
2990
2991 for (var integer j := 0; j < 10; j := j + 1) {
2992 if (acc[16 - 1 - j] == '0'B) { /* the list marks barred, we count allowed */
2993 times_allowed[j] := times_allowed[j] + 1;
2994 }
2995 }
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002996 }
2997
2998 for (var integer j := 0; j < 10; j := j + 1) {
2999 log("ACC", j, " allowed ", times_allowed[j], " times" );
3000 if (j != 5 and times_allowed[j] < 3) {
3001 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " < 1 times");
3002 } else if (j == 5 and times_allowed[j] > 0) {
3003 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " > 0 times");
3004 }
3005 }
3006
3007 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
3008 "rach access-control-class 5 allowed"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003009 f_shutdown_helper();
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003010}
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02003011
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003012/* verify ACC startup ramp+rotate feature */
3013testcase TC_si_acc_ramp_rotate() runs on test_CT {
3014 var template SystemInformationConfig sic := SystemInformationConfig_default;
3015 var SystemInformationType1 last_si1;
3016 var AccessControlClass acc;
3017 var ASP_RSL_Unitdata rx_rsl_ud;
3018 var uint8_t count;
3019 var uint8_t prev_count;
3020 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
3021
3022 f_init(0, guard_timeout := 80.0);
3023
3024 f_bts_0_cfg(BSCVTY, {"rach access-control-class 4 barred",
3025 "access-control-class-rotate 0",
3026 "access-control-class-rotate-quantum 1",
3027 "access-control-class-ramping",
3028 "access-control-class-ramping-step-interval 5",
3029 "access-control-class-ramping-step-size 5"});
3030
3031 /* Init and get first sysinfo */
3032 f_init_bts_and_check_sysinfo(0, expect_si := ?);
3033 last_si1 := g_system_information[0].si1;
3034 acc := last_si1.rach_control.acc;
3035 count := f_acc09_count_allowed(acc);
3036 /* Adm subset size was set to 0 above, so wait until all ACC are barred */
3037 while (count > 0) {
3038 last_si1 := f_recv_next_si1(0);
3039 acc := last_si1.rach_control.acc;
3040 count := f_acc09_count_allowed(acc);
3041 log("RSL: wait len()=0: GOT SI1 ACC len=", count, ": ", acc);
3042 }
3043
3044 /* Increase adm subset size, we should see ramping start up */
3045 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10"});
3046 prev_count := 0;
3047 while (true) {
3048 last_si1 := f_recv_next_si1(0);
3049 acc := last_si1.rach_control.acc;
3050 count := f_acc09_count_allowed(acc);
3051 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
3052
3053 if (prev_count > count) {
3054 setverdict(fail, "ACC allowed count dropped while expecting grow: ", prev_count, " -> ", count);
3055 break;
3056 }
3057
3058 if (count == 9) {
3059 break; /* Maximum reached (10 - 1 perm barred), done here */
3060 }
3061
3062 prev_count := count;
3063 }
3064
3065 setverdict(pass);
3066
3067 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
3068 "rach access-control-class 4 allowed",
3069 "no access-control-class-ramping"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003070 f_shutdown_helper();
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003071}
3072
Harald Welte4003d112017-12-09 22:35:39 +01003073testcase TC_ctrl_msc_connection_status() runs on test_CT {
3074 var charstring ctrl_resp;
3075
Harald Welte89d42e82017-12-17 16:42:41 +01003076 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003077
3078 /* See https://osmocom.org/issues/2729 */
3079 f_ctrl_get_exp(IPA_CTRL, "msc_connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003080 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01003081}
3082
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003083testcase TC_ctrl_msc0_connection_status() runs on test_CT {
3084 var charstring ctrl_resp;
3085
3086 f_init(1);
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003087
3088 f_ctrl_get_exp(IPA_CTRL, "msc.0.connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003089 f_shutdown_helper();
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003090}
3091
Neels Hofmeyr0bc470d2021-08-21 13:37:13 +02003092/* Verify correct stats on the number of configured and connected MSCs */
3093private function f_tc_stat_num_msc_connected_msc_connhdlr(integer expect_num_msc_connected) runs on MSC_ConnHdlr {
3094 g_pars := f_gen_test_hdlr_pars();
3095 var StatsDExpects expect := {
3096 { name := "TTCN3.bsc.0.num_msc.connected", mtype := "g", min := expect_num_msc_connected, max := expect_num_msc_connected },
3097 { name := "TTCN3.bsc.0.num_msc.total", mtype := "g", min := NUM_MSC, max := NUM_MSC }
3098 };
3099 f_statsd_expect(expect);
3100}
3101
3102private function f_tc_stat_num_msc_connected_test_ct(void_fn tc_fn, integer nr_msc) runs on test_CT
3103{
3104 var MSC_ConnHdlr vc_conn;
3105
3106 f_init(nr_bts := 1, handler_mode := true, nr_msc := nr_msc);
3107 f_sleep(1.0);
3108 vc_conn := f_start_handler(tc_fn);
3109 vc_conn.done;
3110
3111 /* Also verify stat exposed on CTRL interface */
3112 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:connected", int2str(nr_msc));
3113 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:total", int2str(NUM_MSC));
3114
3115 f_shutdown_helper();
3116}
3117
3118/* Verify that when 1 MSC is active, that num_msc:connected reports 1. */
3119private function f_tc_stat_num_msc_connected_1(charstring id) runs on MSC_ConnHdlr {
3120 f_tc_stat_num_msc_connected_msc_connhdlr(1);
3121}
3122testcase TC_stat_num_msc_connected_1() runs on test_CT {
3123 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_1), 1);
3124}
3125
3126/* Verify that when 2 MSCs are active, that num_msc:connected reports 2. */
3127private function f_tc_stat_num_msc_connected_2(charstring id) runs on MSC_ConnHdlr {
3128 f_tc_stat_num_msc_connected_msc_connhdlr(2);
3129}
3130testcase TC_stat_num_msc_connected_2() runs on test_CT {
3131 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_2), 2);
3132}
3133
3134/* Verify that when 3 MSCs are active, that num_msc:connected reports 3. */
3135private function f_tc_stat_num_msc_connected_3(charstring id) runs on MSC_ConnHdlr {
3136 f_tc_stat_num_msc_connected_msc_connhdlr(3);
3137}
3138testcase TC_stat_num_msc_connected_3() runs on test_CT {
3139 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_3), 3);
3140}
3141
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003142/* Verify correct stats on the number of configured and connected MSCs */
3143private 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 +06003144 var integer num_trx_connected := 0;
3145 var integer num_trx_total := 0;
3146
3147 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3148 var integer trx_num := c_BtsParams[i].trx_num;
3149 num_trx_total := num_trx_total + trx_num;
3150 if (i < expect_num_bts_connected) {
3151 num_trx_connected := num_trx_connected + trx_num;
3152 }
3153 }
3154
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003155 var StatsDExpects expect := {
3156 { name := "TTCN3.bsc.0.num_bts.oml_connected", mtype := "g", min := expect_num_bts_connected, max := NUM_BTS_CFG },
3157 { name := "TTCN3.bsc.0.num_bts.all_trx_rsl_connected", mtype := "g", min := expect_num_bts_connected, max := expect_num_bts_connected },
3158 { name := "TTCN3.bsc.0.num_bts.total", mtype := "g", min := NUM_BTS_CFG, max := NUM_BTS_CFG },
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003159 { name := "TTCN3.bsc.0.num_trx.rsl_connected", mtype := "g", min := num_trx_connected, max := num_trx_connected },
3160 { name := "TTCN3.bsc.0.num_trx.total", mtype := "g", min := num_trx_total, max := num_trx_total }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003161 };
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003162
3163 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003164 f_statsd_expect(expect);
3165}
3166
3167private 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 +06003168 var integer num_trx_connected := 0;
3169 var integer num_trx_total := 0;
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003170 var MSC_ConnHdlr vc_conn;
3171
3172 f_init(nr_bts := nr_bts, handler_mode := true, nr_msc := 1);
3173 f_sleep(1.0);
3174 vc_conn := f_start_handler(tc_fn);
3175 vc_conn.done;
3176
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003177 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3178 var integer trx_num := c_BtsParams[i].trx_num;
3179 num_trx_total := num_trx_total + trx_num;
3180 if (i < nr_bts) {
3181 num_trx_connected := num_trx_connected + trx_num;
3182 }
3183 }
3184
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003185 /* Also verify stat exposed on CTRL interface */
3186 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_bts:all_trx_rsl_connected", int2str(nr_bts));
3187 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 +06003188 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_trx:rsl_connected", int2str(num_trx_connected));
3189 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 +02003190
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003191 /* Verify rf_states exposed on CTRL interface */
3192 var charstring expect_net_rf_states := "";
3193 for (var integer i := 0; i < NUM_BTS_CFG; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003194 var charstring expect_bts_rf_states := "";
3195
3196 for (var integer j := 0; j < c_BtsParams[i].trx_num; j := j + 1) {
3197 expect_bts_rf_states := expect_bts_rf_states &
3198 int2str(i) & "," & int2str(j) & ",";
3199 if (i < NUM_BTS) {
3200 /* In these tests, OML for the first NUM_BTS are always connected via osmo-bts-omldummy */
3201 expect_bts_rf_states := expect_bts_rf_states & "operational,unlocked,";
3202 } else {
3203 /* For remaining i < NUM_BTS_CFG, OML is not connected, i.e. inoperational */
3204 expect_bts_rf_states := expect_bts_rf_states & "inoperational,locked,";
3205 }
3206 /* The RF policy is still global in osmo-bsc, i.e. always "on" */
3207 expect_bts_rf_states := expect_bts_rf_states & "on,";
3208 if (i < nr_bts) {
3209 /* For BTS where RSL is connected, the RSL state will be "up" */
3210 expect_bts_rf_states := expect_bts_rf_states & "rsl-up;";
3211 } else {
3212 expect_bts_rf_states := expect_bts_rf_states & "rsl-down;";
3213 }
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003214 }
3215
3216 f_ctrl_get_exp(IPA_CTRL, "bts." & int2str(i) & ".rf_states", expect_bts_rf_states);
3217 expect_net_rf_states := expect_net_rf_states & expect_bts_rf_states;
3218 }
3219 f_ctrl_get_exp(IPA_CTRL, "rf_states", expect_net_rf_states);
3220
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003221 f_shutdown_helper();
3222}
3223
3224/* Verify that when 1 BTS is connected, that num_{bts,trx}:*_connected reports 1. */
3225private function f_tc_stat_num_bts_connected_1(charstring id) runs on MSC_ConnHdlr {
3226 f_tc_stat_num_bts_connected_msc_connhdlr(1);
3227}
3228testcase TC_stat_num_bts_connected_1() runs on test_CT {
3229 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_1), 1);
3230}
3231
3232/* Verify that when 2 BTS is connected, that num_{bts,trx}:*_connected reports 2. */
3233private function f_tc_stat_num_bts_connected_2(charstring id) runs on MSC_ConnHdlr {
3234 f_tc_stat_num_bts_connected_msc_connhdlr(2);
3235}
3236testcase TC_stat_num_bts_connected_2() runs on test_CT {
3237 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_2), 2);
3238}
3239
3240/* Verify that when 3 BTS is connected, that num_{bts,trx}:*_connected reports 3. */
3241private function f_tc_stat_num_bts_connected_3(charstring id) runs on MSC_ConnHdlr {
3242 f_tc_stat_num_bts_connected_msc_connhdlr(3);
3243}
3244testcase TC_stat_num_bts_connected_3() runs on test_CT {
3245 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_3), 3);
3246}
3247
Harald Welte4003d112017-12-09 22:35:39 +01003248testcase TC_ctrl() runs on test_CT {
3249 var charstring ctrl_resp;
3250
Harald Welte89d42e82017-12-17 16:42:41 +01003251 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003252
3253 /* all below values must match the osmo-bsc.cfg config file used */
3254
Harald Welte6a129692018-03-17 17:30:14 +01003255 f_ctrl_get_exp(IPA_CTRL, "mcc", "001");
3256 f_ctrl_get_exp(IPA_CTRL, "mnc", "01");
Oliver Smith75aa0202019-08-19 14:17:50 +02003257 f_ctrl_get_exp(IPA_CTRL, "number-of-bts", "4");
Harald Welte4003d112017-12-09 22:35:39 +01003258
3259 var integer bts_nr := 0;
3260 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "location-area-code", "1");
3261 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "cell-identity", "0");
3262 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "oml-connection-state", "connected");
3263 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "gprs-mode", "gprs");
3264 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "rf_state", "operational,unlocked,on");
3265 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "arfcn", "871");
3266 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "max-power-reduction", "20");
3267
3268 var integer uptime := str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime"));
3269 f_sleep(2.0);
3270 if (str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime")) < uptime+1) {
3271 setverdict(fail, "oml-uptime not incrementing as expected");
3272 }
3273 /* TODO: Disconnect RSL, imply that OML is disconnected and check for uptime zero? */
3274
3275 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", 0);
3276
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003277 f_shutdown_helper();
Harald Welte96c94412017-12-09 03:12:45 +01003278}
3279
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003280/* Verify that Upon receival of SET "location", BSC forwards a TRAP
3281 "location-state" over the SCCPlite IPA conn */
3282testcase TC_ctrl_location() runs on test_CT {
3283 var MSC_ConnHdlr vc_conn;
3284 var integer bts_nr := 0;
3285
3286 f_init(1, true);
3287 f_sleep(1.0);
3288
3289 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234567,fix3d,0.340000,0.560000,0.780000");
3290 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3291 "1234567,fix3d,0.340000,0.560000,0.780000,operational,unlocked,on,001,01");
3292
3293 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "1");
3294 f_sleep(2.0);
3295
3296 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234888,fix3d,0.350000,0.570000,0.790000");
3297 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3298 "1234888,fix3d,0.350000,0.570000,0.790000,operational,locked,off,001,01");
3299
3300 /* should match the one from config */
3301 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "0");
3302
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003303 f_shutdown_helper();
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003304}
3305
Harald Welte6f521d82017-12-11 19:52:02 +01003306
3307/***********************************************************************
3308 * Paging Testing
3309 ***********************************************************************/
3310
3311type record Cell_Identity {
3312 GsmMcc mcc,
3313 GsmMnc mnc,
3314 GsmLac lac,
3315 GsmCellId ci
3316};
Harald Welte24135bd2018-03-17 19:27:53 +01003317private const Cell_Identity cid := { '001'H, '01'H, 1, 0 };
Stefan Sperling049a86e2018-03-20 15:51:00 +01003318private const Cell_Identity unknown_cid := { '678'H, 'f90'H, 1, 0 };
Harald Welte6f521d82017-12-11 19:52:02 +01003319
Harald Welte5d1a2202017-12-13 19:51:29 +01003320type set of integer BtsIdList;
3321
3322private function f_bts_in_list(integer bts_id, BtsIdList bts_ids) return boolean {
3323 for (var integer j := 0; j < sizeof(bts_ids); j := j + 1) {
3324 if (bts_id == bts_ids[j]) {
3325 return true;
3326 }
3327 }
3328 return false;
3329}
Harald Welte6f521d82017-12-11 19:52:02 +01003330
3331/* core paging test helper function; used by most paging test cases */
3332private function f_pageing_helper(hexstring imsi,
3333 template BSSMAP_FIELD_CellIdentificationList cid_list,
Harald Welte5d1a2202017-12-13 19:51:29 +01003334 BtsIdList bts_ids := { 0 },
Harald Welte6f521d82017-12-11 19:52:02 +01003335 template RSL_ChanNeeded rsl_chneed := omit,
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003336 template (omit) OCT4 tmsi := omit) runs on test_CT
Harald Welte6f521d82017-12-11 19:52:02 +01003337{
3338 var template BSSMAP_IE_ChannelNeeded bssmap_chneed;
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003339 var template MobileIdentityV mi;
Harald Welte6f521d82017-12-11 19:52:02 +01003340 var RSL_Message rx_rsl;
3341 var integer paging_group := hex2int(imsi[lengthof(imsi)-1]);
Harald Welte5d1a2202017-12-13 19:51:29 +01003342 var integer i;
Harald Welte6f521d82017-12-11 19:52:02 +01003343
3344 f_init();
Harald Welte6f521d82017-12-11 19:52:02 +01003345
3346 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Harald Weltec3068592018-03-17 19:55:31 +01003347 for (i := 0; i < NUM_BTS; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003348 IPA_RSL[i][0].clear;
Harald Welte5d1a2202017-12-13 19:51:29 +01003349 }
Harald Welte6f521d82017-12-11 19:52:02 +01003350
3351 if (isvalue(rsl_chneed)) {
3352 /* The values of 08.08 3.2.2.36 and 08.58 9.3.40 are luckily identical */
3353 bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
3354 } else {
3355 bssmap_chneed := omit;
3356 }
3357
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003358 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own,
3359 ts_BSSMAP_Paging(imsi, cid_list, tmsi, bssmap_chneed)));
Harald Welte6f521d82017-12-11 19:52:02 +01003360
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003361 if (not istemplatekind(tmsi, "omit")) {
3362 mi := t_MI_TMSI(tmsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003363 } else {
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003364 mi := tr_MI_IMSI(imsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003365 }
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003366
Harald Welte5d1a2202017-12-13 19:51:29 +01003367 for (i := 0; i < sizeof(bts_ids); i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003368 rx_rsl := f_exp_ipa_rx(tr_RSL_PAGING_CMD(mi), idx := {bts_ids[i], 0});
Harald Welte5d1a2202017-12-13 19:51:29 +01003369 /* check channel type, paging group */
3370 if (rx_rsl.ies[1].body.paging_group != paging_group) {
3371 setverdict(fail, "Paging for wrong paging group");
3372 }
3373 if (ispresent(rsl_chneed) and
3374 rx_rsl.ies[3].body.chan_needed.chan_needed != valueof(rsl_chneed)) {
3375 setverdict(fail, "RSL Channel Needed != BSSMAP Channel Needed");
3376 }
Harald Welte6f521d82017-12-11 19:52:02 +01003377 }
Harald Welte2fccd982018-01-31 15:48:19 +01003378 f_sleep(2.0);
Harald Welte5d1a2202017-12-13 19:51:29 +01003379 /* do a quick check on all not-included BTSs if they received paging */
3380 for (i := 0; i < NUM_BTS; i := i + 1) {
3381 timer T := 0.1;
3382 if (f_bts_in_list(i, bts_ids)) {
3383 continue;
3384 }
3385 T.start;
3386 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003387 [] IPA_RSL[i][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(mi))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003388 setverdict(fail, "Paging on BTS ", i, " which is not part of ", bts_ids);
3389 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003390 [] IPA_RSL[i][0].receive { repeat; }
Harald Welte5d1a2202017-12-13 19:51:29 +01003391 [] T.timeout { }
3392 }
Harald Welte6f521d82017-12-11 19:52:02 +01003393 }
3394
3395 setverdict(pass);
3396}
3397
Harald Welte5d1a2202017-12-13 19:51:29 +01003398const BtsIdList c_BtsId_all := { 0, 1, 2 };
Harald Welte751d3eb2018-01-31 15:51:06 +01003399const BtsIdList c_BtsId_none := { };
Harald Welte5d1a2202017-12-13 19:51:29 +01003400const BtsIdList c_BtsId_LAC1 := { 0, 1 };
3401const BtsIdList c_BtsId_LAC2 := { 2 };
3402
Harald Welte6f521d82017-12-11 19:52:02 +01003403/* PAGING by IMSI + TMSI */
3404testcase TC_paging_imsi_nochan() runs on test_CT {
3405 var BSSMAP_FIELD_CellIdentificationList cid_list;
3406 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Philipp Maier8c04b0a2018-02-23 13:48:48 +01003407 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, omit);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003408 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003409}
3410
3411/* PAGING by IMSI + TMSI */
3412testcase TC_paging_tmsi_nochan() runs on test_CT {
3413 var BSSMAP_FIELD_CellIdentificationList cid_list;
3414 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003415 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, 'A1B2C301'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003416 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003417}
3418
3419/* Paging with different "channel needed' values */
3420testcase TC_paging_tmsi_any() runs on test_CT {
3421 var BSSMAP_FIELD_CellIdentificationList cid_list;
3422 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003423 f_pageing_helper('001010100000002'H, cid_list, c_BtsId_all, RSL_CHANNEED_ANY, 'A1B2C302'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003424 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003425}
3426testcase TC_paging_tmsi_sdcch() runs on test_CT {
3427 var BSSMAP_FIELD_CellIdentificationList cid_list;
3428 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003429 f_pageing_helper('001010100000003'H, cid_list, c_BtsId_all, RSL_CHANNEED_SDCCH, 'A1B2C303'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003430 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003431}
3432testcase TC_paging_tmsi_tch_f() 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('001010000000004'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_F, 'A1B2C304'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003436 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003437}
3438testcase TC_paging_tmsi_tch_hf() 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('001010000000005'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_ForH, 'A1B2C305'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003442 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003443}
3444
3445/* Paging by CGI */
3446testcase TC_paging_imsi_nochan_cgi() runs on test_CT {
3447 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3448 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(cid.mcc, cid.mnc, cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003449 f_pageing_helper('001010000000006'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003450 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003451}
3452
3453/* Paging by LAC+CI */
3454testcase TC_paging_imsi_nochan_lac_ci() runs on test_CT {
3455 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3456 cid_list := { cIl_LAC_CI := { ts_BSSMAP_CI_LAC_CI(cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003457 f_pageing_helper('001010000000007'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003458 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003459}
3460
3461/* Paging by CI */
3462testcase TC_paging_imsi_nochan_ci() runs on test_CT {
3463 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3464 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003465 f_pageing_helper('001010000000008'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003466 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003467}
3468
3469/* Paging by LAI */
3470testcase TC_paging_imsi_nochan_lai() runs on test_CT {
3471 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3472 cid_list := { cIl_LAI := { ts_BSSMAP_CI_LAI(cid.mcc, cid.mnc, cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003473 f_pageing_helper('001010000000009'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003474 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003475}
3476
3477/* Paging by LAC */
3478testcase TC_paging_imsi_nochan_lac() runs on test_CT {
3479 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3480 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003481 f_pageing_helper('001010000000010'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003482 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003483}
3484
3485/* Paging by "all in BSS" */
3486testcase TC_paging_imsi_nochan_all() runs on test_CT {
3487 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3488 cid_list := { cIl_allInBSS := ''O };
Harald Welte5d1a2202017-12-13 19:51:29 +01003489 f_pageing_helper('001010000000011'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003490 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003491}
3492
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003493/* Paging by PLMN+LAC+RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003494testcase TC_paging_imsi_nochan_plmn_lac_rnc() runs on test_CT {
3495 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3496 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 +01003497 f_pageing_helper('001010000000012'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003498 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003499}
Harald Welte6f521d82017-12-11 19:52:02 +01003500
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003501/* Paging by RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003502testcase TC_paging_imsi_nochan_rnc() runs on test_CT {
3503 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3504 cid_list := { cIl_RNC := { int2oct(13, 2) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003505 f_pageing_helper('001010000000013'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003506 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003507}
3508
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003509/* Paging by LAC+RNC; We do not implement; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003510testcase TC_paging_imsi_nochan_lac_rnc() runs on test_CT {
3511 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3512 cid_list := { cIl_LAC_RNC := { ts_BSSMAP_CI_LAC_RNC(cid.lac, 14) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003513 f_pageing_helper('001010000000014'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003514 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003515}
3516
Harald Welte6f521d82017-12-11 19:52:02 +01003517/* Paging on multiple cells (multiple entries in list): Verify all of them page */
Harald Welte751d3eb2018-01-31 15:51:06 +01003518testcase TC_paging_imsi_nochan_lacs() runs on test_CT {
3519 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3520 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(1), ts_BSSMAP_CI_LAC(2) } };
3521 f_pageing_helper('001010000000015'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003522 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003523}
3524
3525/* Paging on empty list: Verify none of them page */
3526testcase TC_paging_imsi_nochan_lacs_empty() runs on test_CT {
3527 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3528 cid_list := { cIl_LAC := { } };
3529 f_pageing_helper('001010000000016'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003530 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003531}
3532
Stefan Sperling049a86e2018-03-20 15:51:00 +01003533/* Paging by CGI with unknown MCC/MNC: Verify nothing is paged. */
3534testcase TC_paging_imsi_nochan_cgi_unknown_cid() runs on test_CT {
3535 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3536 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(unknown_cid.mcc, unknown_cid.mnc, unknown_cid.lac, unknown_cid.ci) } };
3537 f_pageing_helper('001010000000006'H, cid_list, c_BtsId_none);
3538 f_shutdown_helper();
3539}
3540
Pau Espin Pedrol07657ae2023-01-03 12:08:05 +01003541/* Send paging response containing invalid (wrongly formatted) MobileIdentity IE. */
3542testcase TC_paging_imsi_nochan_ci_resp_invalid_mi() runs on test_CT {
3543 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3544 var BSSAP_N_CONNECT_ind rx_c_ind;
3545 var DchanTuple dt;
3546 var octetstring rr_pag_resp := '06270003535992617965720000'O;
3547 /* { 06 27 } is { GSM48_PDISC_RR, GSM48_MT_RR_PAG_RESP }
3548 * see 3GPP TS 44.018, table 9.1.25.1
3549 * { 00 } or { 01 } is CKSN + Spare Half Octet, not important
3550 * { 03 53 59 92 } is Mobile Station Classmark
3551 * { 61 79 65 72 00 00 } is the invalid Mobile Identity IE (3GPP TS 24.008, 10.5.1.4),
3552 * Length is 0x61 (97 in decimal).
3553 */
3554
3555 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
3556 f_pageing_helper('001010000000008'H, cid_list, { 0 });
3557
3558 /* Send CHAN RQD and wait for allocation; acknowledge it */
3559 dt.rsl_chan_nr := f_chreq_act_ack();
3560 dt.idx := {0, 0};
3561
3562 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
3563 f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), rr_pag_resp));
3564
3565 /* Expevct a CR with a matching Paging response on the A-Interface */
3566 timer T := 5.0;
3567 T.start;
3568 alt {
3569 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
3570 setverdict(pass);
3571 dt.sccp_conn_id := rx_c_ind.connectionId;
3572 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
3573 }
3574 [] BSSAP.receive {
3575 setverdict(fail, "Received unexpected message on A-Interface!");
3576 }
3577 [] T.timeout {
3578 setverdict(fail, "Received nothing on A-Interface!");
3579 }
3580 }
3581
3582 f_perform_clear_test_ct(dt);
3583 f_shutdown_helper();
3584}
3585
Harald Welte6f521d82017-12-11 19:52:02 +01003586/* Verify paging retransmission interval + count */
3587/* Verify paging stops after channel establishment */
Harald Welte6f521d82017-12-11 19:52:02 +01003588/* Test behavior under paging overload */
Harald Welteae026692017-12-09 01:03:01 +01003589
Harald Weltee65d40e2017-12-13 00:09:06 +01003590/* Verify PCH load */
3591testcase TC_paging_imsi_load() runs on test_CT {
3592 var BSSMAP_FIELD_CellIdentificationList cid_list;
3593 timer T := 4.0;
Harald Welte2caa1062018-03-17 18:19:05 +01003594 timer T_retrans := 1.0;
Harald Weltee65d40e2017-12-13 00:09:06 +01003595 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003596 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Weltee65d40e2017-12-13 00:09:06 +01003597
3598 /* tell BSC there is no paging space anymore */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003599 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte3b57ab52018-03-17 18:01:10 +01003600 f_sleep(0.2);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003601 IPA_RSL[0][0].clear;
Harald Weltee65d40e2017-12-13 00:09:06 +01003602
3603 /* Wait for 4 seconds if any more PAGING CMD are received on RSL. Normally,
3604 * there would be 8 retransmissions during 4 seconds */
3605 T.start;
Harald Welte2caa1062018-03-17 18:19:05 +01003606 T_retrans.start;
Harald Weltee65d40e2017-12-13 00:09:06 +01003607 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003608 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Weltee65d40e2017-12-13 00:09:06 +01003609 setverdict(fail, "Received PAGING after LOAD_IND(0)");
Daniel Willmannafce8662018-07-06 23:11:32 +02003610 mtc.stop;
Harald Weltee65d40e2017-12-13 00:09:06 +01003611 }
Harald Welte2caa1062018-03-17 18:19:05 +01003612 [] T_retrans.timeout {
3613 /* re-trnsmit the zero-space LOAD IND to avoid BSC 'auto credit' */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003614 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte2caa1062018-03-17 18:19:05 +01003615 T_retrans.start;
3616 repeat;
3617 }
Harald Weltee65d40e2017-12-13 00:09:06 +01003618 [] T.timeout {
3619 setverdict(pass);
3620 }
3621 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003622
3623 f_shutdown_helper();
Harald Weltee65d40e2017-12-13 00:09:06 +01003624}
3625
Harald Welte235ebf12017-12-15 14:18:16 +01003626/* Verify Paging Counter */
Harald Welte1ff69992017-12-14 12:31:17 +01003627testcase TC_paging_counter() runs on test_CT {
3628 var BSSMAP_FIELD_CellIdentificationList cid_list;
3629 timer T := 4.0;
3630 var integer i;
3631 var integer paging_attempted_bsc;
3632 var integer paging_attempted_bts[NUM_BTS];
Oliver Smith8b343d32021-11-26 13:01:42 +01003633 var integer paging_expired_bsc;
Harald Welte1ff69992017-12-14 12:31:17 +01003634 var integer paging_expired_bts[NUM_BTS];
3635 cid_list := valueof(ts_BSSMAP_CIL_noCell);
3636
3637 f_init();
3638
3639 /* read counters before paging */
3640 paging_attempted_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted");
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01003641 paging_expired_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired");
Harald Welte1ff69992017-12-14 12:31:17 +01003642 for (i := 0; i < NUM_BTS; i := i+1) {
3643 paging_attempted_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted");
3644 paging_expired_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired");
3645 }
3646
3647 f_pageing_helper('001230000000001'H, cid_list, c_BtsId_all);
3648
3649 /* expect the attempted pages on BSC and each BTSs to have incremented by one */
3650 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", paging_attempted_bsc+1);
3651 for (i := 0; i < NUM_BTS; i := i+1) {
3652 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted",
3653 paging_attempted_bts[i]+1);
3654 }
3655
3656 /* assume that 12s later the paging on all BTSs have expired and hence incremented by 1 */
3657 f_sleep(12.0);
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01003658 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired", paging_expired_bsc+1);
Harald Welte1ff69992017-12-14 12:31:17 +01003659 for (i := 0; i < NUM_BTS; i := i+1) {
3660 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired",
3661 paging_expired_bts[i]+1);
3662 }
Harald Welte1ff69992017-12-14 12:31:17 +01003663
Philipp Maier282ca4b2018-02-27 17:17:00 +01003664 f_shutdown_helper();
Harald Welte1ff69992017-12-14 12:31:17 +01003665}
3666
3667
Harald Welte10985002017-12-12 09:29:15 +01003668/* Verify paging stops after A-RESET */
3669testcase TC_paging_imsi_a_reset() runs on test_CT {
3670 var BSSMAP_FIELD_CellIdentificationList cid_list;
3671 timer T := 3.0;
3672 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003673 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Welte10985002017-12-12 09:29:15 +01003674
3675 /* Perform a BSSMAP Reset and wait for ACK */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003676 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 +01003677 alt {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003678 [] 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 +01003679 [] BSSAP.receive { repeat; }
3680 }
3681
Daniel Willmanncbef3982018-07-30 09:22:40 +02003682 /* Wait to avoid a possible race condition if a paging message is
3683 * received right before the reset ACK. */
3684 f_sleep(0.2);
3685
Harald Welte10985002017-12-12 09:29:15 +01003686 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Philipp Maier1e6b4422018-02-23 14:02:13 +01003687 for (var integer i := 0; i < sizeof(IPA_RSL); i := i+1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003688 IPA_RSL[i][0].clear;
Philipp Maier1e6b4422018-02-23 14:02:13 +01003689 }
Harald Welte10985002017-12-12 09:29:15 +01003690
3691 /* Wait for 3 seconds if any more PAGING CMD are received on RSL */
3692 T.start;
3693 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003694 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte10985002017-12-12 09:29:15 +01003695 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003696 mtc.stop;
Harald Welte10985002017-12-12 09:29:15 +01003697 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003698 [] IPA_RSL[1][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003699 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003700 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003701 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003702 [] IPA_RSL[2][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003703 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003704 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003705 }
Harald Welte10985002017-12-12 09:29:15 +01003706 [] T.timeout {
3707 setverdict(pass);
3708 }
3709 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003710
3711 f_shutdown_helper();
Harald Welte10985002017-12-12 09:29:15 +01003712}
Harald Welteae026692017-12-09 01:03:01 +01003713
Philipp Maierf45824a2019-08-14 14:44:10 +02003714/* Verify how we handle unsolicited Paging Response. In case of an unsolicit
3715 * paging response we can not know which MSC is in charge, so we will blindly
3716 * pick the first configured MSC. This behavior is required in order to make
3717 * MT-CSFB calls working because in those cases the BSC can not know that the
3718 * MSC has already paged the subscriver via SGs. So any MT-CSFB call will look
3719 * like an unsolicited Paging Response to the MSC.
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003720 */
3721testcase TC_paging_resp_unsol() runs on test_CT {
3722
3723 f_init(1);
Philipp Maierf45824a2019-08-14 14:44:10 +02003724 timer T := 5.0;
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003725
3726 var BSSAP_N_CONNECT_ind rx_c_ind;
3727 var DchanTuple dt;
3728 var PDU_ML3_MS_NW l3 := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010008880018'H))));
Philipp Maierf45824a2019-08-14 14:44:10 +02003729 var octetstring rr_pag_resp := enc_PDU_ML3_MS_NW(l3);
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003730
3731 /* Send CHAN RQD and wait for allocation; acknowledge it */
3732 dt.rsl_chan_nr := f_chreq_act_ack();
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003733 dt.idx := {0, 0};
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003734
3735 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
Pau Espin Pedrole8a51012023-01-03 11:59:59 +01003736 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 +01003737
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003738
Philipp Maierf45824a2019-08-14 14:44:10 +02003739 /* Expevct a CR with a matching Paging response on the A-Interface */
3740 T.start;
3741 alt {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003742 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
Philipp Maierf45824a2019-08-14 14:44:10 +02003743 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003744 dt.sccp_conn_id := rx_c_ind.connectionId;
3745 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
Philipp Maierf45824a2019-08-14 14:44:10 +02003746 }
3747 [] BSSAP.receive {
3748 setverdict(fail, "Received unexpected message on A-Interface!");
3749 }
3750 [] T.timeout {
3751 setverdict(fail, "Received nothing on A-Interface!");
3752 }
3753 }
3754
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003755 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003756 f_shutdown_helper();
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003757}
3758
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003759/* Verify BSC can schedule N paging requests under one minute if BTS buffer is good enough */
3760function f_TC_paging_Nreq(integer num_subscribers, boolean send_pag_load_ind) runs on test_CT {
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003761 var ASP_RSL_Unitdata rx_rsl_ud;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003762 var Hexstrings imsis := {};
3763 var Booleans rx_paging_done := {};
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003764 var integer rx_paging_num := 0;
3765 var integer i;
3766 timer T_rx := 60.0;
3767 timer T_load_ind := 1.0;
3768
3769 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003770 imsis := imsis & {f_gen_imsi(i)};
3771 rx_paging_done := rx_paging_done & { false };
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003772 }
3773
3774 f_init(1, guard_timeout := 100.0);
3775
3776 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003777 IPA_RSL[0][0].clear;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003778 if (send_pag_load_ind) {
3779 /* Tell there's plenty of space at the BTS (UINT16_MAX): */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003780 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(65535));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003781 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003782
3783 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003784 /* Page on LAC-CI of BTS0: */
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003785 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 +02003786 ts_BSSMAP_Paging(imsis[i], valueof(ts_BSSMAP_CIL_LAC_CI({ts_BSSMAP_CI_LAC_CI(1, 0)})),
3787 omit, omit)));
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003788 }
3789
3790 T_rx.start;
3791 T_load_ind.start;
3792 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003793 [] 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 +02003794 var hexstring imsi := rx_rsl_ud.rsl.ies[2].body.ms_identity.mobileIdentityV.oddEvenInd_identity.imsi.digits;
3795 var hexstring imsi_suffix := substr(imsi, lengthof(imsi)-6, 6);
3796 var charstring imsi_str := hex2str(imsi_suffix);
3797 var integer imsi_idx := str2int(imsi_str);
3798 if (rx_paging_done[imsi_idx] == false) {
3799 rx_paging_done[imsi_idx] := true;
3800 rx_paging_num := rx_paging_num + 1;
Pau Espin Pedrolef7ef632022-04-25 13:34:57 +02003801 } else {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003802 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 +02003803 mtc.stop;
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003804 }
3805 if (rx_paging_num < num_subscribers) {
3806 repeat;
3807 }
3808 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003809 [] IPA_RSL[0][0].receive { repeat; }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003810 [] T_load_ind.timeout {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003811 log("[CCH Load Ind timer] received paging requests so far: ", rx_paging_num);
3812 if (send_pag_load_ind) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003813 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(40));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003814 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003815 T_load_ind.start;
3816 repeat;
3817 }
3818 [] T_rx.timeout {
3819 setverdict(fail, "Timeout expecting paging requests, so far ", rx_paging_num);
3820 mtc.stop;
3821 }
3822 }
3823
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003824 /* Drop OML connection to have all paging requests flushed: */
3825 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
3826
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003827 f_shutdown_helper();
3828}
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003829/* Verify BSC can schedule 500 paging requests under one minute if BTS buffer is good enough */
3830testcase TC_paging_500req() runs on test_CT {
3831 f_TC_paging_Nreq(500, true);
3832}
3833/* Same as TC_paging_500req, but without sending CCCH Load Indication, which
3834 * means BTS is always under CCH Load Threshold, aka capable of sending tons of requests.
3835 * Since No CCCH Load Ind, BSC uses a conservative estimation of BTS load, which
3836 * for current config yields ~8req/sec, so 480req/min maximum. */
3837testcase TC_paging_450req_no_paging_load_ind() runs on test_CT {
3838 f_TC_paging_Nreq(450, false);
3839}
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003840
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003841/* Test RSL link drop causes counter increment */
3842testcase TC_rsl_drop_counter() runs on test_CT {
3843 var integer rsl_fail;
3844
Harald Welte89d42e82017-12-17 16:42:41 +01003845 f_init(1);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003846
3847 rsl_fail := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail");
3848
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003849 f_ipa_rsl_stop(bts[0][0].rsl);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003850
3851 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail", rsl_fail+1);
3852
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003853 f_shutdown_helper();
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003854}
3855
3856/* TODO: Test OML link drop causes counter increment */
3857
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003858/* The body of TC_rsl_unknown_unit_id() and TC_oml_unknown_unit_id() tests. */
3859function f_ipa_unknown_unit_id(integer mp_bsc_ipa_port) runs on test_CT return boolean {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003860 var IPA_Client client;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003861 timer T := 10.0;
3862
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003863 client.id := "IPA-BTS0-TRX0-RSL";
3864 client.vc_IPA := IPA_Emulation_CT.create(client.id & "-IPA") alive;
3865 client.ccm_pars := c_IPA_default_ccm_pars;
3866 client.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
3867 client.ccm_pars.unit_id := "99/0/0"; /* value which is unknown at BTS */
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003868
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01003869 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003870
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003871 f_init_mgcp(0, "VirtMGW");
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003872
3873 /* start RSL/OML connection (XXX re-uses RSL port/protocol definitions for OML) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003874 map(client.vc_IPA:IPA_PORT, system:IPA);
3875 connect(client.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[0][0]);
3876 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 +01003877
3878 /* wait for IPA OML link to connect and then disconnect */
3879 T.start;
3880 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003881 [] IPA_RSL[0][0].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_DOWN)) {
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003882 T.stop;
3883 return true;
3884 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003885 [] IPA_RSL[0][0].receive { repeat }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003886 [] T.timeout {
Daniel Willmannafce8662018-07-06 23:11:32 +02003887 return false;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003888 }
3889 }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003890 return false;
3891}
3892
3893/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3894testcase TC_rsl_unknown_unit_id() runs on test_CT {
3895 if (f_ipa_unknown_unit_id(mp_bsc_rsl_port)) {
3896 setverdict(pass);
3897 } else {
3898 setverdict(fail, "Timeout RSL waiting for connection to close");
3899 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003900 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003901}
3902
3903
3904/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3905testcase TC_oml_unknown_unit_id() runs on test_CT {
3906 if (f_ipa_unknown_unit_id(mp_bsc_oml_port)) {
3907 setverdict(pass);
3908 } else {
3909 setverdict(fail, "Timeout OML waiting for connection to close");
3910 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003911 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003912}
3913
3914
Harald Weltec1a2fff2017-12-17 11:06:19 +01003915/***********************************************************************
Harald Welte6811d102019-04-14 22:23:14 +02003916 * "New world" test cases using RSL_Emulation + RAN_Emulation
Harald Weltec1a2fff2017-12-17 11:06:19 +01003917 ***********************************************************************/
3918
Harald Welte6811d102019-04-14 22:23:14 +02003919import from RAN_Emulation all;
Harald Welte47cd0e32020-08-21 12:39:11 +02003920import from BSSAP_LE_Emulation all;
Harald Weltec1a2fff2017-12-17 11:06:19 +01003921import from RSL_Emulation all;
3922import from MSC_ConnectionHandler all;
3923
3924type function void_fn(charstring id) runs on MSC_ConnHdlr;
3925
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003926/* helper function to create and connect a MSC_ConnHdlr component
3927 * TODO: allow connecting to TRX1..N, not only TRX0 */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003928private 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 +02003929 connect(vc_conn:RAN, g_bssap[bssap_idx].vc_RAN:PROC);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003930 connect(vc_conn:RSL, bts[0][0].rsl.vc_RSL:CLIENT_PT);
3931 connect(vc_conn:RSL_PROC, bts[0][0].rsl.vc_RSL:RSL_PROC);
3932 if (isvalue(bts[1][0])) {
3933 connect(vc_conn:RSL1, bts[1][0].rsl.vc_RSL:CLIENT_PT);
3934 connect(vc_conn:RSL1_PROC, bts[1][0].rsl.vc_RSL:RSL_PROC);
Philipp Maier956a92f2018-02-16 10:58:07 +01003935 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003936 if (isvalue(bts[2][0])) {
3937 connect(vc_conn:RSL2, bts[2][0].rsl.vc_RSL:CLIENT_PT);
3938 connect(vc_conn:RSL2_PROC, bts[2][0].rsl.vc_RSL:RSL_PROC);
Neels Hofmeyr91401012019-07-11 00:42:35 +02003939 }
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003940 connect(vc_conn:BSSAP, g_bssap[bssap_idx].vc_RAN:CLIENT);
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02003941 if (mp_enable_lcs_tests) {
3942 connect(vc_conn:BSSAP_LE, g_bssap_le.vc_BSSAP_LE:CLIENT);
3943 connect(vc_conn:BSSAP_LE_PROC, g_bssap_le.vc_BSSAP_LE:PROC);
3944 }
Daniel Willmannebdecc02020-08-12 15:30:17 +02003945 connect(vc_conn:STATSD_PROC, vc_STATSD:STATSD_PROC);
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003946 connect(vc_conn:MGCP_PROC, vc_MGCP[mgwpool_idx]:MGCP_PROC);
3947 connect(vc_conn:MGCP, vc_MGCP[mgwpool_idx]:MGCP_CLIENT);
3948 connect(vc_conn:MGCP_MULTI, vc_MGCP[mgwpool_idx]:MGCP_CLIENT_MULTI);
Harald Welte336820c2018-05-31 20:34:52 +02003949}
3950
Neels Hofmeyrda436782021-07-20 22:09:06 +02003951function f_start_handler_create(template (omit) TestHdlrParams pars := omit)
Harald Welte336820c2018-05-31 20:34:52 +02003952runs on test_CT return MSC_ConnHdlr {
3953 var charstring id := testcasename();
3954 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003955 var integer bssap_idx := 0;
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003956 var integer mgwpool_idx := 0;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003957 if (isvalue(pars)) {
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003958 var TestHdlrParams pars_val := valueof(pars);
3959 bssap_idx := pars_val.mscpool.bssap_idx;
3960 mgwpool_idx := pars_val.mgwpool_idx;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003961 }
Harald Welte336820c2018-05-31 20:34:52 +02003962 vc_conn := MSC_ConnHdlr.create(id);
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003963 f_connect_handler(vc_conn, bssap_idx, mgwpool_idx);
Neels Hofmeyrda436782021-07-20 22:09:06 +02003964 return vc_conn;
3965}
3966
3967function f_start_handler_run(MSC_ConnHdlr vc_conn, void_fn fn, template (omit) TestHdlrParams pars := omit)
3968runs on test_CT return MSC_ConnHdlr {
3969 var charstring id := testcasename();
Harald Weltea0630032018-03-20 21:09:55 +01003970 vc_conn.start(f_handler_init(fn, id, pars));
Harald Weltec1a2fff2017-12-17 11:06:19 +01003971 return vc_conn;
3972}
3973
Neels Hofmeyrda436782021-07-20 22:09:06 +02003974function f_start_handler(void_fn fn, template (omit) TestHdlrParams pars := omit)
3975runs on test_CT return MSC_ConnHdlr {
3976 return f_start_handler_run(f_start_handler_create(pars), fn, pars);
3977}
3978
Harald Weltea0630032018-03-20 21:09:55 +01003979/* first function inside ConnHdlr component; sets g_pars + starts function */
3980private function f_handler_init(void_fn fn, charstring id, template (omit) TestHdlrParams pars := omit)
3981runs on MSC_ConnHdlr {
3982 if (isvalue(pars)) {
3983 g_pars := valueof(pars);
3984 }
3985 fn.apply(id);
3986}
3987
Oliver Smith26a3db72021-07-09 13:51:29 +02003988private function f_vty_encryption_a5(charstring options) runs on test_CT {
3989 f_vty_transceive(BSCVTY, "configure terminal");
3990 f_vty_transceive(BSCVTY, "network");
3991 f_vty_transceive(BSCVTY, "encryption a5 " & options);
3992 f_vty_transceive(BSCVTY, "exit");
3993 f_vty_transceive(BSCVTY, "exit");
3994}
3995
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01003996const charstring VTY_A5_DEFAULT := "0 1 3";
3997
Oliver Smith26a3db72021-07-09 13:51:29 +02003998private function f_vty_encryption_a5_reset() runs on test_CT {
3999 /* keep in sync with docker-playground.git ttcn3-bsc-test/osmo-bsc.cfg */
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01004000 f_vty_encryption_a5(VTY_A5_DEFAULT);
Oliver Smith26a3db72021-07-09 13:51:29 +02004001}
4002
Harald Welte3c86ea02018-05-10 22:28:05 +02004003/* Establish signalling channel (non-assignment case) followed by cipher mode */
4004private function f_tc_ciph_mode_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02004005 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4006 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte3c86ea02018-05-10 22:28:05 +02004007 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Philipp Maier23000732018-05-18 11:25:37 +02004008 ass_cmd.pdu.bssmap.assignmentRequest.circuitIdentityCode := omit;
4009 ass_cmd.pdu.bssmap.assignmentRequest.aoIPTransportLayer := omit;
4010 exp_compl.pdu.bssmap.assignmentComplete.circuitIdentityCode := omit;
4011 exp_compl.pdu.bssmap.assignmentComplete.aoIPTransportLayer := omit;
Harald Welte3c86ea02018-05-10 22:28:05 +02004012
Philipp Maier23000732018-05-18 11:25:37 +02004013 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004014 f_perform_clear();
Harald Welte3c86ea02018-05-10 22:28:05 +02004015}
4016testcase TC_ciph_mode_a5_0() runs on test_CT {
4017 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004018 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004019 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
4020
4021 f_init(1, true);
4022 f_sleep(1.0);
4023 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4024 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004025 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004026}
4027testcase TC_ciph_mode_a5_1() runs on test_CT {
4028 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004029 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004030 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
4031
4032 f_init(1, true);
4033 f_sleep(1.0);
4034 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4035 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004036 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004037}
Oliver Smith50b98122021-07-09 15:00:28 +02004038/* OS#4975: verify that A5/2 is preferred over A5/0 */
4039testcase TC_ciph_mode_a5_2_0() runs on test_CT {
4040 var MSC_ConnHdlr vc_conn;
4041 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4042
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01004043 pars.encr := f_encr_params('05'O, '04'O); /* A5/0 and A5/2 (0x01|0x04)*/
Oliver Smith50b98122021-07-09 15:00:28 +02004044
4045 f_init(1, true);
4046 f_vty_encryption_a5("0 1 2 3");
4047 f_sleep(1.0);
4048 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4049 vc_conn.done;
4050 f_vty_encryption_a5_reset();
4051 f_shutdown_helper();
4052}
Oliver Smith1dff88d2021-07-09 08:45:51 +02004053/* OS#4975: verify that A5/1 is preferred over A5/2 */
4054testcase TC_ciph_mode_a5_2_1() runs on test_CT {
4055 var MSC_ConnHdlr vc_conn;
4056 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4057
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01004058 pars.encr := f_encr_params('06'O, '02'O); /* A5/1 and A5/2 (0x02|0x04)*/
Oliver Smith1dff88d2021-07-09 08:45:51 +02004059
4060 f_init(1, true);
4061 f_vty_encryption_a5("1 2");
4062 f_sleep(1.0);
4063 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4064 vc_conn.done;
4065 f_vty_encryption_a5_reset();
4066 f_shutdown_helper();
4067}
Harald Welte3c86ea02018-05-10 22:28:05 +02004068testcase TC_ciph_mode_a5_3() runs on test_CT {
4069 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004070 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004071 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
4072
4073 f_init(1, true);
4074 f_sleep(1.0);
4075 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4076 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004077 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004078}
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004079/* Establish a Signalling channel with A5/4 encryption. */
4080testcase TC_ciph_mode_a5_4() runs on test_CT {
4081 var MSC_ConnHdlr vc_conn;
4082 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4083 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Harald Welte3c86ea02018-05-10 22:28:05 +02004084
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004085 f_init(1, true);
Oliver Smith26a3db72021-07-09 13:51:29 +02004086 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004087 f_sleep(1.0);
4088 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4089 vc_conn.done;
Oliver Smith26a3db72021-07-09 13:51:29 +02004090 f_vty_encryption_a5_reset();
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004091 f_shutdown_helper();
4092}
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004093/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
4094private function f_tc_assignment_aoip_tla_v6(charstring id) runs on MSC_ConnHdlr {
4095 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4096 var PDU_BSSAP ass_cmd := f_gen_ass_req(aoip_tla := "::3");
4097 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4098 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4099
4100 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004101 f_perform_clear();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004102}
4103testcase TC_assignment_aoip_tla_v6() runs on test_CT {
4104 var MSC_ConnHdlr vc_conn;
4105 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4106
4107 f_init(1, true);
4108 f_sleep(1.0);
4109 vc_conn := f_start_handler(refers(f_tc_assignment_aoip_tla_v6), pars);
4110 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004111 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004112}
4113
Harald Welte3c86ea02018-05-10 22:28:05 +02004114
4115/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
Harald Welte651fcdc2018-05-10 20:23:16 +02004116private function f_tc_assignment_fr_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02004117 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4118 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004119
Harald Welte552620d2017-12-16 23:21:36 +01004120 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4121 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte73cd2712017-12-17 00:44:52 +01004122
Harald Weltea0630032018-03-20 21:09:55 +01004123 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004124 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004125}
Harald Welte552620d2017-12-16 23:21:36 +01004126testcase TC_assignment_fr_a5_0() runs on test_CT {
4127 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004128 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004129 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
Harald Welte552620d2017-12-16 23:21:36 +01004130
Harald Welte89d42e82017-12-17 16:42:41 +01004131 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004132 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004133 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004134 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004135 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004136}
Harald Welte552620d2017-12-16 23:21:36 +01004137testcase TC_assignment_fr_a5_1() runs on test_CT {
Harald Weltec1a2fff2017-12-17 11:06:19 +01004138 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004139 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004140 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004141
Harald Welte89d42e82017-12-17 16:42:41 +01004142 f_init(1, true);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004143 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004144 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4145 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004146 f_shutdown_helper();
Harald Welte651fcdc2018-05-10 20:23:16 +02004147}
4148testcase TC_assignment_fr_a5_3() runs on test_CT {
4149 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004150 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004151 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004152
Harald Welte651fcdc2018-05-10 20:23:16 +02004153 f_init(1, true);
4154 f_sleep(1.0);
4155 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004156 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004157 f_shutdown_helper();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004158}
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004159/* Establish a Signalling channel and re-assign to TCH/F with A5/4 encryption. */
4160testcase TC_assignment_fr_a5_4() runs on test_CT {
4161 var MSC_ConnHdlr vc_conn;
4162 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4163 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
4164
4165 f_init(1, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02004166 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004167 f_sleep(1.0);
4168 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4169 vc_conn.done;
Oliver Smith7eabd312021-07-12 14:18:56 +02004170 f_vty_encryption_a5_reset();
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004171 f_shutdown_helper();
4172}
Harald Weltec1a2fff2017-12-17 11:06:19 +01004173
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +02004174/* Allow only A5/4, but omit the Kc128 IE from MSC's msg. Expect Cipher Mode Reject. */
4175testcase TC_assignment_fr_a5_4_fail() runs on test_CT {
4176 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4177 var MSC_ConnHdlr vc_conn;
4178
4179 f_init(1, true);
4180 f_sleep(1.0);
4181
4182 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8))); // A5/4 support, but Kc128 missing!
4183 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
4184 vc_conn.done;
4185 f_shutdown_helper();
4186}
4187
Harald Welte552620d2017-12-16 23:21:36 +01004188/* Expect ASSIGNMENT FAIL if mandatory IE is missing */
4189private function f_tc_assignment_fr_a5_1_codec_missing(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004190 g_pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004191 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02004192 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004193
4194 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02004195 /* Omit: ass_cmd.pdu.bssmap.assignmentRequest.codecList */
4196
Harald Weltea0630032018-03-20 21:09:55 +01004197 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004198 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004199}
Harald Welte552620d2017-12-16 23:21:36 +01004200testcase TC_assignment_fr_a5_1_codec_missing() runs on test_CT {
4201 var MSC_ConnHdlr vc_conn;
4202
Harald Welte89d42e82017-12-17 16:42:41 +01004203 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004204 f_sleep(1.0);
4205
Harald Welte8863fa12018-05-10 20:15:27 +02004206 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5_1_codec_missing));
Harald Welte552620d2017-12-16 23:21:36 +01004207 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004208 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004209}
4210
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004211private function f_TC_assignment_a5_not_sup(charstring id) runs on MSC_ConnHdlr {
4212 var template PDU_BSSAP exp_ass_cpl := f_gen_exp_compl();
4213 var PDU_BSSAP exp_ass_req := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004214
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004215 exp_ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4216 exp_ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4217
4218 /* this is like the beginning of f_establish_fully(), but only up to ciphering reject */
4219
4220 var BSSMAP_FIELD_CodecType codecType;
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004221
4222 codecType := exp_ass_req.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType;
4223 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
4224
4225 f_create_chan_and_exp();
4226 /* we should now have a COMPL_L3 at the MSC */
4227
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004228 /* Start ciphering, expect Cipher Mode Reject */
Neels Hofmeyr6c388f22021-06-11 02:36:56 +02004229 f_cipher_mode(g_pars.encr, exp_fail := true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004230 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004231}
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004232testcase TC_assignment_fr_a5_not_sup() runs on test_CT {
4233 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004234 var MSC_ConnHdlr vc_conn;
4235
Harald Welte89d42e82017-12-17 16:42:41 +01004236 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004237 f_sleep(1.0);
4238
Neels Hofmeyr0588cad2021-06-11 01:38:18 +02004239 pars.encr := valueof(t_EncrParams('20'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004240 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004241 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004242 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004243}
4244
4245
Harald Welte4532e0a2017-12-23 02:05:44 +01004246private function f_tc_assignment_sign(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004247 g_pars := f_gen_test_hdlr_pars();
Harald Welte4532e0a2017-12-23 02:05:44 +01004248 var template PDU_BSSAP exp_compl := tr_BSSMAP_AssignmentComplete(omit, omit);
Philipp Maier48604732018-10-09 15:00:37 +02004249 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte4532e0a2017-12-23 02:05:44 +01004250 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004251
4252 f_statsd_reset();
Harald Weltea0630032018-03-20 21:09:55 +01004253 f_establish_fully(ass_cmd, exp_compl);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004254
4255 var StatsDExpects expect := {
Daniel Willmannc5398f72020-09-21 10:41:35 +02004256 { name := "TTCN3.bts.0.chreq.total", mtype := "c", min := 1, max := 1},
4257 { name := "TTCN3.bts.0.chreq.successful", mtype := "c", min := 1, max := 1},
Daniel Willmannebdecc02020-08-12 15:30:17 +02004258 { name := "TTCN3.bsc.0.assignment.attempted", mtype := "c", min := 1, max := 1},
4259 { name := "TTCN3.bsc.0.assignment.completed", mtype := "c", min := 1, max := 1}
4260 };
4261 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004262 f_perform_clear();
Harald Welte4532e0a2017-12-23 02:05:44 +01004263}
4264
4265testcase TC_assignment_sign() runs on test_CT {
4266 var MSC_ConnHdlr vc_conn;
4267
4268 f_init(1, true);
4269 f_sleep(1.0);
4270
Harald Welte8863fa12018-05-10 20:15:27 +02004271 vc_conn := f_start_handler(refers(f_tc_assignment_sign));
Harald Welte4532e0a2017-12-23 02:05:44 +01004272 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004273 f_shutdown_helper();
Harald Welte4532e0a2017-12-23 02:05:44 +01004274}
4275
Harald Welte60aa5762018-03-21 19:33:13 +01004276/***********************************************************************
4277 * Codec (list) testing
4278 ***********************************************************************/
4279
4280/* check if the given rsl_mode is compatible with the a_elem */
4281private function f_match_codec(BSSMAP_FIELD_CodecElement a_elem, RSL_IE_ChannelMode rsl_mode)
4282return boolean {
4283 select (a_elem.codecType) {
4284 case (GSM_FR) {
4285 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM1))) {
4286 return true;
4287 }
4288 }
4289 case (GSM_HR) {
4290 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM1))) {
4291 return true;
4292 }
4293 }
4294 case (GSM_EFR) {
4295 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM2))) {
4296 return true;
4297 }
4298 }
4299 case (FR_AMR) {
4300 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM3))) {
4301 return true;
4302 }
4303 }
4304 case (HR_AMR) {
4305 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM3))) {
4306 return true;
4307 }
4308 }
4309 case else { }
4310 }
4311 return false;
4312}
4313
4314/* check if the given rsl_mode is compatible with the a_list */
4315private function f_match_codecs(BSSMAP_IE_SpeechCodecList a_list, RSL_IE_ChannelMode rsl_mode)
4316return boolean {
4317 for (var integer i := 0; i < sizeof(a_list); i := i+1) {
4318 if (f_match_codec(a_list.codecElements[i], rsl_mode)) {
4319 return true;
4320 }
4321 }
4322 return false;
4323}
4324
4325/* determine BSSMAP_IE_ChannelType from *first* element of BSSMAP_FIELD_CodecElement */
Philipp Maier61f6b572018-07-06 14:03:38 +02004326function f_BSSMAP_chtype_from_codec(BSSMAP_FIELD_CodecElement a_elem)
Harald Welte60aa5762018-03-21 19:33:13 +01004327return BSSMAP_IE_ChannelType {
4328 /* FIXME: actually look at all elements of BSSMAP_IE_SpeechCodecList */
4329 var BSSMAP_IE_ChannelType ret := valueof(ts_BSSMAP_IE_ChannelType);
4330 select (a_elem.codecType) {
4331 case (GSM_FR) {
4332 ret.channelRateAndType := ChRate_TCHF;
4333 ret.speechId_DataIndicator := Spdi_TCHF_FR;
4334 }
4335 case (GSM_HR) {
4336 ret.channelRateAndType := ChRate_TCHH;
4337 ret.speechId_DataIndicator := Spdi_TCHH_HR;
4338 }
4339 case (GSM_EFR) {
4340 ret.channelRateAndType := ChRate_TCHF;
4341 ret.speechId_DataIndicator := Spdi_TCHF_EFR;
4342 }
4343 case (FR_AMR) {
4344 ret.channelRateAndType := ChRate_TCHF;
4345 ret.speechId_DataIndicator := Spdi_TCHF_AMR;
4346 }
4347 case (HR_AMR) {
4348 ret.channelRateAndType := ChRate_TCHH;
4349 ret.speechId_DataIndicator := Spdi_TCHH_AMR;
4350 }
4351 case else {
4352 setverdict(fail, "Unsupported codec ", a_elem);
Daniel Willmannafce8662018-07-06 23:11:32 +02004353 mtc.stop;
Harald Welte60aa5762018-03-21 19:33:13 +01004354 }
4355 }
4356 return ret;
4357}
4358
Harald Weltea63b9102018-03-22 20:36:16 +01004359private function f_rsl_chmod_tmpl_from_codec(BSSMAP_FIELD_CodecElement a_elem)
4360return template RSL_IE_Body {
4361 var template RSL_IE_Body mode_ie := {
4362 chan_mode := {
4363 len := ?,
4364 reserved := ?,
4365 dtx_d := ?,
4366 dtx_u := ?,
4367 spd_ind := RSL_SPDI_SPEECH,
4368 ch_rate_type := -,
Oliver Smith0033b122023-02-28 13:30:53 +01004369 u := { speech := - }
Harald Weltea63b9102018-03-22 20:36:16 +01004370 }
4371 }
4372
4373 select (a_elem.codecType) {
4374 case (GSM_FR) {
4375 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004376 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM1;
Harald Weltea63b9102018-03-22 20:36:16 +01004377 }
4378 case (GSM_HR) {
4379 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
Oliver Smith0033b122023-02-28 13:30:53 +01004380 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM1;
Harald Weltea63b9102018-03-22 20:36:16 +01004381 }
4382 case (GSM_EFR) {
4383 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004384 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM2;
Harald Weltea63b9102018-03-22 20:36:16 +01004385 }
4386 case (FR_AMR) {
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_GSM3;
Harald Weltea63b9102018-03-22 20:36:16 +01004389 }
4390 case (HR_AMR) {
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_GSM3;
Harald Weltea63b9102018-03-22 20:36:16 +01004393 }
4394 }
4395 return mode_ie;
4396}
4397
Harald Welte60aa5762018-03-21 19:33:13 +01004398type record CodecListTest {
4399 BSSMAP_IE_SpeechCodecList codec_list,
4400 charstring id
4401}
4402type record of CodecListTest CodecListTests
4403
4404private function f_TC_assignment_codec(charstring id) runs on MSC_ConnHdlr {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004405 f_assignment_codec(id);
4406}
4407
4408private function f_assignment_codec(charstring id, boolean do_perform_clear := true) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02004409 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02004410 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Harald Welte60aa5762018-03-21 19:33:13 +01004411
4412 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004413 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte79f3f542018-05-25 20:02:37 +02004414 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4415 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
4416 g_pars.ass_codec_list.codecElements[0];
Philipp Maierd0e64b02019-03-13 14:15:23 +01004417 if (isvalue(g_pars.expect_mr_s0_s7)) {
4418 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
4419 g_pars.expect_mr_s0_s7;
4420 }
Harald Welte79f3f542018-05-25 20:02:37 +02004421 }
Harald Welte60aa5762018-03-21 19:33:13 +01004422 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4423 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
Harald Welte60aa5762018-03-21 19:33:13 +01004424 log("expecting ASS COMPL like this: ", exp_compl);
4425
4426 f_establish_fully(ass_cmd, exp_compl);
Harald Weltea63b9102018-03-22 20:36:16 +01004427
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004428 if (not g_pars.expect_channel_mode_modify) {
4429 /* Verify that the RSL-side activation actually matches our expectations */
4430 var RSL_Message rsl := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
Harald Weltea63b9102018-03-22 20:36:16 +01004431
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004432 var RSL_IE_Body mode_ie;
4433 if (f_rsl_find_ie(rsl, RSL_IE_CHAN_MODE, mode_ie) == false) {
4434 setverdict(fail, "Couldn't find CHAN_MODE IE");
Daniel Willmannafce8662018-07-06 23:11:32 +02004435 mtc.stop;
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004436 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004437 var template RSL_IE_Body t_mode_ie := f_rsl_chmod_tmpl_from_codec(g_pars.ass_codec_list.codecElements[0]);
4438 if (not match(mode_ie, t_mode_ie)) {
4439 log("mode_ie ", mode_ie, " != t_mode_ie ", t_mode_ie);
4440 setverdict(fail, "RSL Channel Mode IE doesn't match expectation");
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004441 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004442
4443 var RSL_IE_Body mr_conf;
4444 if (g_pars.expect_mr_conf_ie != omit) {
4445 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == false) {
4446 setverdict(fail, "Missing MR CONFIG IE in RSL Chan Activ");
4447 mtc.stop;
4448 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004449 log("found RSL MR CONFIG IE: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004450
4451 if (not match(mr_conf, g_pars.expect_mr_conf_ie)) {
Vadim Yanitskiy8b189372022-09-14 17:31:17 +07004452 setverdict(fail, "RSL MR CONFIG IE does not match expectation. ",
4453 "Expected: ", g_pars.expect_mr_conf_ie, ", got: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004454 }
4455 } else {
4456 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == true) {
4457 log("found RSL MR CONFIG IE: ", mr_conf);
4458 setverdict(fail, "Found MR CONFIG IE in RSL Chan Activ, expecting omit");
4459 mtc.stop;
4460 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004461 }
4462 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004463
4464 if (do_perform_clear) {
4465 f_perform_clear();
4466 }
Harald Welte60aa5762018-03-21 19:33:13 +01004467}
4468
Philipp Maierd0e64b02019-03-13 14:15:23 +01004469private function f_TC_assignment_codec_fail(charstring id) runs on MSC_ConnHdlr {
4470
4471 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4472 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4473
4474 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004475 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maierd0e64b02019-03-13 14:15:23 +01004476 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4477 }
4478 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4479 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
4480 log("expecting ASS FAIL like this: ", exp_fail);
4481
4482 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004483 f_perform_clear();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004484}
4485
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004486const CounterNameVals counternames_bsc_bts_assignment := {
4487 { "assignment:attempted", 0 },
4488 { "assignment:completed", 0 },
4489 { "assignment:stopped", 0 },
4490 { "assignment:no_channel", 0 },
4491 { "assignment:timeout", 0 },
4492 { "assignment:failed", 0 },
4493 { "assignment:error", 0 }
4494};
4495
4496const CounterNameVals counternames_bts_assignment := {
4497 { "assignment:attempted_sign", 0 },
4498 { "assignment:attempted_speech", 0 },
4499 { "assignment:completed_sign", 0 },
4500 { "assignment:completed_speech", 0 },
4501 { "assignment:stopped_sign", 0 },
4502 { "assignment:stopped_speech", 0 },
4503 { "assignment:no_channel_sign", 0 },
4504 { "assignment:no_channel_speech", 0 },
4505 { "assignment:timeout_sign", 0 },
4506 { "assignment:timeout_speech", 0 },
4507 { "assignment:failed_sign", 0 },
4508 { "assignment:failed_speech", 0 },
4509 { "assignment:error_sign", 0 },
4510 { "assignment:error_speech", 0 }
4511};
4512
4513function f_ctrs_bsc_and_bts_assignment_init(integer bts_count := NUM_BTS) runs on test_CT {
4514 var CounterNameVals bts_names := counternames_bsc_bts_assignment & counternames_bts_assignment;
4515 f_ctrs_bts_init(bts_count, bts_names);
4516 f_ctrs_bsc_init(counternames_bsc_bts_assignment);
4517}
4518
Harald Welte60aa5762018-03-21 19:33:13 +01004519testcase TC_assignment_codec_fr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004520 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004521 var MSC_ConnHdlr vc_conn;
4522
4523 f_init(1, true);
4524 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004525 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004526
4527 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004528 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004529 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004530
4531 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4532 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4533 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4534 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4535 f_ctrs_bts_verify();
4536
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004537 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004538}
4539
4540testcase TC_assignment_codec_hr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004541 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004542 var MSC_ConnHdlr vc_conn;
4543
4544 f_init(1, true);
4545 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004546 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004547
4548 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004549 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004550 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004551
4552 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4553 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4554 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4555 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4556 f_ctrs_bts_verify();
4557
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004558 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004559}
4560
4561testcase TC_assignment_codec_efr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004562 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004563 var MSC_ConnHdlr vc_conn;
4564
4565 f_init(1, true);
4566 f_sleep(1.0);
4567
4568 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecEFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004569 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004570 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004571 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004572}
4573
Philipp Maierd0e64b02019-03-13 14:15:23 +01004574/* Allow 5,90k only (current default config) */
4575private function f_allow_amr_rate_5_90k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004576 f_vty_cfg_msc(BSCVTY, 0, {
4577 "amr-config 12_2k forbidden",
4578 "amr-config 10_2k forbidden",
4579 "amr-config 7_95k forbidden",
4580 "amr-config 7_40k forbidden",
4581 "amr-config 6_70k forbidden",
4582 "amr-config 5_90k allowed",
4583 "amr-config 5_15k forbidden",
4584 "amr-config 4_75k forbidden"
4585 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004586}
4587
4588/* Allow 4,75k, 5,90k, 4,70k and 12,2k, which are the most common rates
4589 * ("Config-NB-Code = 1") */
4590private function f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004591 f_vty_cfg_msc(BSCVTY, 0, {
4592 "amr-config 12_2k allowed",
4593 "amr-config 10_2k forbidden",
4594 "amr-config 7_95k forbidden",
4595 "amr-config 7_40k allowed",
4596 "amr-config 6_70k forbidden",
4597 "amr-config 5_90k allowed",
4598 "amr-config 5_15k forbidden",
4599 "amr-config 4_75k allowed"
4600 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004601}
4602
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004603private function f_vty_amr_start_mode_set(boolean fr, charstring startmode) runs on test_CT {
4604 var charstring tch;
4605 if (fr) {
4606 tch := "tch-f";
4607 } else {
4608 tch := "tch-h";
4609 }
4610 f_vty_cfg_bts(BSCVTY, 0, { "amr " & tch & " start-mode " & startmode });
4611}
4612
4613/* Set the AMR start-mode for this TCH back to the default configuration. */
4614private function f_vty_amr_start_mode_restore(boolean fr) runs on test_CT {
4615 f_vty_amr_start_mode_set(fr, "auto");
4616}
4617
Harald Welte60aa5762018-03-21 19:33:13 +01004618testcase TC_assignment_codec_amr_f() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004619 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004620 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004621
4622 /* Note: This setups the codec configuration. The parameter payload in
4623 * mr_conf must be consistant with the parameter codecElements in pars
4624 * and also must match the amr-config in osmo-bsc.cfg! */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004625 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004626 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004627 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004628 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004629
Harald Welte60aa5762018-03-21 19:33:13 +01004630 f_init(1, true);
4631 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004632 f_vty_amr_start_mode_set(true, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004633 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004634
Harald Welte8863fa12018-05-10 20:15:27 +02004635 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004636 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004637
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004638 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4639 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4640 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4641 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4642 f_ctrs_bts_verify();
4643
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004644 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004645 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004646}
4647
4648testcase TC_assignment_codec_amr_h() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004649 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004650 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004651
4652 /* See note above */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004653 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004654 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004655 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004656 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004657
Harald Welte60aa5762018-03-21 19:33:13 +01004658 f_init(1, true);
4659 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004660 f_vty_amr_start_mode_set(false, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004661 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004662
Harald Welte8863fa12018-05-10 20:15:27 +02004663 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004664 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004665
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004666 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4667 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4668 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4669 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4670 f_ctrs_bts_verify();
4671
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004672 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004673 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004674}
4675
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004676/* Establish signalling on a TCH/F lchan, and then switch to speech mode without a new Assignment. */
4677testcase TC_assignment_codec_fr_by_mode_modify() runs on test_CT {
4678 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4679 var MSC_ConnHdlr vc_conn;
4680
4681 f_init(1, true);
4682 f_sleep(1.0);
4683
4684 /* By disabling all SDCCH, the MS should be given a TCH/F for signalling. Then activating an FR codec should
4685 * merely do a Channel Mode Modify, and not assign to a new lchan. f_establish_fully() already accounts for
4686 * expecting a Channel Mode Modify if the channel type is compatible. */
4687 f_disable_all_sdcch();
4688 f_disable_all_tch_h();
4689
4690 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4691 pars.expect_channel_mode_modify := true;
4692 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4693 vc_conn.done;
4694
4695 f_enable_all_sdcch();
4696 f_enable_all_tch();
4697 f_shutdown_helper();
4698}
4699
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004700/* 'amr start-mode auto' should not keep the (unused) 'smod' bits from previous configuration */
4701testcase TC_assignment_codec_amr_startmode_cruft() runs on test_CT {
4702 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4703 var MSC_ConnHdlr vc_conn;
4704
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004705 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4706 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
4707 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy36fe9582022-09-14 15:25:04 +07004708 pars.expect_mr_conf_ie := c_mr_conf_5_90;
4709 pars.expect_mr_conf_ie.multirate_cfg.icmi := false; /* expect ICMI=0, smod=00: */
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004710
4711 f_init(1, true);
4712 f_sleep(1.0);
4713
4714 /* First set nonzero start mode bits */
4715 f_vty_amr_start_mode_set(true, "4");
4716 /* Now set to auto, and expect the startmode bits to be zero in the message, i.e. ensure that osmo-bsc does not
4717 * let the startmode bits stick around and has deterministic MultiRate config for 'start-mode auto'; that is
4718 * ensured by above '2004'O, where 'x0xx'O indicates ICMI = 0, spare = 0, smod = 00. */
4719 f_vty_amr_start_mode_set(true, "auto");
4720
4721 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4722 vc_conn.done;
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004723
4724 /* Clear the startmode bits to not affect subsequent tests, in case the bits should indeed stick around. */
4725 f_vty_amr_start_mode_set(true, "1");
4726 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004727 f_shutdown_helper();
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004728}
4729
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004730function f_TC_assignment_codec_amr(boolean fr, RSL_IE_MultirateCfg mr_cfg,
4731 bitstring s8_s0, bitstring exp_s8_s0,
4732 charstring start_mode := "1")
Philipp Maierd0e64b02019-03-13 14:15:23 +01004733runs on test_CT {
4734
4735 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4736 var MSC_ConnHdlr vc_conn;
4737
Philipp Maierd0e64b02019-03-13 14:15:23 +01004738 if (fr) {
4739 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4740 } else {
4741 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4742 }
4743 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4744 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004745 pars.expect_mr_conf_ie := { multirate_cfg := mr_cfg };
Philipp Maierd0e64b02019-03-13 14:15:23 +01004746 pars.expect_mr_s0_s7 := exp_s8_s0;
4747
4748 f_init(1, true);
4749 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004750 f_vty_amr_start_mode_set(fr, start_mode);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004751 f_sleep(1.0);
4752
4753 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4754 vc_conn.done;
4755 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004756 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004757}
4758
4759function f_TC_assignment_codec_amr_fail(boolean fr, bitstring s8_s0)
4760runs on test_CT {
4761
4762 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4763 var MSC_ConnHdlr vc_conn;
4764
4765 if (fr) {
4766 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4767 } else {
4768 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4769 }
4770 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4771 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
4772
4773 f_init(1, true);
4774 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004775 f_vty_amr_start_mode_set(fr, "1");
Philipp Maierd0e64b02019-03-13 14:15:23 +01004776 f_sleep(1.0);
4777
4778 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fail), pars);
4779 vc_conn.done;
4780 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004781 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004782}
4783
Philipp Maierd0e64b02019-03-13 14:15:23 +01004784/* Set S1, we expect an AMR multirate configuration IE with all four rates
4785 * set. */
4786testcase TC_assignment_codec_amr_f_S1() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004787 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4788 params := '20882208'O));
4789 f_TC_assignment_codec_amr(true, mr_cfg, '00000011'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004790 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004791}
4792
4793/* Set S1, we expect an AMR multirate configuration IE with the lower three
4794 * rates set. */
4795testcase TC_assignment_codec_amr_h_S1() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004796 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4797 params := '208820'O));
4798 f_TC_assignment_codec_amr(false, mr_cfg, '00000010'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004799 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004800}
4801
4802/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4803 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4804testcase TC_assignment_codec_amr_f_S124() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004805 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4806 params := '20882208'O));
4807 f_TC_assignment_codec_amr(true, mr_cfg, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004808 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004809}
4810
4811/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4812 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4813testcase TC_assignment_codec_amr_h_S124() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004814 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4815 params := '208820'O));
4816 f_TC_assignment_codec_amr(false, mr_cfg, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004817 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004818}
4819
4820/* The following block of tests selects more and more rates until all four
4821 * possible rates are in the active set (full rate) */
4822testcase TC_assignment_codec_amr_f_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004823 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4824 f_TC_assignment_codec_amr(true, mr_cfg, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004825 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004826}
4827
4828testcase TC_assignment_codec_amr_f_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004829 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4830 params := '2080'O));
4831 f_TC_assignment_codec_amr(true, mr_cfg, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004832 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004833}
4834
4835testcase TC_assignment_codec_amr_f_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004836 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4837 params := '208820'O));
4838 f_TC_assignment_codec_amr(true, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004839 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004840}
4841
4842testcase TC_assignment_codec_amr_f_S0247() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004843 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4844 params := '20882208'O));
4845 f_TC_assignment_codec_amr(true, mr_cfg, '10010101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004846 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004847}
4848
4849/* The following block of tests selects more and more rates until all three
4850 * possible rates are in the active set (half rate) */
4851testcase TC_assignment_codec_amr_h_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004852 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4853 f_TC_assignment_codec_amr(false, mr_cfg, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004854 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004855}
4856
4857testcase TC_assignment_codec_amr_h_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004858 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4859 params := '2080'O));
4860 f_TC_assignment_codec_amr(false, mr_cfg, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004861 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004862}
4863
4864testcase TC_assignment_codec_amr_h_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004865 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4866 params := '208820'O));
4867 f_TC_assignment_codec_amr(false, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004868 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004869}
4870
4871/* The following block tests what happens when the MSC does offer rate
4872 * configurations that are not supported by the BSC. Normally such situations
4873 * should not happen because the MSC gets informed by the BSC in advance via
4874 * the L3 COMPLETE message which rates are applicable. The MSC should not try
4875 * to offer rates that are not applicable anyway. */
4876
4877testcase TC_assignment_codec_amr_h_S0247() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004878 /* Try to include 12,2k in into the active set even though the channel
4879 * is half rate only. The BSC is expected to remove the 12,0k */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004880 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4881 params := '208820'O));
4882 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004883 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004884}
4885
4886testcase TC_assignment_codec_amr_f_S01234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004887 /* See what happens when all rates are selected at once. Since then
4888 * Also S1 is selected, this setting will be prefered and we should
4889 * get 12.2k, 7,40k, 5,90k, and 4,75k in the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004890 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4891 params := '20882208'O));
4892 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004893 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004894}
4895
4896testcase TC_assignment_codec_amr_f_S0234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004897 /* Same as above, but with S1 missing, the MSC is then expected to
4898 * select the currently supported rates, which are also 12.2k, 7,40k,
4899 * 5,90k, and 4,75k, into the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004900 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4901 params := '20882208'O));
4902 f_TC_assignment_codec_amr(true, mr_cfg, '11111101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004903 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004904}
4905
4906testcase TC_assignment_codec_amr_f_zero() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004907 /* Try to select no rates at all */
4908 f_TC_assignment_codec_amr_fail(true, '00000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004909 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004910}
4911
4912testcase TC_assignment_codec_amr_f_unsupp() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004913 /* Try to select only unsupported rates */
4914 f_TC_assignment_codec_amr_fail(true, '01101000'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_h_S7() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004919 /* Try to select 12,2k for half rate */
4920 f_TC_assignment_codec_amr_fail(false, '10000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004921 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004922}
4923
Neels Hofmeyr21863562020-11-26 00:34:33 +00004924testcase TC_assignment_codec_amr_f_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004925 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
4926 codec_modes := '10010101'B,
4927 params := '20882208'O));
4928 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004929 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004930}
4931
4932testcase TC_assignment_codec_amr_h_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004933 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
4934 codec_modes := '00010101'B,
4935 params := '208820'O));
4936 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B,
Neels Hofmeyr21863562020-11-26 00:34:33 +00004937 start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004938 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004939}
4940
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004941testcase TC_assignment_codec_amr_f_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004942 /* "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 +07004943 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 3,
4944 codec_modes := '10010101'B,
4945 params := '20882208'O));
4946 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004947 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004948}
4949
4950testcase TC_assignment_codec_amr_h_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004951 /* "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 +07004952 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 2,
4953 codec_modes := '00010101'B,
4954 params := '208820'O));
4955 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004956 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004957}
4958
Philipp Maierac09bfc2019-01-08 13:41:39 +01004959private function f_disable_all_tch_f() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004960 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 borken");
4961 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 borken");
4962 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 borken");
4963 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004964}
4965
4966private function f_disable_all_tch_h() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004967 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 borken");
4968 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004969}
4970
4971private function f_enable_all_tch() 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 unused");
4973 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 unused");
4974 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 unused");
4975 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 unused");
4976 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 unused");
4977 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 unused");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004978}
4979
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004980private function f_disable_all_sdcch() runs on test_CT {
4981 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 borken");
4982 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 borken");
4983 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 borken");
4984 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 borken");
4985}
4986
4987private function f_enable_all_sdcch() runs on test_CT {
4988 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 unused");
4989 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 unused");
4990 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 unused");
4991 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 unused");
4992}
4993
Philipp Maierac09bfc2019-01-08 13:41:39 +01004994/* Allow HR only */
4995private function f_TC_assignment_codec_xr_exhausted_req_hr(charstring id) runs on MSC_ConnHdlr {
4996 g_pars := f_gen_test_hdlr_pars();
4997 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4998 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4999 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5000 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
5001 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
5002 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5003 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005004 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005005}
5006
5007/* Allow FR only */
5008private function f_TC_assignment_codec_xr_exhausted_req_fr(charstring id) runs on MSC_ConnHdlr {
5009 g_pars := f_gen_test_hdlr_pars();
5010 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5011 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5012 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5013 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
5014 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
5015 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5016 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005017 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005018}
5019
5020/* Allow HR only (expect assignment failure) */
5021private function f_TC_assignment_codec_xr_exhausted_req_hr_fail(charstring id) runs on MSC_ConnHdlr {
5022 g_pars := f_gen_test_hdlr_pars();
5023 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5024 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
5025 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5026 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
5027 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
5028 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5029 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005030 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005031}
5032
5033/* Allow FR only (expect assignment failure) */
5034private function f_TC_assignment_codec_xr_exhausted_req_fr_fail(charstring id) runs on MSC_ConnHdlr {
5035 g_pars := f_gen_test_hdlr_pars();
5036 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5037 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
5038 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5039 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
5040 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
5041 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5042 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005043 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005044}
5045
5046/* Allow FR and HR, but prefer FR */
5047private function f_TC_assignment_codec_fr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5048 g_pars := f_gen_test_hdlr_pars();
5049 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5050 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5051 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5052 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5053 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5054 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5055 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5056 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005057 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005058}
5059
5060/* Allow FR and HR, but prefer HR */
5061private function f_TC_assignment_codec_fr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5062 g_pars := f_gen_test_hdlr_pars();
5063 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5064 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5065 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5066 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5067 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5068 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5069 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5070 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005071 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005072}
5073
5074/* Allow FR and HR, but prefer FR */
5075private function f_TC_assignment_codec_hr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5076 g_pars := f_gen_test_hdlr_pars();
5077 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5078 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5079 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5080 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5081 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5082 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5083 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5084 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005085 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005086}
5087
5088/* Allow FR and HR, but prefer HR */
5089private function f_TC_assignment_codec_hr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5090 g_pars := f_gen_test_hdlr_pars();
5091 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5092 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5093 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5094 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5095 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5096 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5097 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5098 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005099 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005100}
5101
5102/* Request a HR channel while all FR channels are exhausted, this is expected
5103 * to work without conflicts */
5104testcase TC_assignment_codec_fr_exhausted_req_hr() runs on test_CT {
5105 var MSC_ConnHdlr vc_conn;
5106 f_init(1, true);
5107 f_sleep(1.0);
5108 f_enable_all_tch();
5109 f_disable_all_tch_f();
5110 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr));
5111 vc_conn.done;
5112 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005113 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005114}
5115
5116/* Request a FR channel while all FR channels are exhausted, this is expected
5117 * to fail. */
5118testcase TC_assignment_codec_fr_exhausted_req_fr() runs on test_CT {
5119 var MSC_ConnHdlr vc_conn;
5120 f_init(1, true);
5121 f_sleep(1.0);
5122 f_enable_all_tch();
5123 f_disable_all_tch_f();
5124 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr_fail));
5125 vc_conn.done;
5126 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005127 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005128}
5129
5130/* Request a FR (prefered) or alternatively a HR channel while all FR channels
5131 * are exhausted, this is expected to be resolved by selecting a HR channel. */
5132testcase TC_assignment_codec_fr_exhausted_req_fr_hr() runs on test_CT {
5133 var MSC_ConnHdlr vc_conn;
5134 f_init(1, true);
5135 f_sleep(1.0);
5136 f_enable_all_tch();
5137 f_disable_all_tch_f();
5138 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_fr_hr));
5139 vc_conn.done;
5140 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005141 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005142}
5143
5144/* Request a HR (prefered) or alternatively a FR channel while all FR channels
5145 * are exhausted, this is expected to work without conflicts. */
5146testcase TC_assignment_codec_fr_exhausted_req_hr_fr() runs on test_CT {
5147 var MSC_ConnHdlr vc_conn;
5148 f_init(1, true);
5149 f_sleep(1.0);
5150 f_enable_all_tch();
5151 f_disable_all_tch_f();
5152 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_hr_fr));
5153 vc_conn.done;
5154 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005155 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005156}
5157
5158/* Request a FR channel while all HR channels are exhausted, this is expected
5159 * to work without conflicts */
5160testcase TC_assignment_codec_hr_exhausted_req_fr() runs on test_CT {
5161 var MSC_ConnHdlr vc_conn;
5162 f_init(1, true);
5163 f_sleep(1.0);
5164 f_enable_all_tch();
5165 f_disable_all_tch_h();
5166 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr));
5167 vc_conn.done;
5168 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005169 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005170}
5171
5172/* Request a HR channel while all HR channels are exhausted, this is expected
5173 * to fail. */
5174testcase TC_assignment_codec_hr_exhausted_req_hr() runs on test_CT {
5175 var MSC_ConnHdlr vc_conn;
5176 f_init(1, true);
5177 f_sleep(1.0);
5178 f_enable_all_tch();
5179 f_disable_all_tch_h();
5180 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr_fail));
5181 vc_conn.done;
5182 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005183 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005184}
5185
5186/* Request a HR (prefered) or alternatively a FR channel while all HR channels
5187 * are exhausted, this is expected to be resolved by selecting a FR channel. */
5188testcase TC_assignment_codec_hr_exhausted_req_hr_fr() runs on test_CT {
5189 var MSC_ConnHdlr vc_conn;
5190 f_init(1, true);
5191 f_sleep(1.0);
5192 f_enable_all_tch();
5193 f_disable_all_tch_h();
5194 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_hr_fr));
5195 vc_conn.done;
5196 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005197 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005198}
5199
5200/* Request a FR (prefered) or alternatively a HR channel while all HR channels
5201 * are exhausted, this is expected to work without conflicts. */
5202testcase TC_assignment_codec_hr_exhausted_req_fr_hr() runs on test_CT {
5203 var MSC_ConnHdlr vc_conn;
5204 f_init(1, true);
5205 f_sleep(1.0);
5206 f_enable_all_tch();
5207 f_disable_all_tch_h();
5208 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_fr_hr));
5209 vc_conn.done;
5210 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005211 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005212}
5213
5214/* Allow FR and HR, but prefer HR */
5215private function f_TC_assignment_codec_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5216 g_pars := f_gen_test_hdlr_pars();
5217 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5218 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5219 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5220 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5221 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5222 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5223 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5224 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005225 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005226}
5227
5228/* Allow FR and HR, but prefer FR */
5229private function f_TC_assignment_codec_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5230 g_pars := f_gen_test_hdlr_pars();
5231 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5232 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5233 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5234 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5235 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5236 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5237 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5238 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005239 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005240}
5241
5242/* Request a HR (prefered) or alternatively a FR channel, it is expected that
5243 * HR, which is the prefered type, is selected. */
5244testcase TC_assignment_codec_req_hr_fr() runs on test_CT {
5245 var MSC_ConnHdlr vc_conn;
5246 f_init(1, true);
5247 f_sleep(1.0);
5248 f_enable_all_tch();
5249 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_hr_fr));
5250 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005251 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005252}
5253
5254/* Request a FR (prefered) or alternatively a HR channel, it is expected that
5255 * FR, which is the prefered type, is selected. */
5256testcase TC_assignment_codec_req_fr_hr() 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_fr_hr));
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
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005266/* request a signalling channel with all SDCCH exhausted, it is expected that a TCH will be selected */
5267private function f_TC_assignment_sdcch_exhausted_req_signalling(charstring id) runs on MSC_ConnHdlr {
5268 g_pars := f_gen_test_hdlr_pars();
5269 g_pars.ra := '02'O; /* RA containing reason=LU */
5270
5271 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5272 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5273 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5274 var template uint3_t tsc := ?;
5275
5276 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5277 f_create_bssmap_exp(l3_enc);
5278 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5279 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5280
5281 /* we should now have a COMPL_L3 at the MSC */
5282 timer T := 10.0;
5283 T.start;
5284 alt {
5285 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5286 [] T.timeout {
5287 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5288 }
5289 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005290
5291 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005292}
5293testcase TC_assignment_sdcch_exhausted_req_signalling() runs on test_CT {
5294 var MSC_ConnHdlr vc_conn;
5295 f_init(1, true);
5296 f_sleep(1.0);
5297 f_disable_all_sdcch();
5298 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_signalling));
5299 vc_conn.done;
5300 f_enable_all_sdcch();
5301 f_shutdown_helper();
5302}
5303
5304/* Request a signalling channel with all SDCCH exhausted, it is
5305 expected that no TCH will be selected for signalling and assigment will fail
5306 because it's dictated by VTY config */
5307testcase TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() runs on test_CT {
5308 var RSL_Message rsl_unused, rsl_msg;
5309 var GsmRrMessage rr;
5310 f_init(1, false);
5311 f_sleep(1.0);
5312 f_vty_allow_tch_for_signalling(false, 0);
5313 f_disable_all_sdcch();
5314
5315 /* RA containing reason=LU */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005316 f_ipa_tx(ts_RSL_CHAN_RQD('02'O, 2342));
5317 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005318 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
5319 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
5320 setverdict(fail, "Expected reject");
5321 }
5322
5323 f_vty_allow_tch_for_signalling(true, 0);
5324 f_enable_all_sdcch();
5325 f_shutdown_helper();
5326}
5327
5328/* Request a voice channel with all SDCCH exhausted, it is
5329 * expected that TCH channel will be allocated since the VTY option is only
5330 * aimed at signalling requests */
5331private function f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden(charstring id) runs on MSC_ConnHdlr {
5332 g_pars := f_gen_test_hdlr_pars();
5333 g_pars.ra := '43'O; /* RA containing reason=originating speech call*/
5334
5335 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5336 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5337 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5338 var template uint3_t tsc := ?;
5339
5340 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5341 f_create_bssmap_exp(l3_enc);
5342 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5343 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5344
5345 /* we should now have a COMPL_L3 at the MSC */
5346 timer T := 10.0;
5347 T.start;
5348 alt {
5349 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5350 [] T.timeout {
5351 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5352 }
5353 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005354 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005355}
5356testcase TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() runs on test_CT {
5357 var MSC_ConnHdlr vc_conn;
5358 f_init(1, true);
5359 f_sleep(1.0);
5360 f_vty_allow_tch_for_signalling(false, 0);
5361 f_disable_all_sdcch();
5362
5363 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden));
5364 vc_conn.done;
5365
5366 f_vty_allow_tch_for_signalling(true, 0);
5367 f_enable_all_sdcch();
5368 f_shutdown_helper();
5369}
5370
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005371/* Test Osmux setup BSC<->MSC */
5372testcase TC_assignment_osmux_cn() runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005373 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5374 var MSC_ConnHdlr vc_conn;
5375
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005376 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5377 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5378 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiyb9bf00f2022-09-14 15:35:37 +07005379 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02005380 pars.use_osmux_cn := true;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005381
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02005382 g_osmux_enabled_cn := true;
5383 f_init(1, true);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005384 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005385 f_vty_amr_start_mode_set(false, "1");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005386
5387 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5388 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005389
5390 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01005391 f_shutdown_helper();
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005392}
5393
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005394/* Test Osmux setup BTS<->BSC */
5395testcase TC_assignment_osmux_bts() runs on test_CT {
5396 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5397 var MSC_ConnHdlr vc_conn;
5398
5399 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5400 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5401 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005402 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005403 pars.use_osmux_bts := true;
5404
5405 g_osmux_enabled_bts := true;
5406 f_init(1, true);
5407 f_sleep(1.0);
5408 f_vty_amr_start_mode_set(false, "1");
5409
5410 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5411 vc_conn.done;
5412
5413 f_vty_amr_start_mode_restore(false);
5414 f_shutdown_helper();
5415}
5416
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +02005417/* Test non-AMR codecs still work fine as RTP when Osmux is enabled BTS<->BSC<->MSC */
5418testcase TC_assignment_codec_hr_osmux_on() runs on test_CT {
5419 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5420 var MSC_ConnHdlr vc_conn;
5421
5422 g_osmux_enabled_cn := true;
5423 g_osmux_enabled_bts := true;
5424 f_init(1, true);
5425 f_sleep(1.0);
5426 f_ctrs_bsc_and_bts_assignment_init(1);
5427
5428 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5429 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5430 vc_conn.done;
5431
5432 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
5433 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
5434 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
5435 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
5436 f_ctrs_bts_verify();
5437
5438 f_shutdown_helper();
5439}
5440
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005441/* Test Osmux setup BTS<->BSC<->MSC */
5442testcase TC_assignment_osmux() runs on test_CT {
5443 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5444 var MSC_ConnHdlr vc_conn;
5445
5446 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5447 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5448 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005449 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005450 pars.use_osmux_cn := true;
5451 pars.use_osmux_bts := true;
5452
5453 g_osmux_enabled_cn := true;
5454 g_osmux_enabled_bts := true;
5455 f_init(1, true);
5456 f_sleep(1.0);
5457 f_vty_amr_start_mode_set(false, "1");
5458
5459 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5460 vc_conn.done;
5461
5462 f_vty_amr_start_mode_restore(false);
5463 f_shutdown_helper();
5464}
5465
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005466/* test the procedure of the MSC requesting a Classmark Update:
5467 * a) BSSMAP Classmark Request should result in RR CLASSMARK ENQUIRY,
5468 * b) L3 RR CLASSMARK CHANGE should result in BSSMAP CLASSMARK UPDATE */
Harald Welte898113b2018-01-31 18:32:21 +01005469private function f_tc_classmark(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005470 g_pars := f_gen_test_hdlr_pars();
5471
Harald Weltea0630032018-03-20 21:09:55 +01005472 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005473 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005474
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005475 BSSAP.send(ts_BSSMAP_ClassmarkRequest);
5476 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_CM_ENQUIRY));
5477
Harald Welte898113b2018-01-31 18:32:21 +01005478 f_rsl_send_l3(ts_RRM_CM_CHG(valueof(ts_CM2)));
5479 BSSAP.receive(tr_BSSMAP_ClassmarkUpd(?, omit));
5480 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005481
5482 f_perform_clear();
Harald Welte898113b2018-01-31 18:32:21 +01005483}
5484testcase TC_classmark() runs on test_CT {
5485 var MSC_ConnHdlr vc_conn;
5486 f_init(1, true);
5487 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005488 vc_conn := f_start_handler(refers(f_tc_classmark));
Harald Welte898113b2018-01-31 18:32:21 +01005489 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005490 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005491}
5492
Harald Welteeddf0e92020-06-21 19:42:15 +02005493/* Send a CommonID from the simulated MSC and verify that the information is used to
5494 * fill BSC-internal data structures (specifically, bsc_subscr associated with subscr_conn) */
5495private function f_tc_common_id(charstring id) runs on MSC_ConnHdlr {
5496 g_pars := f_gen_test_hdlr_pars();
5497 f_MscConnHdlr_init_vty();
5498
5499 f_create_chan_and_exp();
5500 /* we should now have a COMPL_L3 at the MSC */
Harald Welteeddf0e92020-06-21 19:42:15 +02005501
5502 /* Send CommonID */
5503 BSSAP.send(ts_BSSMAP_CommonId(g_pars.imsi));
5504
5505 /* Use VTY to verify that the IMSI of the subscr_conn is set */
5506 var charstring regex := "*(IMSI: " & hex2str(g_pars.imsi) & ")*";
5507 f_vty_transceive_match_regexp_retry(BSCVTY, "show conns", regex, 0, 4, 1.0);
5508
5509 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005510
5511 f_perform_clear();
Harald Welteeddf0e92020-06-21 19:42:15 +02005512}
5513testcase TC_common_id() runs on test_CT {
5514 var MSC_ConnHdlr vc_conn;
5515 f_init(1, true);
5516 f_sleep(1.0);
5517 vc_conn := f_start_handler(refers(f_tc_common_id));
5518 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005519 f_shutdown_helper();
Harald Welteeddf0e92020-06-21 19:42:15 +02005520}
5521
Harald Weltee3bd6582018-01-31 22:51:25 +01005522private function f_est_single_l3(template PDU_ML3_MS_NW l3) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005523 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005524 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005525 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005526
Harald Weltee3bd6582018-01-31 22:51:25 +01005527 /* send the single message we want to send */
5528 f_rsl_send_l3(l3);
5529}
5530
5531private function f_bssap_expect_nothing(float sec := 5.00) runs on MSC_ConnHdlr {
5532 timer T := sec;
5533 var PDU_BSSAP bssap;
Harald Welte898113b2018-01-31 18:32:21 +01005534 T.start;
5535 alt {
Harald Weltee3bd6582018-01-31 22:51:25 +01005536 [] BSSAP.receive(PDU_BSSAP:?) -> value bssap {
5537 setverdict(fail, "Unexpected BSSMAP ", bssap);
Daniel Willmannafce8662018-07-06 23:11:32 +02005538 mtc.stop;
Harald Welte898113b2018-01-31 18:32:21 +01005539 }
5540 [] T.timeout {
5541 setverdict(pass);
5542 }
5543 }
5544}
5545
Harald Weltee3bd6582018-01-31 22:51:25 +01005546/* unsolicited ASSIGNMENT FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5547private function f_tc_unsol_ass_fail(charstring id) runs on MSC_ConnHdlr {
5548 f_est_single_l3(ts_RRM_AssignmentFailure('00'O));
5549 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005550 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005551}
Harald Welte898113b2018-01-31 18:32:21 +01005552testcase TC_unsol_ass_fail() runs on test_CT {
5553 var MSC_ConnHdlr vc_conn;
5554 f_init(1, true);
5555 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005556 vc_conn := f_start_handler(refers(f_tc_unsol_ass_fail));
Harald Welte898113b2018-01-31 18:32:21 +01005557 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005558 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005559}
Harald Welte552620d2017-12-16 23:21:36 +01005560
Harald Welteea99a002018-01-31 20:46:43 +01005561
5562/* unsolicited ASSIGNMENT COMPLETE (without ASSIGN) from MS shouldn't bring BSC down */
5563private function f_tc_unsol_ass_compl(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005564 f_est_single_l3(ts_RRM_AssignmentComplete('00'O));
5565 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005566 f_perform_clear();
Harald Welteea99a002018-01-31 20:46:43 +01005567}
5568testcase TC_unsol_ass_compl() runs on test_CT {
5569 var MSC_ConnHdlr vc_conn;
5570 f_init(1, true);
5571 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005572 vc_conn := f_start_handler(refers(f_tc_unsol_ass_compl));
Harald Welteea99a002018-01-31 20:46:43 +01005573 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005574 f_shutdown_helper();
Harald Welteea99a002018-01-31 20:46:43 +01005575}
5576
5577
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005578/* unsolicited HANDOVER FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5579private function f_tc_unsol_ho_fail(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005580 f_est_single_l3(ts_RRM_HandoverFailure('00'O));
5581 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005582 f_perform_clear();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005583}
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005584testcase TC_unsol_ho_fail() runs on test_CT {
5585 var MSC_ConnHdlr vc_conn;
5586 f_init(1, true);
5587 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005588 vc_conn := f_start_handler(refers(f_tc_unsol_ho_fail));
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005589 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005590 f_shutdown_helper();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005591}
5592
5593
Harald Weltee3bd6582018-01-31 22:51:25 +01005594/* short message from MS should be ignored */
5595private function f_tc_err_82_short_msg(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005596 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005597 f_create_chan_and_exp();
Harald Weltee3bd6582018-01-31 22:51:25 +01005598 /* we should now have a COMPL_L3 at the MSC */
Harald Weltee3bd6582018-01-31 22:51:25 +01005599
5600 /* send short message */
5601 RSL.send(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), ''O));
5602 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005603 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005604}
5605testcase TC_err_82_short_msg() runs on test_CT {
5606 var MSC_ConnHdlr vc_conn;
5607 f_init(1, true);
5608 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005609 vc_conn := f_start_handler(refers(f_tc_err_82_short_msg));
Harald Weltee3bd6582018-01-31 22:51:25 +01005610 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005611 f_shutdown_helper();
Harald Weltee3bd6582018-01-31 22:51:25 +01005612}
5613
5614
Harald Weltee9e02e42018-01-31 23:36:25 +01005615/* 24.008 8.4 Unknown message must trigger RR STATUS */
5616private function f_tc_err_84_unknown_msg(charstring id) runs on MSC_ConnHdlr {
5617 f_est_single_l3(ts_RRM_UL_REL('00'O));
5618 timer T := 3.0
5619 alt {
5620 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_STATUS)) {
5621 setverdict(pass);
5622 }
5623 [] BSSAP.receive { setverdict(fail, "unexpected BSSAP"); }
Harald Welte458fd372018-03-21 11:26:23 +01005624 [] T.timeout { setverdict(fail, "Timeout waiting for RR STATUS"); }
Harald Weltee9e02e42018-01-31 23:36:25 +01005625 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005626 f_perform_clear();
Harald Weltee9e02e42018-01-31 23:36:25 +01005627}
5628testcase TC_err_84_unknown_msg() runs on test_CT {
5629 var MSC_ConnHdlr vc_conn;
5630 f_init(1, true);
5631 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005632 vc_conn := f_start_handler(refers(f_tc_err_84_unknown_msg));
Harald Weltee9e02e42018-01-31 23:36:25 +01005633 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005634 f_shutdown_helper();
Harald Weltee9e02e42018-01-31 23:36:25 +01005635}
5636
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005637/***********************************************************************
5638 * Handover
5639 ***********************************************************************/
5640
Harald Welte94e0c342018-04-07 11:33:23 +02005641/* execute a "bts <0-255> trx <0-255> timeslot <0-7> " command on given Dchan */
5642private function f_vty_ts_action(charstring suffix, integer bts_nr, integer trx_nr, integer ts_nr)
5643runs on test_CT {
5644 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5645 " timeslot "&int2str(ts_nr)&" ";
5646 f_vty_transceive(BSCVTY, cmd & suffix);
5647}
5648
Harald Welte261af4b2018-02-12 21:20:39 +01005649/* 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 +07005650private function f_vty_ss_action(TELNETasp_PT pt, charstring suffix,
5651 uint8_t bts_nr, uint8_t trx_nr,
5652 in RslChannelNr chan_nr)
5653{
Harald Welte261af4b2018-02-12 21:20:39 +01005654 /* FIXME: resolve those from component-global state */
5655 var integer ts_nr := chan_nr.tn;
5656 var integer ss_nr;
5657 if (ischosen(chan_nr.u.ch0)) {
5658 ss_nr := 0;
5659 } else if (ischosen(chan_nr.u.lm)) {
5660 ss_nr := chan_nr.u.lm.sub_chan;
5661 } else if (ischosen(chan_nr.u.sdcch4)) {
5662 ss_nr := chan_nr.u.sdcch4.sub_chan;
5663 } else if (ischosen(chan_nr.u.sdcch8)) {
5664 ss_nr := chan_nr.u.sdcch8.sub_chan;
5665 } else {
5666 setverdict(fail, "Invalid ChanNr ", chan_nr);
Daniel Willmannafce8662018-07-06 23:11:32 +02005667 mtc.stop;
Harald Welte261af4b2018-02-12 21:20:39 +01005668 }
5669
5670 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5671 " timeslot "&int2str(ts_nr)&" sub-slot "&int2str(ss_nr)&" ";
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005672 f_vty_transceive(pt, cmd & suffix);
Harald Welte261af4b2018-02-12 21:20:39 +01005673}
5674
Neels Hofmeyr91401012019-07-11 00:42:35 +02005675/* Even though the VTY command to trigger handover takes a new BTS number as argument, behind the scenes osmo-bsc always
5676 * translates that to a target ARFCN+BSIC first. See bsc_vty.c trigger_ho_or_as(), which puts the selected BTS' neighbor
5677 * ident key (ARFCN + BSIC) in the struct passed on to handover_request(). handover_start() then resolves that to a
5678 * viable actual neighbor cell. So from the internal osmo-bsc perspective, we always request handover to an ARFCN + BSIC
5679 * pair, not really to a specific BTS number. */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005680private function f_vty_handover(TELNETasp_PT pt, uint8_t bts_nr, uint8_t trx_nr,
5681 in RslChannelNr chan_nr, uint8_t new_bts_nr)
5682{
5683 f_vty_ss_action(pt, "handover " & int2str(new_bts_nr), bts_nr, trx_nr, chan_nr);
Harald Welte261af4b2018-02-12 21:20:39 +01005684}
5685
5686/* intra-BSC hand-over between BTS0 and BTS1 */
5687private function f_tc_ho_int(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02005688 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5689 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte261af4b2018-02-12 21:20:39 +01005690
5691 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5692 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5693
Harald Weltea0630032018-03-20 21:09:55 +01005694 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr666f0432020-07-04 00:53:07 +02005695 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Harald Welte261af4b2018-02-12 21:20:39 +01005696
5697 var HandoverState hs := {
5698 rr_ho_cmpl_seen := false,
5699 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005700 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005701 expect_target_tsc := c_BtsParams[1].tsc
Harald Welte261af4b2018-02-12 21:20:39 +01005702 };
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005703 /* issue hand-over command on VTY, from BTS 0 to BTS 1 */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005704 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
Harald Welte261af4b2018-02-12 21:20:39 +01005705 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5706 f_rslem_suspend(RSL1_PROC);
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005707
5708 /* From the MGW perspective, a handover is is characterized by
5709 * performing one MDCX operation with the MGW. So we expect to see
5710 * one more MDCX during handover. */
5711 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5712
Harald Welte261af4b2018-02-12 21:20:39 +01005713 alt {
5714 [] as_handover(hs);
Harald Welte261af4b2018-02-12 21:20:39 +01005715 }
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005716
Philipp Maier4dae0652018-11-12 12:03:26 +01005717 /* Since this is an internal handover we expect the BSC to inform the
5718 * MSC about the event */
5719 BSSAP.receive(tr_BSSMAP_HandoverPerformed);
5720
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005721 /* Check the amount of MGCP transactions is still consistant with the
5722 * test expectation */
5723 f_check_mgcp_expectations()
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005724
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005725 var RSL_Message chan_act := f_rslem_get_last_act(RSL1_PROC, 0, g_chan_nr);
5726
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005727 /* Ensure the Channel Activation for the new channel contained the right encryption params. as_handover() set
5728 * 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 +02005729 f_verify_encr_info(chan_act);
5730
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005731 f_chan_act_verify_tsc(chan_act, c_BtsParams[1].tsc);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005732
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005733 f_perform_clear(RSL1, RSL1_PROC);
5734
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01005735 f_sleep(0.5);
Harald Welte261af4b2018-02-12 21:20:39 +01005736}
5737
5738testcase TC_ho_int() runs on test_CT {
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005739 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte261af4b2018-02-12 21:20:39 +01005740 var MSC_ConnHdlr vc_conn;
5741 f_init(2, true);
5742 f_sleep(1.0);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005743
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005744 pars.expect_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005745
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005746 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005747
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005748 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
Harald Welte261af4b2018-02-12 21:20:39 +01005749 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005750
5751 /* from f_establish_fully() */
5752 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5753 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5754 /* from handover */
5755 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5756 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5757 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5758 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005759 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5760 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005761 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02005762 f_shutdown_helper(ho := true);
Harald Welte261af4b2018-02-12 21:20:39 +01005763}
Harald Weltee9e02e42018-01-31 23:36:25 +01005764
Oliver Smith7eabd312021-07-12 14:18:56 +02005765function 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 +02005766 var MSC_ConnHdlr vc_conn;
5767 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5768 pars.encr := valueof(t_EncrParams(encr_alg, f_rnd_octstring(8), f_rnd_octstring(16)));
5769
5770 f_init(2, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02005771 f_vty_encryption_a5(enc_a5);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005772 f_sleep(1.0);
5773
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005774 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005775
5776 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
5777 vc_conn.done;
5778
5779 /* from f_establish_fully() */
5780 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5781 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5782 /* from handover */
5783 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5784 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5785 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5786 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005787 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5788 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005789 f_ctrs_bsc_and_bts_verify();
Oliver Smith7eabd312021-07-12 14:18:56 +02005790 f_vty_encryption_a5_reset();
Oliver Smith39f53072022-10-27 14:44:04 +02005791 f_shutdown_helper(ho := true);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005792}
5793
5794testcase TC_ho_int_a5_0() runs on test_CT {
5795 f_tc_ho_int_a5('01'O);
5796}
5797
5798testcase TC_ho_int_a5_1() runs on test_CT {
5799 f_tc_ho_int_a5('02'O);
5800}
5801
5802testcase TC_ho_int_a5_3() runs on test_CT {
5803 f_tc_ho_int_a5('08'O);
5804}
5805
5806testcase TC_ho_int_a5_4() runs on test_CT {
Oliver Smith7eabd312021-07-12 14:18:56 +02005807 f_tc_ho_int_a5('10'O, "0 1 3 4");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005808}
5809
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005810/* intra-BSC hand-over with CONNection FAILure and cause Radio Link Failure: check RR release cause */
5811private function f_tc_ho_int_radio_link_failure(charstring id) runs on MSC_ConnHdlr {
5812 g_pars := f_gen_test_hdlr_pars();
5813 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5814 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005815
5816 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5817 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5818
5819 f_establish_fully(ass_cmd, exp_compl);
5820 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
5821
5822 var HandoverState hs := {
5823 rr_ho_cmpl_seen := false,
5824 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005825 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005826 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005827 };
5828 /* issue hand-over command on VTY */
5829 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
5830 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5831 f_rslem_suspend(RSL1_PROC);
5832
5833 /* From the MGW perspective, a handover is is characterized by
5834 * performing one MDCX operation with the MGW. So we expect to see
5835 * one more MDCX during handover. */
5836 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5837
5838 var RSL_Message rsl;
5839 var PDU_ML3_NW_MS l3;
5840 var RslChannelNr new_chan_nr;
5841 var GsmArfcn arfcn;
5842 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
5843 l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
5844 if (not ischosen(l3.msgs.rrm.handoverCommand)) {
5845 setverdict(fail, "Expected handoverCommand");
5846 mtc.stop;
5847 }
5848 }
5849 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
5850 new_chan_nr, arfcn);
5851
5852 f_rslem_register(0, new_chan_nr, RSL1_PROC);
5853
5854 /* resume processing of RSL DChan messages, which was temporarily suspended
5855 * before performing a hand-over */
5856 f_rslem_resume(RSL1_PROC);
5857 RSL1.receive(tr_RSL_IPA_CRCX(new_chan_nr));
5858
5859 f_sleep(1.0);
5860
5861 /* Handover fails because no HANDO DET appears on the new lchan,
5862 * and the old lchan reports a Radio Link Failure. */
5863 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
5864
5865 var PDU_BSSAP rx_clear_request;
5866 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
5867 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
5868 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5869
5870 var RR_Cause rr_cause := GSM48_RR_CAUSE_ABNORMAL_UNSPEC;
5871
5872 var MgcpCommand mgcp;
5873 interleave {
5874 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE(int2oct(enum2int(rr_cause), 1)))) {}
5875 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005876 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005877 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005878 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005879 }
5880 [] RSL1.receive(tr_RSL_DEACT_SACCH(new_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005881 [] RSL1.receive(tr_RSL_RF_CHAN_REL(new_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005882 RSL1.send(ts_RSL_RF_CHAN_REL_ACK(new_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005883 f_rslem_unregister(0, g_chan_nr, PT := RSL1_PROC);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005884 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005885 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
5886 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
5887 }
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005888 }
5889
5890 f_sleep(0.5);
5891 setverdict(pass);
5892}
5893testcase TC_ho_int_radio_link_failure() runs on test_CT {
5894 var MSC_ConnHdlr vc_conn;
5895 f_init(2, true);
5896 f_sleep(1.0);
5897
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005898 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005899
5900 vc_conn := f_start_handler(refers(f_tc_ho_int_radio_link_failure));
5901 vc_conn.done;
5902
5903 /* from f_establish_fully() */
5904 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5905 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5906 /* from handover */
5907 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5908 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
5909 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5910 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:stopped");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005911 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5912 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:stopped");
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005913 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02005914 f_shutdown_helper(ho := true);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005915}
5916
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005917/* Expecting MGCP to DLCX the endpoint's two connections: towards BTS and towards MSC */
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005918private function f_expect_dlcx_conns() runs on MSC_ConnHdlr {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005919 var MgcpCommand mgcp;
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005920 var template MgcpResponse mgcp_resp;
5921 var MGCP_RecvFrom mrf;
5922 var template MgcpMessage msg_resp;
5923 var template MgcpMessage msg_dlcx := {
5924 command := tr_DLCX()
5925 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005926
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005927 if (g_pars.aoip) {
5928 MGCP.receive(tr_DLCX()) -> value mgcp {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005929 log("Got first DLCX: ", mgcp);
5930 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005931 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005932
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005933 MGCP.receive(tr_DLCX()) -> value mgcp {
5934 log("Got second DLCX: ", mgcp);
5935 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
5936 };
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005937 } else {
5938 /* For SCCPLite, BSC doesn't handle the MSC-side */
5939 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
5940 log("Got first DLCX: ", mrf.msg.command);
5941 msg_resp := {
5942 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
5943 }
5944 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, msg_resp));
5945 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005946 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005947}
5948
Oliver Smithc9a5f532022-10-21 11:32:23 +02005949private function f_ho_out_of_this_bsc(template (omit) BSSMAP_oldToNewBSSIEs exp_oldToNewBSSIEs := omit,
5950 boolean skip_meas_rep := false) runs on MSC_ConnHdlr {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005951
Oliver Smithc9a5f532022-10-21 11:32:23 +02005952 if (not skip_meas_rep) {
5953 var NcellReports neighbor_rep := {
5954 { rxlev := 20, bcch_freq := 0, bsic := 11 }
5955 };
5956 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
5957 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
5958 l3_mr, 0));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005959
Oliver Smithc9a5f532022-10-21 11:32:23 +02005960 BSSAP.receive(tr_BSSMAP_HandoverRequired(exp_oldToNewBSSIEs));
5961 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005962
5963 f_sleep(0.5);
5964 /* The MSC negotiates Handover Request and Handover Request Ack with
5965 * the other BSS and comes back with a BSSMAP Handover Command
5966 * containing an RR Handover Command coming from the target BSS... */
5967
5968 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
5969 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
5970 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
5971 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
5972 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
5973
5974 /* expect the Handover Command to go out on RR */
5975 var RSL_Message rsl_ho_cmd
5976 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
5977 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
5978 var RSL_IE_Body rsl_ho_cmd_l3;
5979 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
5980 log("RSL message contains no L3 Info IE, expected RR Handover Command");
5981 setverdict(fail);
5982 } else {
5983 log("Found L3 Info: ", rsl_ho_cmd_l3);
5984 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
5985 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
5986 setverdict(fail);
5987 } else {
5988 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
5989 setverdict(pass);
5990 }
5991 }
5992
5993 /* When the other BSS has reported a completed handover, this side is
5994 * torn down. */
5995
5996 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_HANDOVER_SUCCESSFUL;
5997 var BssmapCause cause := enum2int(cause_val);
5998 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5999
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006000 f_expect_dlcx_conns();
Pau Espin Pedrol06199952021-06-15 11:30:00 +02006001
6002 interleave {
6003 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE));
6004 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr));
6005 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006006 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
6007 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
6008 }
Pau Espin Pedrol06199952021-06-15 11:30:00 +02006009 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006010 setverdict(pass);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006011}
6012
6013private function f_tc_ho_out_of_this_bsc(charstring id) runs on MSC_ConnHdlr {
6014 g_pars := f_gen_test_hdlr_pars();
6015 var PDU_BSSAP ass_req := f_gen_ass_req();
6016 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6017 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6018 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6019 f_establish_fully(ass_req, exp_compl);
6020
6021 f_ho_out_of_this_bsc();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006022}
6023testcase TC_ho_out_of_this_bsc() runs on test_CT {
6024 var MSC_ConnHdlr vc_conn;
6025
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01006026 f_init_vty();
6027 f_bts_0_cfg(BSCVTY,
6028 {"neighbor-list mode automatic",
6029 "handover 1",
6030 "handover algorithm 2",
6031 "handover2 window rxlev averaging 1",
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006032 "no neighbors",
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01006033 "neighbor lac 99 arfcn 123 bsic any"});
6034 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6035
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006036 f_init(1, true);
6037 f_sleep(1.0);
6038
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006039 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006040
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006041 vc_conn := f_start_handler(refers(f_tc_ho_out_of_this_bsc));
6042 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006043
6044 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6045 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6046 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6047 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6048 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6049 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
6050 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006051 f_shutdown_helper(ho := true);
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006052}
6053
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006054private function f_mo_l3_transceive(RSL_DCHAN_PT rsl := RSL,
6055 template (value) RslLinkId link_id := ts_RslLinkID_DCCH(0),
Vadim Yanitskiy2ef6a2f2020-10-08 23:17:32 +07006056 template (present) OCT1 dlci := ?,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07006057 octetstring l3 := '0123456789'O)
6058runs on MSC_ConnHdlr {
Neels Hofmeyr43654812020-09-25 01:35:35 +02006059 /* The old lchan and conn should still be active. See that arbitrary L3
6060 * is still going through. */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006061 rsl.send(ts_RSL_DATA_IND(g_chan_nr, link_id, l3));
Neels Hofmeyr43654812020-09-25 01:35:35 +02006062 var template PDU_BSSAP exp_data := {
6063 discriminator := '1'B,
6064 spare := '0000000'B,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07006065 dlci := dlci,
6066 lengthIndicator := lengthof(l3),
Neels Hofmeyr43654812020-09-25 01:35:35 +02006067 pdu := {
6068 dtap := l3
6069 }
6070 };
6071 BSSAP.receive(exp_data);
6072 setverdict(pass);
6073}
6074
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006075private function f_mt_l3_transceive(RSL_DCHAN_PT rsl := RSL,
6076 template (present) RslLinkId link_id := tr_RslLinkID_DCCH(0),
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07006077 template (value) OCT1 dlci := '00'O,
6078 octetstring l3 := '0123456789'O)
6079runs on MSC_ConnHdlr {
6080 BSSAP.send(PDU_BSSAP:{
6081 discriminator := '1'B,
6082 spare := '0000000'B,
6083 dlci := dlci,
6084 lengthIndicator := lengthof(l3),
6085 pdu := {
6086 dtap := l3
6087 }
6088 });
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006089 rsl.receive(tr_RSL_DATA_REQ(g_chan_nr, link_id, l3));
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07006090 setverdict(pass);
6091}
6092
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006093/* BSC asks for inter-BSC HO, but the MSC decides that it won't happen and
6094 * simply never sends a BSSMAP Handover Command. */
6095private function f_tc_ho_out_fail_no_msc_response(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006096 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006097
6098 var PDU_BSSAP ass_req := f_gen_ass_req();
6099 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6100 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6101 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6102 f_establish_fully(ass_req, exp_compl);
6103
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006104 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006105 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6106
6107 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6108
6109 /* osmo-bsc should time out 10 seconds after the handover started.
6110 * Let's give it a bit extra. */
6111 f_sleep(15.0);
6112
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006113 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006114 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006115 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006116}
6117testcase TC_ho_out_fail_no_msc_response() runs on test_CT {
6118 var MSC_ConnHdlr vc_conn;
6119
6120 f_init(1, true);
6121 f_sleep(1.0);
6122
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006123 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006124
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006125 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_msc_response));
6126 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006127
6128 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6129 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6130 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6131 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6132 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6133 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6134 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006135 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006136}
6137
6138/* BSC asks for inter-BSC HO, receives BSSMAP Handover Command, but MS reports
6139 * RR Handover Failure. */
6140private function f_tc_ho_out_fail_rr_ho_failure(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006141 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006142
6143 var PDU_BSSAP ass_req := f_gen_ass_req();
6144 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6145 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6146 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6147 f_establish_fully(ass_req, exp_compl);
6148
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006149 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006150 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6151
6152 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6153
6154 f_sleep(0.5);
6155 /* The MSC negotiates Handover Request and Handover Request Ack with
6156 * the other BSS and comes back with a BSSMAP Handover Command
6157 * containing an RR Handover Command coming from the target BSS... */
6158
6159 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6160 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6161 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6162 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6163 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6164
6165 /* expect the Handover Command to go out on RR */
6166 var RSL_Message rsl_ho_cmd
6167 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6168 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6169 var RSL_IE_Body rsl_ho_cmd_l3;
6170 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6171 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6172 setverdict(fail);
6173 } else {
6174 log("Found L3 Info: ", rsl_ho_cmd_l3);
6175 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6176 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6177 setverdict(fail);
6178 } else {
6179 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6180 setverdict(pass);
6181 }
6182 }
6183
6184 f_sleep(0.2);
6185 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
6186
6187 /* Should tell the MSC about the failure */
6188 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6189
6190 f_sleep(1.0);
6191
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006192 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006193 f_sleep(1.0);
6194
6195 setverdict(pass);
6196 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006197 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006198}
6199testcase TC_ho_out_fail_rr_ho_failure() runs on test_CT {
6200 var MSC_ConnHdlr vc_conn;
6201
6202 f_init(1, true);
6203 f_sleep(1.0);
6204
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006205 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006206
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006207 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_rr_ho_failure));
6208 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006209
6210 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6211 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6212 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6213 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6214 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6215 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:failed");
6216 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006217 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006218}
6219
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006220/* BSC asks for inter-BSC-out HO, receives BSSMAP Handover Command, but then no reply is received about HO outcome
6221 * (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 +02006222 * and the lchan is released. */
6223private function f_tc_ho_out_fail_no_result_after_ho_cmd(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006224 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006225
6226 var PDU_BSSAP ass_req := f_gen_ass_req();
6227 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6228 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6229 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6230 f_establish_fully(ass_req, exp_compl);
6231
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006232 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006233 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6234
6235 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6236
6237 f_sleep(0.5);
6238 /* The MSC negotiates Handover Request and Handover Request Ack with
6239 * the other BSS and comes back with a BSSMAP Handover Command
6240 * containing an RR Handover Command coming from the target BSS... */
6241
6242 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6243 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6244 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6245 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6246 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6247
6248 /* expect the Handover Command to go out on RR */
6249 var RSL_Message rsl_ho_cmd
6250 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6251 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6252 var RSL_IE_Body rsl_ho_cmd_l3;
6253 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6254 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6255 setverdict(fail);
6256 } else {
6257 log("Found L3 Info: ", rsl_ho_cmd_l3);
6258 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6259 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6260 setverdict(fail);
6261 } else {
6262 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6263 setverdict(pass);
6264 }
6265 }
6266
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006267 /* We get neither success nor failure report from the remote BSS. Eventually T8 times out and we run into 3GPP
6268 * TS 48.008 3.1.5.3.3 "Abnormal Conditions": Clear Request should go to the MSC, and RR should be released
6269 * after Clear Command */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006270
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006271 var PDU_BSSAP rx_clear_request;
Neels Hofmeyre1797aa2019-07-09 19:34:04 +02006272 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
6273 log("Got BSSMAP Clear Request");
6274 /* Instruct BSC to clear channel */
6275 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
6276 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6277
6278 var MgcpCommand mgcp;
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006279 interleave {
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01006280 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
6281 log("Got Deact SACCH");
6282 }
Harald Welte924b6ea2019-02-04 01:05:34 +01006283 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
Neels Hofmeyr211169d2018-11-07 00:37:29 +01006284 log("Got RR Release");
6285 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02006286 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006287 log("Got RF Chan Rel");
6288 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02006289 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006290 }
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006291 }
6292
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006293 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006294 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006295 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006296
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006297 setverdict(pass);
6298 f_sleep(1.0);
6299}
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006300testcase TC_ho_out_fail_no_result_after_ho_cmd() runs on test_CT {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006301 var MSC_ConnHdlr vc_conn;
6302
6303 f_init(1, true);
6304 f_sleep(1.0);
6305
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006306 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006307
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006308 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_result_after_ho_cmd));
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006309 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006310
6311 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6312 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6313 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6314 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6315 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6316 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6317 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006318 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006319}
6320
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006321private 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 +01006322 var PDU_BSSAP rx_bssap;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006323 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6324 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6325 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6326 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6327 * before we get started. */
6328 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6329 f_rslem_register(0, new_chan_nr);
6330 g_chan_nr := new_chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06006331 var uint3_t expect_target_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006332 f_sleep(1.0);
6333
6334 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6335 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006336 var default as_media := activate(as_Media());
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006337
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01006338 var PDU_BSSAP ho_req := f_gen_handover_req(aoip_tla := g_pars.host_aoip_tla,
6339 cell_id_source := g_pars.cell_id_source,
6340 oldToNewBSSIEs := oldToNewBSSIEs,
6341 enc := g_pars.encr);
6342 if (g_pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr) {
6343 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, ho_req));
6344 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6345 } else {
6346 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, omit));
6347 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6348 BSSAP.send(ho_req);
6349 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006350
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006351 alt {
6352 [] BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap {
6353 if (g_pars.expect_ho_fail) {
6354 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6355 "Expected Handover Request to fail, but got Handover Request Ack")
6356 }
6357 }
6358 [] BSSAP.receive(tr_BSSMAP_HandoverFailure) -> value rx_bssap {
6359 if (not g_pars.expect_ho_fail) {
6360 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6361 "Expected Handover Request to succeed, but got Handover Failure")
6362 }
6363 // TODO: evaluate correct cause value. But osmo-bsc doesn't seem to send meaningful causes yet!
6364 // For now just accept any cause.
6365 BSSAP.receive(tr_BSSMAP_ClearRequest);
6366 setverdict(pass);
6367 return;
6368 }
6369 }
6370
Oliver Smith7a8594a2023-02-13 14:30:49 +01006371 if (g_pars.expect_ho_fail_lchan_est) {
6372 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6373 setverdict(pass);
Oliver Smitha1cbec52023-02-21 12:44:12 +01006374
6375 /* When we let MGCP MDCX run into a timeout, it's still in the
6376 * queue and additionally after BSSAP HandoverFailure, two DLCX
Oliver Smith30eb8822023-03-06 12:31:53 +01006377 * get sent (for AoIP, for SCCPlite one DLCX). */
Oliver Smitha1cbec52023-02-21 12:44:12 +01006378 if (g_pars.ignore_mgw_mdcx) {
Oliver Smith30eb8822023-03-06 12:31:53 +01006379 if (g_pars.aoip) {
6380 MGCP.receive(tr_MDCX);
6381 MGCP.receive(tr_DLCX);
6382 MGCP.receive(tr_DLCX);
6383 } else {
6384 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any({command := tr_MDCX}));
6385 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any({command := tr_DLCX}));
6386 }
Oliver Smitha1cbec52023-02-21 12:44:12 +01006387 }
Oliver Smith7a8594a2023-02-13 14:30:49 +01006388 return;
6389 }
6390
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006391 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6392
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006393 /* we're sure that the channel activation is done now, verify the parameters in it */
6394 var RSL_Message chan_act := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
6395 f_verify_encr_info(chan_act);
6396 f_chan_act_verify_tsc(chan_act, expect_target_tsc);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006397
Neels Hofmeyr46e16e52022-02-23 17:04:00 +01006398 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.codecList)) {
6399 if (not g_pars.aoip) {
6400 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6401 "handoverRequestAck: Expected no Speech Codec List (BSS Supported), because this is not AoIP");
6402 }
6403 /* TODO: check actual codecs? */
6404 } else {
6405 if (g_pars.aoip) {
6406 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6407 "handoverRequestAck: Expected Speech Codec List (BSS Supported), but none found");
6408 }
6409 }
6410
6411 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.speechCodec)) {
6412 if (not g_pars.aoip) {
6413 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6414 "handoverRequestAck: Expected no Speech Codec (Chosen), because this is not AoIP");
6415 }
6416 /* TODO: check actual codec? */
6417 } else {
6418 if (g_pars.aoip) {
6419 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6420 "handoverRequestAck: Expected Speech Codec (Chosen), but none found");
6421 }
6422 }
6423
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006424 var octetstring ho_command_str;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006425 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6426 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6427 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6428 log("L3 Info in HO Request Ack is ", ho_command);
6429
6430 var GsmArfcn arfcn;
6431 var RslChannelNr actual_new_chan_nr;
6432 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6433 actual_new_chan_nr, arfcn);
6434
6435 if (actual_new_chan_nr != new_chan_nr) {
6436 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6437 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6438 setverdict(fail);
6439 return;
6440 }
6441 log("Handover Command chan_nr is", actual_new_chan_nr);
6442
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006443 var uint3_t got_tsc := rr_chan_desc_tsc(ho_command.msgs.rrm.handoverCommand.channelDescription2);
6444 if (not match(got_tsc, expect_target_tsc)) {
6445 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
6446 expect_target_tsc, " got ", got_tsc);
6447 mtc.stop;
6448 } else {
6449 log("handoverCommand: verified TSC = ", got_tsc);
6450 }
6451
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006452 /* Check the Cipher Mode Setting IE (shall be present during inter-RAT handover) */
6453 if (ispresent(ho_command.msgs.rrm.handoverCommand.cipherModeSetting)) {
6454 var CipherModeSetting_TV cms := ho_command.msgs.rrm.handoverCommand.cipherModeSetting;
6455 var template (present) CipherModeSetting_TV tr_cms := {
6456 sC := '0'B, /* no ciphering by default */
6457 algorithmIdentifier := '000'B,
6458 elementIdentifier := ?
6459 };
6460 if (ispresent(g_pars.encr) and g_pars.encr.enc_alg_expect != '01'O) { /* A5/N */
6461 tr_cms.algorithmIdentifier := f_cipher_mode_bssmap_to_rr(g_pars.encr.enc_alg_expect);
6462 tr_cms.sC := '1'B;
6463 }
6464 if (not match(cms, tr_cms)) {
6465 setverdict(fail, "RR Handover Command: unexpected Cipher Mode Setting IE: ",
6466 cms, ", expected: ", tr_cms);
6467 }
6468 } else {
6469 setverdict(fail, "RR Handover Command: Cipher Mode Setting IE is not present");
6470 }
6471
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006472 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6473 * tells the MS to handover to the new lchan. Here comes the new MS on
6474 * the new lchan with a Handover RACH: */
6475
6476 /* send handover detect */
6477
6478 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6479
6480 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6481
6482 /* send handover complete over the new channel */
6483
6484 var PDU_ML3_MS_NW l3_tx := valueof(ts_RRM_HandoverComplete('00'O));
6485 RSL.send(ts_RSL_EST_IND(new_chan_nr, valueof(ts_RslLinkID_DCCH(0)),
6486 enc_PDU_ML3_MS_NW(l3_tx)));
6487
6488 BSSAP.receive(tr_BSSMAP_HandoverComplete);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006489 deactivate(as_media);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006490 setverdict(pass);
6491}
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006492
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006493private function f_tc_ho_into_this_bsc(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006494 var template PDU_ML3_NW_MS exp_rr_rel_tmpl;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006495 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit;
6496 if (not istemplatekind(g_pars.last_used_eutran_plmn, "omit")) {
6497 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006498 }
6499 if (g_pars.exp_fast_return) {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006500 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE_CellSelectInd;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006501 } else {
6502 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006503 }
6504 f_ho_into_this_bsc(id, oldToNewBSSIEs);
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006505 if (g_pars.expect_ho_fail) {
6506 f_perform_clear_no_lchan();
Oliver Smith7a8594a2023-02-13 14:30:49 +01006507 } else if (g_pars.expect_ho_fail_lchan_est) {
6508 BSSAP.receive(tr_BSSMAP_ClearRequest);
6509 f_perform_clear_no_lchan();
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006510 } else {
6511 f_perform_clear(exp_rr_rel_tmpl := exp_rr_rel_tmpl);
6512 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006513 setverdict(pass);
6514}
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006515function 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 +01006516 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006517
6518 f_init(1, true);
6519 f_sleep(1.0);
6520
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006521 f_vty_encryption_a5(vty_a5_cfg);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006522 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006523
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006524 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6525 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006526
6527 vc_conn := f_start_handler(refers(f_tc_ho_into_this_bsc), pars);
6528 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006529
6530 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006531 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006532 if (pars.expect_ho_fail) {
6533 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6534 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:failed");
Oliver Smith7a8594a2023-02-13 14:30:49 +01006535 } else if (pars.expect_ho_fail_lchan_est) {
6536 f_ctrs_bsc_and_bts_add(0, "handover:error");
6537 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006538 } else {
6539 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6540 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed");
6541 }
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006542 f_ctrs_bsc_and_bts_verify();
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006543
6544 f_vty_encryption_a5_reset();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006545}
6546
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006547testcase TC_ho_into_this_bsc() runs on test_CT {
6548 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6549 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02006550 f_shutdown_helper(ho := true);
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006551}
6552
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006553function f_tc_ho_into_this_bsc_a5(TestHdlrEncrParams encr, charstring vty_a5_cfg := VTY_A5_DEFAULT,
6554 boolean expect_fail := false) runs on test_CT {
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006555 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006556 pars.encr := encr;
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006557 pars.expect_ho_fail := expect_fail;
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006558 f_tc_ho_into_this_bsc_main(pars, vty_a5_cfg);
Oliver Smith39f53072022-10-27 14:44:04 +02006559 f_shutdown_helper(ho := true);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006560}
6561
6562testcase TC_ho_into_this_bsc_a5_0() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006563 f_tc_ho_into_this_bsc_a5(f_encr_params('01'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006564}
6565
6566testcase TC_ho_into_this_bsc_a5_1() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006567 f_tc_ho_into_this_bsc_a5(f_encr_params('02'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006568}
6569
6570testcase TC_ho_into_this_bsc_a5_3() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006571 f_tc_ho_into_this_bsc_a5(f_encr_params('08'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006572}
6573
6574testcase TC_ho_into_this_bsc_a5_4() runs on test_CT {
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006575 f_tc_ho_into_this_bsc_a5(f_encr_params('10'O, kc128 := true), "3 4");
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006576}
6577
Neels Hofmeyr1951be22022-02-16 16:21:07 +01006578/* Report: in inter-BSC incoming handover, when the MSC omits the Chosen Encryption Algorithm IE in the Handover Request
6579 * message, then osmo-bsc starts an unencrypted lchan even if A5/0 is not permitted.
6580 *
6581 * This test verifies that the Encryption Information is present in the Channel Activation when the Chosen Enc Alg is
6582 * omitted.
6583 *
6584 * Related: SYS#5839
6585 */
6586testcase TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() runs on test_CT {
6587 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O, alg_chosen := omit));
6588}
6589
6590testcase TC_ho_into_this_bsc_a5_1_3() runs on test_CT {
6591 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O));
6592}
6593
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006594/* Send a permitted algo mask that does not intersect with osmo-bsc.cfg */
6595testcase TC_ho_into_this_bsc_a5_mismatch() runs on test_CT {
6596 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '18'O, alg_expect := '10'O), "0 1",
6597 expect_fail := true); // 0x18 = A5/3 and A5/4
6598}
6599
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006600testcase TC_ho_into_this_bsc_tla_v6() runs on test_CT {
6601 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6602 pars.host_aoip_tla := "::6";
6603 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02006604 f_shutdown_helper(ho := true);
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006605}
6606
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006607/* Similar to TC_ho_into_this_bsc, but when in SRVCC, HO Req contains "Old BSS
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006608 to New BSS Information" IE with "Last Used E-UTRAN PLMN Id", which, when the
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006609 channel is later released (RR CHannel Release), should trigger inclusion of
6610 IE "Cell Selection Indicator after Release of all TCH and SDCCH" with E-UTRAN
6611 neighbors. */
6612testcase TC_srvcc_eutran_to_geran() runs on test_CT {
6613 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6614 pars.last_used_eutran_plmn := '323454'O;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006615 pars.exp_fast_return := true;
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006616 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006617
6618 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6619 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6620 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006621 f_shutdown_helper(ho := true);
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006622}
6623
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006624/* Same as TC_srvcc_eutran_to_geran, but enables ciphering on the target channel. */
6625testcase TC_srvcc_eutran_to_geran_a5_3() runs on test_CT {
6626 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6627 pars.encr := f_encr_params('08'O); /* only A5/3 */
6628 pars.last_used_eutran_plmn := '323454'O;
6629 pars.exp_fast_return := true;
6630 f_tc_ho_into_this_bsc_main(pars);
6631
6632 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6633 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6634 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006635 f_shutdown_helper(ho := true);
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006636}
6637
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006638/* Same as TC_srvcc_eutran_to_geran, but test explicitly forbiding fast return
6639 on the BTS. As a result, RR Release shouldn't contain the EUTRAN neighbor
6640 list when the channel is released. */
6641testcase TC_srvcc_eutran_to_geran_forbid_fast_return() runs on test_CT {
6642 f_init_vty();
6643 f_vty_allow_srvcc_fast_return(true, 0)
6644
6645 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6646 pars.last_used_eutran_plmn := '323454'O;
6647 pars.exp_fast_return := false;
6648 f_tc_ho_into_this_bsc_main(pars);
6649 f_vty_allow_srvcc_fast_return(false, 0);
6650 f_shutdown_helper();
6651}
6652
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01006653/* Same as TC_srvcc_eutran_to_geran, but using SAI as serving Cell Identifier. SYS#5838 */
6654testcase TC_srvcc_eutran_to_geran_src_sai() runs on test_CT {
6655 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6656 pars.last_used_eutran_plmn := '323454'O;
6657 pars.cell_id_source := valueof(ts_CellID_SAI('123456'O, 300, 444));
6658 f_tc_ho_into_this_bsc_main(pars);
6659
6660 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6661 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6662 f_ctrs_bsc_and_bts_verify();
6663 f_shutdown_helper();
6664}
6665
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006666private function f_tc_srvcc_eutran_to_geran_ho_out(charstring id) runs on MSC_ConnHdlr {
6667 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs;
6668 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
6669 f_ho_into_this_bsc(id, oldToNewBSSIEs);
6670 f_ho_out_of_this_bsc(oldToNewBSSIEs);
6671 setverdict(pass);
6672}
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006673
6674private function f_tc_srvcc_eutran_to_geran_ho_out_main(boolean disable_fast_return)
6675 runs on test_CT {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006676 var MSC_ConnHdlr vc_conn;
6677 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6678
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006679 f_init_vty();
6680 f_bts_0_cfg(BSCVTY,
6681 {"neighbor-list mode automatic",
6682 "handover 1",
6683 "handover algorithm 2",
6684 "handover2 window rxlev averaging 1",
6685 "no neighbors",
6686 "neighbor lac 99 arfcn 123 bsic any"});
6687 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6688
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006689 f_init(1, true);
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006690 if (disable_fast_return) {
6691 f_vty_allow_srvcc_fast_return(true, 0);
6692 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006693 f_sleep(1.0);
6694
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006695 f_ctrs_bsc_and_bts_handover_init();
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006696
6697 pars.last_used_eutran_plmn := '323454'O;
6698 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6699 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
6700
6701 vc_conn := f_start_handler(refers(f_tc_srvcc_eutran_to_geran_ho_out), pars);
6702 vc_conn.done;
6703
6704 f_ctrs_bsc_and_bts_add(0, "handover:attempted", 2);
6705 f_ctrs_bsc_and_bts_add(0, "handover:completed", 2);
6706 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted", 1);
6707 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed", 1);
6708 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted", 1);
6709 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed", 1);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006710
6711 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted", 1);
6712 f_ctrs_bsc_and_bts_add(0, "srvcc:completed", 1);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006713 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006714
6715 if (disable_fast_return) {
6716 f_vty_allow_srvcc_fast_return(false, 0);
6717 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006718 f_shutdown_helper();
6719}
6720
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006721/* First, HO into BSC from EUTRAN (SRVCC): HO Request contains "Old BSS to New
6722 BSS Information" IE with "Last Used E-UTRAN PLMN Id".
6723 Second, HO to another BSC: HO Required contains "Old BSS to New BSS Information"
6724 IE with "Last Used E-UTRAN PLMN Id" from first step. */
6725testcase TC_srvcc_eutran_to_geran_ho_out() runs on test_CT {
6726 f_tc_srvcc_eutran_to_geran_ho_out_main(false);
6727}
6728/* Validate subsequent intra-GSM-HO works the same (with OldBSSToNewBSSInfo IE)
6729 * independently of fast-reture allowed/forbidden in local BTS */
6730testcase TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() runs on test_CT {
6731 f_tc_srvcc_eutran_to_geran_ho_out_main(true);
6732}
6733
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006734private function f_tc_ho_in_fail_msc_clears(charstring id) runs on MSC_ConnHdlr {
6735 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6736 f_rslem_register(0, new_chan_nr);
6737 g_chan_nr := new_chan_nr;
6738 f_sleep(1.0);
6739
6740 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6741 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6742 activate(as_Media());
6743
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006744 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006745 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006746 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006747
6748 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6749
6750 var PDU_BSSAP rx_bssap;
6751 var octetstring ho_command_str;
6752
6753 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6754
6755 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6756 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6757 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6758 log("L3 Info in HO Request Ack is ", ho_command);
6759
6760 var GsmArfcn arfcn;
6761 var RslChannelNr actual_new_chan_nr;
6762 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6763 actual_new_chan_nr, arfcn);
6764
6765 if (actual_new_chan_nr != new_chan_nr) {
6766 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6767 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6768 setverdict(fail);
6769 return;
6770 }
6771 log("Handover Command chan_nr is", actual_new_chan_nr);
6772
Neels Hofmeyr61ca08d2019-05-06 23:52:22 +02006773 /* For deterministic test results, give some time for the MGW endpoint to be configured */
6774 f_sleep(1.0);
6775
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006776 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6777 * tells the MS to handover to the new lchan. In this case, the MS
6778 * reports a Handover Failure to the old BSS, which forwards a BSSMAP
6779 * Handover Failure to the MSC. The procedure according to 3GPP TS
6780 * 48.008 3.1.5.3.2 "Handover Failure" is then that the MSC sends a
6781 * BSSMAP Clear Command: */
6782
6783 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6784 var BssmapCause cause := enum2int(cause_val);
6785 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6786
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006787 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006788 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006789 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006790
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006791 setverdict(pass);
6792 f_sleep(1.0);
6793
6794 setverdict(pass);
6795}
6796testcase TC_ho_in_fail_msc_clears() runs on test_CT {
6797 var MSC_ConnHdlr vc_conn;
6798 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6799
6800 f_init(1, true);
6801 f_sleep(1.0);
6802
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006803 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006804
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006805 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6806 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006807
6808 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears), pars);
6809 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006810
6811 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6812 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6813 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6814 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6815 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006816 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006817}
6818
6819private function f_tc_ho_in_fail_msc_clears_after_ho_detect(charstring id) runs on MSC_ConnHdlr {
6820 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6821 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6822 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6823 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6824 * before we get started. */
6825 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6826 f_rslem_register(0, new_chan_nr);
6827 g_chan_nr := new_chan_nr;
6828 f_sleep(1.0);
6829
6830 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6831 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6832 activate(as_Media());
6833
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006834 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006835 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006836 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006837
6838 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6839
6840 var PDU_BSSAP rx_bssap;
6841 var octetstring ho_command_str;
6842
6843 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6844
6845 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6846 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6847 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6848 log("L3 Info in HO Request Ack is ", ho_command);
6849
6850 var GsmArfcn arfcn;
6851 var RslChannelNr actual_new_chan_nr;
6852 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6853 actual_new_chan_nr, arfcn);
6854
6855 if (actual_new_chan_nr != new_chan_nr) {
6856 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6857 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6858 setverdict(fail);
6859 return;
6860 }
6861 log("Handover Command chan_nr is", actual_new_chan_nr);
6862
6863 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6864 * tells the MS to handover to the new lchan. Here comes the new MS on
6865 * the new lchan with a Handover RACH: */
6866
6867 /* send handover detect */
6868
6869 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6870
6871 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6872
6873 /* The MSC chooses to clear the connection now, maybe we got the
6874 * Handover RACH on the new cell but the MS still signaled Handover
6875 * Failure to the old BSS? */
6876
6877 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6878 var BssmapCause cause := enum2int(cause_val);
6879 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6880
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006881 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006882 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006883 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006884
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006885 f_sleep(1.0);
6886}
6887testcase TC_ho_in_fail_msc_clears_after_ho_detect() runs on test_CT {
6888 var MSC_ConnHdlr vc_conn;
6889 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6890
6891 f_init(1, true);
6892 f_sleep(1.0);
6893
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006894 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006895
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006896 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6897 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006898
6899 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears_after_ho_detect), pars);
6900 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006901
6902 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6903 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6904 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6905 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6906 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006907 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006908}
6909
6910/* The new BSS's lchan times out before the MSC decides that handover failed. */
6911private function f_tc_ho_in_fail_no_detect(charstring id) runs on MSC_ConnHdlr {
6912 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6913 f_rslem_register(0, new_chan_nr);
6914 g_chan_nr := new_chan_nr;
6915 f_sleep(1.0);
6916
6917 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6918 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Oliver Smith735b47c2023-02-15 16:03:54 +01006919 activate(as_Media());
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006920
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006921 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006922 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006923 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006924
6925 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6926
6927 var PDU_BSSAP rx_bssap;
6928 var octetstring ho_command_str;
6929
6930 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6931
6932 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6933 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6934 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6935 log("L3 Info in HO Request Ack is ", ho_command);
6936
6937 var GsmArfcn arfcn;
6938 var RslChannelNr actual_new_chan_nr;
6939 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6940 actual_new_chan_nr, arfcn);
6941
6942 if (actual_new_chan_nr != new_chan_nr) {
6943 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6944 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6945 setverdict(fail);
6946 return;
6947 }
6948 log("Handover Command chan_nr is", actual_new_chan_nr);
6949
6950 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6951 * tells the MS to handover to the new lchan. But the MS never shows up
6952 * on the new lchan. */
6953
6954 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6955
6956 /* Did osmo-bsc also send a Clear Request? */
6957 timer T := 0.5;
6958 T.start;
6959 alt {
6960 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
6961 [] T.timeout { }
6962 }
6963
6964 /* MSC plays along with a Clear Command (no matter whether osmo-bsc
6965 * asked for it, this is a Handover Failure after all). */
6966
6967 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6968 var BssmapCause cause := enum2int(cause_val);
6969 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6970
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006971 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006972 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006973 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006974
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006975 f_sleep(1.0);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006976}
6977testcase TC_ho_in_fail_no_detect() runs on test_CT {
6978 var MSC_ConnHdlr vc_conn;
6979 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6980
Oliver Smithd49f46d2023-03-08 12:23:13 +01006981 pars.fail_on_dlcx := false;
6982
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006983 f_init(1, true);
6984 f_sleep(1.0);
6985
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006986 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006987
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006988 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6989 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006990
6991 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect), pars);
6992 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006993
6994 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6995 f_ctrs_bsc_and_bts_add(0, "handover:error");
6996 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6997 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
6998 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006999 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007000}
7001
7002/* Same as f_tc_ho_in_fail_no_detect, but MSC fails to send a Clear Command */
7003private function f_tc_ho_in_fail_no_detect2(charstring id) runs on MSC_ConnHdlr {
7004 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
7005 f_rslem_register(0, new_chan_nr);
7006 g_chan_nr := new_chan_nr;
7007 f_sleep(1.0);
7008
7009 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
7010 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Oliver Smith735b47c2023-02-15 16:03:54 +01007011 activate(as_Media());
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007012
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007013 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007014 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02007015 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007016
7017 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
7018
7019 var PDU_BSSAP rx_bssap;
7020 var octetstring ho_command_str;
7021
7022 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
7023
7024 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
7025 log("Received L3 Info in HO Request Ack: ", ho_command_str);
7026 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
7027 log("L3 Info in HO Request Ack is ", ho_command);
7028
7029 var GsmArfcn arfcn;
7030 var RslChannelNr actual_new_chan_nr;
7031 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
7032 actual_new_chan_nr, arfcn);
7033
7034 if (actual_new_chan_nr != new_chan_nr) {
7035 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
7036 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
7037 setverdict(fail);
7038 return;
7039 }
7040 log("Handover Command chan_nr is", actual_new_chan_nr);
7041
7042 /* Now the MSC forwards the RR Handover Command to the other BSC, which
7043 * tells the MS to handover to the new lchan. But the MS never shows up
7044 * on the new lchan. */
7045
7046 BSSAP.receive(tr_BSSMAP_HandoverFailure);
7047
7048 /* MSC plays dumb and sends no Clear Command */
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007049 var PDU_BSSAP rx_clear_request;
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02007050
7051 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request {
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007052 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
7053 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
7054 };
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02007055 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007056 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007057 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007058
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007059 f_sleep(1.0);
7060}
7061testcase TC_ho_in_fail_no_detect2() runs on test_CT {
7062 var MSC_ConnHdlr vc_conn;
7063 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7064
Oliver Smith735b47c2023-02-15 16:03:54 +01007065 pars.fail_on_dlcx := false;
7066
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007067 f_init(1, true);
7068 f_sleep(1.0);
7069
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007070 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007071
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007072 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
7073 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007074
7075 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect2), pars);
7076 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007077
7078 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7079 f_ctrs_bsc_and_bts_add(0, "handover:error");
7080 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
7081 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
7082 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007083 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007084}
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01007085
Oliver Smith7a8594a2023-02-13 14:30:49 +01007086testcase TC_ho_in_fail_mgw_mdcx_timeout() runs on test_CT {
7087 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7088
7089 pars.ignore_mgw_mdcx := true;
7090 pars.expect_ho_fail_lchan_est := true;
7091
7092 f_tc_ho_into_this_bsc_main(pars);
7093 f_shutdown_helper(ho := true);
7094}
7095
Oliver Smith4eed06f2023-02-15 15:43:19 +01007096testcase TC_ho_in_fail_ipa_crcx_timeout() runs on test_CT {
7097 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7098
7099 pars.ignore_ipa_media := true;
7100 pars.expect_ho_fail_lchan_est := true;
7101 pars.fail_on_dlcx := false;
7102
7103 f_tc_ho_into_this_bsc_main(pars);
7104 f_shutdown_helper(ho := true);
7105}
7106
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01007107/* An incoming inter-BSC HO can either issue the Handover Request message attached to the initial SCCP N-Connect (as in
7108 * the other tests we have so far), or the first CR can be "empty" with the BSSAP request following later. Test the
7109 * empty N-Connect case. */
7110testcase TC_ho_into_this_bsc_sccp_cr_without_bssap() runs on test_CT {
7111 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7112 pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr := false;
7113 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02007114 f_shutdown_helper(ho := true);
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01007115}
7116
Neels Hofmeyr91401012019-07-11 00:42:35 +02007117type record of charstring Commands;
7118
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007119private function f_bts_0_cfg(TELNETasp_PT pt, Commands cmds := {})
Neels Hofmeyr91401012019-07-11 00:42:35 +02007120{
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007121 f_vty_enter_cfg_bts(pt, 0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007122 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007123 f_vty_transceive(pt, cmds[i]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007124 }
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007125 f_vty_transceive(pt, "end");
Neels Hofmeyr91401012019-07-11 00:42:35 +02007126}
7127
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01007128private function f_cs7_inst_0_cfg(TELNETasp_PT pt, Commands cmds := {})
7129{
7130 f_vty_enter_cfg_cs7_inst(pt, 0);
7131 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
7132 f_vty_transceive(pt, cmds[i]);
7133 }
7134 f_vty_transceive(pt, "end");
7135}
7136
Neels Hofmeyr91401012019-07-11 00:42:35 +02007137private function f_probe_for_handover(charstring log_label,
7138 charstring log_descr,
7139 charstring handover_vty_cmd,
7140 boolean expect_handover,
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007141 boolean is_inter_bsc_handover := false,
7142 template uint3_t expect_target_tsc := ?)
Neels Hofmeyr91401012019-07-11 00:42:35 +02007143runs on MSC_ConnHdlr
7144{
Neels Hofmeyrb3fc8982020-05-11 00:16:42 +02007145 /* We're going to thwart any and all handover attempts, just be ready to handle (and ignore) handover target
7146 * lchans to be established on bts 1 or bts 2. */
7147 f_rslem_suspend(RSL1_PROC);
7148 f_rslem_suspend(RSL2_PROC);
7149
Neels Hofmeyr91401012019-07-11 00:42:35 +02007150 var RSL_Message rsl;
7151
7152 var charstring log_msg := " (expecting handover)"
7153 if (not expect_handover) {
7154 log_msg := " (expecting NO handover)";
7155 }
7156 log("f_probe_for_handover starting: " & log_label & ": " & log_descr & log_msg);
7157 f_vty_transceive(BSCVTY, handover_vty_cmd);
7158
Neels Hofmeyr91401012019-07-11 00:42:35 +02007159 timer T := 2.0;
7160 T.start;
7161
7162 alt {
7163 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
7164 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
7165 log("Rx L3 from net: ", l3);
7166 if (ischosen(l3.msgs.rrm.handoverCommand)) {
7167 var RslChannelNr new_chan_nr;
7168 var GsmArfcn arfcn;
7169 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
7170 new_chan_nr, arfcn);
7171 log("Handover to new chan ", new_chan_nr, " on ARFCN ", arfcn);
7172 log(l3.msgs.rrm.handoverCommand);
7173
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007174 /* Verify correct TSC in handoverCommand */
7175 var uint3_t got_tsc := rr_chan_desc_tsc(l3.msgs.rrm.handoverCommand.channelDescription2);
7176 if (not match(got_tsc, expect_target_tsc)) {
7177 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
7178 expect_target_tsc, " got ", got_tsc);
7179 mtc.stop;
7180 } else {
7181 log("handoverCommand: verified TSC = ", got_tsc, " (matches ",
7182 expect_target_tsc, ")");
7183 }
7184
Neels Hofmeyr91401012019-07-11 00:42:35 +02007185 /* Need to register for new lchan on new BTS -- it's either bts 1 or bts 2. It doesn't really
7186 * matter on which BTS it really is, we're not going to follow through an entire handover
7187 * anyway. */
7188 f_rslem_register(0, new_chan_nr, RSL1_PROC);
7189 f_rslem_resume(RSL1_PROC);
7190 f_rslem_register(0, new_chan_nr, RSL2_PROC);
7191 f_rslem_resume(RSL2_PROC);
7192
7193 if (expect_handover and not is_inter_bsc_handover) {
7194 setverdict(pass);
7195 log("f_probe_for_handover(" & log_label & "): Got RSL Handover Command as expected.");
7196 } else {
7197 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got RSL Handover Command. "
7198 & log_label & ": " & log_descr);
7199 }
7200
7201 log("f_probe_for_handover(" & log_label & "): Ending the test: Handover Failure stops the procedure.");
7202 /* osmo-bsc has triggered Handover. That's all we need to know for this test, reply with
7203 * Handover Failure. */
7204 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
7205
7206 /* target BTS is told to release lchan again; don't care which BTS nor what messages. */
7207 f_sleep(0.5);
7208 RSL1.clear;
7209 RSL2.clear;
7210 log("f_probe_for_handover(" & log_label & "): done (got RSL Handover Command)");
7211 break;
7212 } else {
7213 repeat;
7214 }
7215 }
7216 [] BSSAP.receive(tr_BSSMAP_HandoverRequired) {
7217 if (expect_handover and is_inter_bsc_handover) {
7218 setverdict(pass);
7219 log("f_probe_for_handover(" & log_label & "): Got BSSMAP Handover Required as expected.");
7220 } else {
7221 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got BSSMAP Handover Required. "
7222 & log_label & ": " & log_descr);
7223 }
7224
7225 log("f_probe_for_handover(" & log_label & "): done (got BSSMAP Handover Required)");
7226
7227 /* Note: f_tc_ho_neighbor_config_start() sets T7, the timeout for BSSMAP Handover Required, to
7228 * 1 second. There is no legal way to quickly abort a handover after a BSSMAP Handover Required,
7229 * setting a short timeout and waiting is the only way. */
7230 log("f_probe_for_handover(" & log_label & "): waiting for inter-BSC HO to time out...");
7231 f_sleep(1.5);
7232 log("f_probe_for_handover(" & log_label & "): ...done");
7233
7234 break;
7235 }
7236 [] T.timeout {
7237 if (expect_handover) {
7238 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected Handover, but got none. "
7239 & log_label & ": " & log_descr);
7240 } else {
7241 setverdict(pass);
7242 log("f_probe_for_handover(" & log_label & "): Got no Handover, as expected.");
7243 }
7244 log("f_probe_for_handover(" & log_label & "): done (got no Handover)");
7245 break;
7246 }
7247 }
7248
7249 f_rslem_resume(RSL1_PROC);
7250 f_rslem_resume(RSL2_PROC);
7251 f_sleep(3.0);
7252 RSL.clear;
7253
7254 log("f_probe_for_handover(" & log_label & "): done clearing");
7255}
7256
7257/* Test the effect of various neighbor configuration scenarios:
7258 *
7259 * To avoid complexity, block off any actual handover operation, and always remain on the lchan at bts 0.
7260 * Reconfigure the neighbors for bts 0, trigger a Handover, and probe whether osmo-bsc does or doesn't start HO.
7261 */
7262private function f_tc_ho_neighbor_config_start() runs on MSC_ConnHdlr {
7263 g_pars := f_gen_test_hdlr_pars();
7264 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
7265 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007266
7267 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
7268 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
7269
7270 /* Establish lchan at bts 0 */
7271 f_establish_fully(ass_cmd, exp_compl);
7272
7273 /* Shorten the inter-BSC Handover timeout, to not wait so long for inter-BSC Handovers */
7274 f_vty_enter_cfg_network(BSCVTY);
7275 f_vty_transceive(BSCVTY, "timer T7 1");
7276 f_vty_transceive(BSCVTY, "end");
7277}
7278
7279private function f_tc_ho_neighbor_config_1(charstring id) runs on MSC_ConnHdlr {
7280 f_tc_ho_neighbor_config_start();
7281
7282 /*
7283 * bts 0 ARFCN 871 BSIC 10
7284 * bts 1 ARFCN 871 BSIC 11
7285 * bts 2 ARFCN 871 BSIC 12
7286 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7287 */
7288
7289 log("f_tc_ho_neighbor_config: 1. No 'neighbor' config");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007290 f_bts_0_cfg(BSCVTY, {"no neighbors"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007291 f_probe_for_handover("1.a", "HO to bts 1 works, implicitly listed as neighbor (legacy behavior when none are configured)",
7292 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007293 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007294
7295 f_probe_for_handover("1.b", "HO to unknown cell does not start",
7296 "handover any to arfcn 13 bsic 39",
7297 false);
7298
7299 f_probe_for_handover("1.c", "HO to 871-12 is ambiguous = error",
7300 "handover any to arfcn 871 bsic 12",
7301 false);
7302
7303 f_probe_for_handover("1.d", "HO to 871-11 still works (verify that this test properly cleans up)",
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 Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007306
7307 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007308}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007309testcase TC_ho_neighbor_config_1() runs on test_CT {
7310 var MSC_ConnHdlr vc_conn;
7311 f_init(3, true, guard_timeout := 60.0);
7312 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007313 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007314 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_1));
7315 vc_conn.done;
7316
7317 /* f_tc_ho_neighbor_config_start() */
7318 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7319 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7320
7321 /* 1.a */
7322 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7323 * handover quickly by sending a Handover Failure message. */
7324 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7325 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7326 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7327 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007328 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7329 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007330
7331 /* 1.b */
7332 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7333 f_ctrs_bsc_and_bts_add(0, "handover:error");
7334
7335 /* 1.c */
7336 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7337 f_ctrs_bsc_and_bts_add(0, "handover:error");
7338
7339 /* 1.d */
7340 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7341 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7342 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7343 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007344 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7345 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007346
7347 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007348 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007349}
7350
Neels Hofmeyr91401012019-07-11 00:42:35 +02007351private function f_tc_ho_neighbor_config_2(charstring id) runs on MSC_ConnHdlr {
7352 f_tc_ho_neighbor_config_start();
7353
7354 /*
7355 * bts 0 ARFCN 871 BSIC 10
7356 * bts 1 ARFCN 871 BSIC 11
7357 * bts 2 ARFCN 871 BSIC 12
7358 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7359 */
7360
7361 log("f_tc_ho_neighbor_config: 2. explicit local neighbor: 'neighbor bts 1'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007362 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007363 f_sleep(0.5);
7364
7365 f_probe_for_handover("2.a", "HO to bts 1 works, explicitly listed as neighbor",
7366 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007367 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007368
7369 f_probe_for_handover("2.b", "HO to bts 2 doesn't work, not listed as neighbor",
7370 "handover any to arfcn 871 bsic 12",
7371 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007372 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007373}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007374testcase TC_ho_neighbor_config_2() runs on test_CT {
7375 var MSC_ConnHdlr vc_conn;
7376 f_init(3, true, guard_timeout := 50.0);
7377 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007378 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007379 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_2));
7380 vc_conn.done;
7381
7382 /* f_tc_ho_neighbor_config_start() */
7383 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7384 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7385
7386 /* 2.a */
7387 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7388 * handover quickly by sending a Handover Failure message. */
7389 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7390 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7391 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7392 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007393 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7394 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007395
7396 /* 2.b */
7397 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7398 f_ctrs_bsc_and_bts_add(0, "handover:error");
7399
7400 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007401 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007402}
7403
Neels Hofmeyr91401012019-07-11 00:42:35 +02007404private function f_tc_ho_neighbor_config_3(charstring id) runs on MSC_ConnHdlr {
7405 f_tc_ho_neighbor_config_start();
7406
7407 /*
7408 * bts 0 ARFCN 871 BSIC 10
7409 * bts 1 ARFCN 871 BSIC 11
7410 * bts 2 ARFCN 871 BSIC 12
7411 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7412 */
7413
7414 log("f_tc_ho_neighbor_config: 3. explicit local neighbor: 'neighbor bts 2'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007415 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007416 f_sleep(0.5);
7417
7418 f_probe_for_handover("3.a", "HO to bts 1 doesn't work, not listed as neighbor",
7419 "handover any to arfcn 871 bsic 11",
7420 false);
7421 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",
7422 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007423 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007424 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007425}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007426testcase TC_ho_neighbor_config_3() runs on test_CT {
7427 var MSC_ConnHdlr vc_conn;
7428 f_init(3, true, guard_timeout := 50.0);
7429 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007430 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007431 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_3));
7432 vc_conn.done;
7433
7434 /* f_tc_ho_neighbor_config_start() */
7435 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7436 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7437
7438 /* 3.a */
7439 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7440 f_ctrs_bsc_and_bts_add(0, "handover:error");
7441
7442 /* 3.b */
7443 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7444 * handover quickly by sending a Handover Failure message. */
7445 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7446 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7447 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7448 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007449 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7450 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007451
7452 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007453 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007454}
7455
Neels Hofmeyr91401012019-07-11 00:42:35 +02007456private function f_tc_ho_neighbor_config_4(charstring id) runs on MSC_ConnHdlr {
7457 f_tc_ho_neighbor_config_start();
7458
7459 /*
7460 * bts 0 ARFCN 871 BSIC 10
7461 * bts 1 ARFCN 871 BSIC 11
7462 * bts 2 ARFCN 871 BSIC 12
7463 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7464 */
7465
7466 log("f_tc_ho_neighbor_config: 4. explicit remote neighbor: 'neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007467 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007468 f_sleep(0.5);
7469
7470 f_probe_for_handover("4.a", "HO to bts 1 doesn't work, not listed as neighbor",
7471 "handover any to arfcn 871 bsic 11",
7472 false);
7473 f_probe_for_handover("4.b", "HO to bts 2 doesn't work, not listed as neighbor",
7474 "handover any to arfcn 871 bsic 12",
7475 false);
7476 f_probe_for_handover("4.c", "HO to 123-45 triggers inter-BSC HO",
7477 "handover any to arfcn 123 bsic 45",
7478 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007479 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007480}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007481testcase TC_ho_neighbor_config_4() runs on test_CT {
7482 var MSC_ConnHdlr vc_conn;
7483 f_init(3, true, guard_timeout := 50.0);
7484 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007485 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007486 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_4));
7487 vc_conn.done;
7488
7489 /* f_tc_ho_neighbor_config_start() */
7490 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7491 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7492
7493 /* 4.a */
7494 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7495 f_ctrs_bsc_and_bts_add(0, "handover:error");
7496
7497 /* 4.b */
7498 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7499 f_ctrs_bsc_and_bts_add(0, "handover:error");
7500
7501 /* 4.c */
7502 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7503 * handover quickly by timing out after the Handover Required message */
7504 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7505 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7506 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7507 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7508
7509 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007510 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007511}
7512
Neels Hofmeyr91401012019-07-11 00:42:35 +02007513private function f_tc_ho_neighbor_config_5(charstring id) runs on MSC_ConnHdlr {
7514 f_tc_ho_neighbor_config_start();
7515
7516 /*
7517 * bts 0 ARFCN 871 BSIC 10
7518 * bts 1 ARFCN 871 BSIC 11
7519 * bts 2 ARFCN 871 BSIC 12
7520 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7521 */
7522
7523 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 +02007524 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007525 f_sleep(0.5);
7526
7527 f_probe_for_handover("5.a", "HO to 871-12 triggers inter-BSC HO (ignoring local cells with same ARFCN+BSIC)",
7528 "handover any to arfcn 871 bsic 12",
7529 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007530 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007531}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007532testcase TC_ho_neighbor_config_5() runs on test_CT {
7533 var MSC_ConnHdlr vc_conn;
7534 f_init(3, true);
7535 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007536 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007537 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_5));
7538 vc_conn.done;
7539
7540 /* f_tc_ho_neighbor_config_start() */
7541 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7542 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7543
7544 /* 5 */
7545 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7546 * handover quickly by timing out after the Handover Required message */
7547 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7548 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7549 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7550 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7551
7552 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007553 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007554}
7555
Neels Hofmeyr91401012019-07-11 00:42:35 +02007556private function f_tc_ho_neighbor_config_6(charstring id) runs on MSC_ConnHdlr {
7557 f_tc_ho_neighbor_config_start();
7558
7559 /*
7560 * bts 0 ARFCN 871 BSIC 10
7561 * bts 1 ARFCN 871 BSIC 11
7562 * bts 2 ARFCN 871 BSIC 12
7563 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7564 */
7565
7566 log("f_tc_ho_neighbor_config: 6. config error: explicit local and remote neighbors with ambiguous ARFCN+BSIC:"
7567 & " 'neighbor bts 2; neighbor lac 99 arfcn 871 bsic 12'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007568 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007569 f_sleep(0.5);
7570
7571 f_probe_for_handover("6.a", "HO to 871-12 is ambiguous = error",
7572 "handover any to arfcn 871 bsic 12",
7573 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007574 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007575}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007576testcase TC_ho_neighbor_config_6() runs on test_CT {
7577 var MSC_ConnHdlr vc_conn;
7578 f_init(3, true);
7579 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007580 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007581 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_6));
7582 vc_conn.done;
7583
7584 /* f_tc_ho_neighbor_config_start() */
7585 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7586 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7587
7588 /* 6.a */
7589 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7590 * handover quickly by timing out after the Handover Required message */
7591 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7592 f_ctrs_bsc_and_bts_add(0, "handover:error");
7593
7594 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007595 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007596}
7597
Neels Hofmeyr91401012019-07-11 00:42:35 +02007598private function f_tc_ho_neighbor_config_7(charstring id) runs on MSC_ConnHdlr {
7599 f_tc_ho_neighbor_config_start();
7600
7601 /*
7602 * bts 0 ARFCN 871 BSIC 10
7603 * bts 1 ARFCN 871 BSIC 11
7604 * bts 2 ARFCN 871 BSIC 12
7605 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7606 */
7607
7608 log("f_tc_ho_neighbor_config: 7. explicit local and remote neighbors:"
7609 & " 'neighbor bts 2; neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007610 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007611 f_sleep(0.5);
7612
7613 f_probe_for_handover("7.a", "HO to 871-12 does HO to bts 2",
7614 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007615 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007616 f_probe_for_handover("7.b", "HO to 123-45 triggers inter-BSC HO",
7617 "handover any to arfcn 123 bsic 45",
7618 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007619 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007620}
Neels Hofmeyr91401012019-07-11 00:42:35 +02007621testcase TC_ho_neighbor_config_7() runs on test_CT {
7622 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf2b88032020-06-16 00:35:04 +02007623 f_init(3, true, guard_timeout := 50.0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007624 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007625 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007626 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_7));
7627 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007628
7629 /* f_tc_ho_neighbor_config_start() */
7630 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7631 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7632
7633 /* 7.a */
7634 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7635 * handover quickly by sending a Handover Failure message. */
7636 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7637 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7638 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7639 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007640 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7641 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007642
7643 /* 7.b */
7644 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7645 * handover quickly by timing out after the Handover Required message */
7646 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7647 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7648 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7649 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7650
7651 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007652 f_shutdown_helper(ho := true);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007653}
7654
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007655/* OS#3041: Open and close N connections in a normal fashion, and expect no
7656 * BSSMAP Reset just because of that. */
7657testcase TC_bssap_rlsd_does_not_cause_bssmap_reset() runs on test_CT {
7658 var default d;
7659 var integer i;
7660 var DchanTuple dt;
7661
7662 f_init();
7663
7664 /* Wait for initial BSSMAP Reset to pass */
7665 f_sleep(4.0);
7666
7667 d := activate(no_bssmap_reset());
7668
7669 /* Setup up a number of connections and RLSD them again from the MSC
7670 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7671 * Let's do it some more times for good measure. */
Harald Weltec3260d92018-06-11 17:48:16 +02007672 for (i := 0; i < 4; i := i+1) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007673 /* Since we're doing a lot of runs, give each one a fresh
7674 * T_guard from the top. */
7675 T_guard.start;
7676
7677 /* Setup a BSSAP connection and clear it right away. This is
7678 * the MSC telling the BSC about a planned release, it's not an
7679 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007680 dt := f_est_dchan(int2oct(i,1), 23+i, gen_l3_valid_payload());
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007681
7682 /* MSC disconnects (RLSD). */
7683 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
7684 }
7685
7686 /* In the buggy behavior, a timeout of 2 seconds happens between above
7687 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7688 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7689 f_sleep(4.0);
7690
7691 deactivate(d);
7692 f_shutdown_helper();
7693}
Harald Welte552620d2017-12-16 23:21:36 +01007694
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007695/* OS#3041: Open and close N connections in a normal fashion, and expect no
7696 * BSSMAP Reset just because of that. Invoke the release by a BSSMAP Clear from
7697 * the MSC. */
7698testcase TC_bssmap_clear_does_not_cause_bssmap_reset() runs on test_CT {
7699 var default d;
7700 var integer i;
7701 var DchanTuple dt;
7702 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007703 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_CALL_CONTROL;
7704 var BssmapCause cause := enum2int(cause_val);
7705
7706 f_init();
7707
7708 /* Wait for initial BSSMAP Reset to pass */
7709 f_sleep(4.0);
7710
7711 d := activate(no_bssmap_reset());
7712
7713 /* Setup up a number of connections and RLSD them again from the MSC
7714 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7715 * Let's do it some more times for good measure. */
7716 for (i := 0; i < 8; i := i+1) {
7717 /* Since we're doing a lot of runs, give each one a fresh
7718 * T_guard from the top. */
7719 T_guard.start;
7720
7721 /* Setup a BSSAP connection and clear it right away. This is
7722 * the MSC telling the BSC about a planned release, it's not an
7723 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007724 dt := f_est_dchan(int2oct(i,1), 23+i, gen_l3_valid_payload());
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007725
7726 /* Instruct BSC to clear channel */
7727 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7728
7729 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007730 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007731 }
7732
7733 /* In the buggy behavior, a timeout of 2 seconds happens between above
7734 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7735 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7736 f_sleep(4.0);
7737
7738 deactivate(d);
7739 f_shutdown_helper();
7740}
7741
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007742/* OS#3041: Open and close N connections in a normal fashion, and expect no
7743 * BSSMAP Reset just because of that. Close connections from the MS side with a
7744 * Release Ind on RSL. */
7745testcase TC_ms_rel_ind_does_not_cause_bssmap_reset() runs on test_CT {
7746 var default d;
7747 var integer i;
7748 var DchanTuple dt;
7749 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007750 var integer j;
7751
7752 f_init();
7753
7754 /* Wait for initial BSSMAP Reset to pass */
7755 f_sleep(4.0);
7756
7757 d := activate(no_bssmap_reset());
7758
7759 /* Setup up a number of connections and RLSD them again from the MSC
7760 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7761 * Let's do it some more times for good measure. */
7762 for (i := 0; i < 8; i := i+1) {
7763 /* Since we're doing a lot of runs, give each one a fresh
7764 * T_guard from the top. */
7765 T_guard.start;
7766
7767 /* Setup a BSSAP connection and clear it right away. This is
7768 * the MSC telling the BSC about a planned release, it's not an
7769 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007770 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007771
7772 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007773 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007774
7775 /* expect Clear Request on MSC side */
7776 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
7777
7778 /* Instruct BSC to clear channel */
7779 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
7780 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7781
7782 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007783 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007784 }
7785
7786 /* In the buggy behavior, a timeout of 2 seconds happens between above
7787 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7788 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7789 f_sleep(4.0);
7790
7791 deactivate(d);
7792 f_shutdown_helper();
7793}
7794
Harald Welte94e0c342018-04-07 11:33:23 +02007795/***********************************************************************
7796 * IPA style dynamic PDCH
7797 ***********************************************************************/
7798
7799private function f_dyn_ipa_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7800 template (omit) RSL_Cause nack := omit)
7801runs on test_CT {
7802 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7803 var RSL_Message rsl_unused;
7804 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7805 f_vty_ts_action("pdch activate", bts_nr, trx_nr, ts_nr);
7806 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007807 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007808 if (istemplatekind(nack, "omit")) {
7809 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007810 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007811 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007812 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007813 }
7814}
7815
7816private function f_dyn_ipa_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7817 template (omit) RSL_Cause nack := omit)
7818runs on test_CT {
7819 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7820 var RSL_Message rsl_unused;
7821 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7822 f_vty_ts_action("pdch deactivate", bts_nr, trx_nr, ts_nr);
7823 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007824 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_DEACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007825 if (istemplatekind(nack, "omit")) {
7826 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007827 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007828 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007829 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007830 }
7831}
7832
7833private function f_ts_dyn_mode_get(integer bts_nr, integer trx_nr, integer ts_nr)
7834runs on test_CT return charstring {
7835 var charstring cmd, resp;
7836 cmd := "show timeslot "&int2str(bts_nr)&" "&int2str(trx_nr)&" "&int2str(ts_nr);
Stefan Sperlingcff13562018-11-13 15:24:06 +01007837 return f_vty_transceive_match_regexp_retry(BSCVTY, cmd, "*\((*)\)*", 0, 4, 1.0);
Harald Welte94e0c342018-04-07 11:33:23 +02007838}
7839
7840private function f_ts_dyn_mode_assert(integer bts_nr, integer trx_nr, integer ts_nr,
7841 template charstring exp)
7842runs on test_CT {
7843 var charstring mode := f_ts_dyn_mode_get(bts_nr, trx_nr, ts_nr);
7844 if (not match(mode, exp)) {
7845 setverdict(fail, "Unexpected TS Mode: ", mode);
Daniel Willmannafce8662018-07-06 23:11:32 +02007846 mtc.stop;
Harald Welte94e0c342018-04-07 11:33:23 +02007847 }
7848}
7849
7850private function f_ts_set_chcomb(integer bts_nr, integer trx_nr, integer ts_nr, charstring chcomb)
7851runs on test_CT {
7852 f_vty_enter_cfg_ts(BSCVTY, bts_nr, trx_nr, ts_nr);
7853 f_vty_transceive(BSCVTY, "phys_chan_config " & chcomb);
7854 f_vty_transceive(BSCVTY, "end");
7855}
7856
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007857
7858private function f_ts_reset_chcomb(integer bts_nr) runs on test_CT {
7859 var integer i;
7860 for (i := 0; i < 8; i := i + 1) {
7861 f_ts_set_chcomb(bts_nr, 0, i, phys_chan_config[i]);
7862 }
7863}
7864
Harald Welte94e0c342018-04-07 11:33:23 +02007865private const charstring TCHF_MODE := "TCH/F mode";
7866private const charstring TCHH_MODE := "TCH/H mode";
7867private const charstring PDCH_MODE := "PDCH mode";
7868private const charstring NONE_MODE := "NONE mode";
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007869private const charstring SDCCH8_MODE := "SDCCH8 mode";
Harald Welte94e0c342018-04-07 11:33:23 +02007870
7871/* Test IPA PDCH activation / deactivation triggered by VTY */
7872testcase TC_dyn_pdch_ipa_act_deact() runs on test_CT {
7873 var RSL_Message rsl_unused;
7874
7875 /* change Timeslot 6 before f_init() starts RSL */
7876 f_init_vty();
7877 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7878 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7879
7880 f_init(1, false);
7881 f_sleep(1.0);
7882
7883 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7884
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007885 log("TCH/F_PDCH pchan starts out in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007886 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7887 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007888 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
7889 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007890 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007891 log("TCH/F_PDCH pchan, PDCH ACT was ACKed, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007892 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7893
7894 /* De-activate it via VTY */
7895 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7896 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007897 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back 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
7900 /* re-activate it via VTY */
7901 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn);
7902 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007903 log("TCH/F_PDCH pchan, PDCH ACT via VTY, 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 /* and finally de-activate it again */
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
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007912 /* clean up config */
7913 f_ts_set_chcomb(0, 0, 6, "PDCH");
7914
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007915 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007916}
7917
7918/* Test IPA PDCH activation NACK */
7919testcase TC_dyn_pdch_ipa_act_nack() runs on test_CT {
7920 var RSL_Message rsl_unused;
7921
7922 /* change Timeslot 6 before f_init() starts RSL */
7923 f_init_vty();
7924 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7925 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7926
7927 f_init(1, false);
7928 f_sleep(1.0);
7929
7930 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7931
7932 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7933 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007934 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
7935 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007936 f_sleep(1.0);
7937 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7938
7939 /* De-activate it via VTY */
7940 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7941 f_sleep(1.0);
7942 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7943
7944 /* re-activate it via VTY, but fail that; check BSC still assumes TCH/F mode */
7945 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn, RSL_ERR_EQUIPMENT_FAIL);
7946 f_sleep(1.0);
7947 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7948
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007949 /* clean up config */
7950 f_ts_set_chcomb(0, 0, 6, "PDCH");
7951
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007952 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007953}
7954
7955
7956/***********************************************************************
7957 * Osmocom style dynamic PDCH
7958 ***********************************************************************/
7959
7960private function f_dyn_osmo_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7961 template (omit) RSL_Cause nack := omit)
7962runs on test_CT {
7963 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
7964 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02007965 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02007966 /* FIXME: no VTY command to activate Osmocom PDCH !! */
7967 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007968 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT(chan_nr, ?));
Harald Welte94e0c342018-04-07 11:33:23 +02007969 if (istemplatekind(nack, "omit")) {
7970 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007971 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02007972 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007973 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007974 }
7975}
7976
7977private function f_dyn_osmo_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7978 template (omit) RSL_Cause nack := omit)
7979runs on test_CT {
7980 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
7981 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02007982 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02007983 /* FIXME: no VTY command to activate Osmocom PDCH !! */
7984 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007985 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007986 if (istemplatekind(nack, "omit")) {
7987 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007988 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007989 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007990 //f_ipa_tx(ts_RSL_RF_CHAN_REL_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007991 }
7992}
7993
7994/* Test Osmocom dyn PDCH activation / deactivation triggered by VTY */
7995testcase TC_dyn_pdch_osmo_act_deact() runs on test_CT {
7996 var RSL_Message rsl_unused;
7997
7998 /* change Timeslot 6 before f_init() starts RSL */
7999 f_init_vty();
8000 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
8001 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8002
8003 f_init(1, false);
8004 f_sleep(1.0);
8005
8006 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
8007
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02008008 log("TCH/F_TCH/H_PDCH pchan starts out in disabled mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02008009 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8010 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008011 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008012
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008013 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02008014 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02008015 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 +02008016 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
8017
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008018 /* clean up config */
8019 f_ts_set_chcomb(0, 0, 6, "PDCH");
8020
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008021 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008022}
8023
8024/* Test Osmocom dyn PDCH activation NACK behavior */
8025testcase TC_dyn_pdch_osmo_act_nack() runs on test_CT {
8026 var RSL_Message rsl_unused;
8027
8028 /* change Timeslot 6 before f_init() starts RSL */
8029 f_init_vty();
8030 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
8031 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8032
8033 f_init(1, false);
8034 f_sleep(1.0);
8035
8036 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
8037
8038 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8039 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008040 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008041
8042 /* NACK this activation and expect the "show timeslot" mode still to be NONE */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008043 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
Harald Welte94e0c342018-04-07 11:33:23 +02008044 f_sleep(1.0);
8045 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8046
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008047 /* clean up config */
8048 f_ts_set_chcomb(0, 0, 6, "PDCH");
8049
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008050 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008051}
8052
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008053/* Test Osmocom dyn TS SDCCH8 activation / deactivation */
8054testcase TC_dyn_ts_sdcch8_act_deact() runs on test_CT {
8055 var RSL_Message rsl_unused, rsl_msg;
8056 var DchanTuple dt;
8057 var BSSAP_N_CONNECT_ind rx_c_ind;
8058
8059 /* change Timeslot 6 before f_init() starts RSL */
8060 f_init_vty();
8061 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
8062 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8063
8064 f_init(1, false);
8065 f_sleep(1.0);
8066
8067 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8068
8069 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8070 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8071 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008072 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008073
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008074 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008075 f_sleep(1.0);
8076 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8077 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8078
8079 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8080 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008081 var DchanTuples sdcch_cleanup := {};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008082 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008083 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008084 dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008085 sdcch_cleanup := sdcch_cleanup & { dt };
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008086 }
8087
8088 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008089 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8090 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8091 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008092
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008093 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008094 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008095 dt.idx := {0, 0};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008096
8097 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008098 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8099 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008100 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
8101
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008102 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 +02008103 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8104 dt.sccp_conn_id := rx_c_ind.connectionId;
8105 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8106
8107 /* Instruct BSC to clear channel */
8108 var BssmapCause cause := 0;
8109 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008110 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008111
8112 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008113 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8114 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008115 f_sleep(1.0);
8116 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8117
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008118 /* Clean up SDCCH lchans */
8119 for (i := 0; i < lengthof(sdcch_cleanup); i := i + 1) {
8120 f_perform_clear_test_ct(sdcch_cleanup[i]);
8121 }
8122
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008123 /* clean up config */
8124 f_ts_set_chcomb(0, 0, 6, "PDCH");
8125
8126 f_shutdown_helper();
8127}
8128
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008129/* Validate all 8 subslots of a dynamics TS configured as SDCCH8 are used */
8130testcase TC_dyn_ts_sdcch8_all_subslots_used() runs on test_CT {
8131 var ASP_RSL_Unitdata rsl_ud;
8132 var integer i;
8133 var integer chreq_total, chreq_nochan;
8134
8135 f_init_vty();
8136 for (i := 1; i < 8; i := i + 1) {
8137 if (i == 2) {
8138 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8139 } else {
8140 f_ts_set_chcomb(0, 0, i, "PDCH");
8141 }
8142 }
8143 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8144
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008145 f_init(1, guard_timeout := 60.0);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008146
8147 /* The dyn TS want to activate PDCH mode, ACK that. */
8148 var RslChannelNr chan_nr;
8149 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008150 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
8151 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008152
8153 f_sleep(1.0);
8154
8155 /* Exhaust all dedicated SDCCH lchans.
8156 /* GSM 44.018 Table 9.1.8.2:
8157 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
8158 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008159 var DchanTuples chan_cleanup := {};
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008160 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008161 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 +02008162 }
8163
8164 /* Only the dyn TS is still available. Its first lchan gets converted to SDCCH8 */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008165 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 +02008166 /* Also occupy the seven other SDCCH of the dyn TS */
8167 for (i := 0; i < 7; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008168 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 +01008169 }
8170
8171 /* Clean up SDCCH lchans */
8172 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8173 f_perform_clear_test_ct(chan_cleanup[i]);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008174 }
8175
8176 /* clean up config */
8177 f_ts_reset_chcomb(0);
8178
8179 f_shutdown_helper();
8180}
8181
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008182/* Test Osmocom dyn TS SDCCH8 activation / deactivation: If activating dyn TS as
8183 SDCCH8 would end up in having no free TCH, then BSC should decide to activate
8184 it as TCH directly instead. SYS#5309. */
8185testcase TC_dyn_ts_sdcch8_tch_call_act_deact() runs on test_CT {
8186 var RSL_Message rsl_unused, rsl_msg;
8187 var DchanTuple dt;
8188 var BSSAP_N_CONNECT_ind rx_c_ind;
8189 var integer i;
8190
8191 /* change Timeslot 6 before f_init() starts RSL */
8192 f_init_vty();
8193 for (i := 1; i < 8; i := i + 1) {
8194 if (i == 6) {
8195 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8196 } else {
8197 f_ts_set_chcomb(0, 0, i, "PDCH");
8198 }
8199 }
8200 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8201
8202 f_init(1, false);
8203 f_sleep(1.0);
8204
8205 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8206
8207 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8208 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8209 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008210 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008211
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008212 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008213 f_sleep(1.0);
8214 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8215 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8216
8217 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8218 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008219 var DchanTuples chan_cleanup := {};
Pau Espin Pedrol2ebbe7c2021-07-23 16:17:09 +02008220 var OCT1 ra := '43'O; /* RA containing reason=originating speech call*/
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008221 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008222 dt := f_est_dchan(ra, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008223 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008224 }
8225
8226 /* Now the dyn ts is selected. First PDCH is released, then TCH chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008227 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int(ra) + i, 1), 2342));
8228 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8229 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008230
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008231 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008232 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008233 dt.idx := {0, 0};
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008234
8235 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008236 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8237 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008238 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
8239
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008240 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 +02008241 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8242 dt.sccp_conn_id := rx_c_ind.connectionId;
8243 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8244
8245 /* Instruct BSC to clear channel */
8246 var BssmapCause cause := 0;
8247 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008248 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008249
8250 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008251 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8252 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008253 f_sleep(1.0);
8254 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8255
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008256 /* Clean up SDCCH lchans */
8257 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8258 f_perform_clear_test_ct(chan_cleanup[i]);
8259 }
8260
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008261 /* clean up config */
8262 f_ts_reset_chcomb(0);
8263 /* TODO: clean up other channels? */
8264
8265 f_shutdown_helper();
8266}
8267
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008268/* Test Osmocom dyn TS SDCCH8 activation / deactivation when SDCCH fails at BTS */
8269testcase TC_dyn_ts_sdcch8_act_nack() runs on test_CT {
8270 var RSL_Message rsl_unused, rsl_msg;
8271 var DchanTuple dt;
8272 var BSSAP_N_CONNECT_ind rx_c_ind;
8273 var GsmRrMessage rr;
8274
8275 /* change Timeslot 6 before f_init() starts RSL */
8276 f_init_vty();
8277 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
8278 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8279
8280 f_init(1, false);
8281 f_sleep(1.0);
8282
8283 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8284
8285 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8286 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8287 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008288 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008289
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008290 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008291 f_sleep(1.0);
8292 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8293 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8294
8295 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8296 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008297 var DchanTuples chan_cleanup := {};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008298 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008299 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008300 dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008301 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008302 }
8303
8304 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008305 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8306 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8307 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008308
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008309 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008310 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008311 dt.idx := {0, 0};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008312
8313 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008314 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(dt.rsl_chan_nr, RSL_ERR_EQUIPMENT_FAIL));
8315 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008316 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
8317 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
8318 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Expected reject");
8319 }
8320
8321 /* FIXME? Currently the TS stays in state BORKEN: */
8322
8323 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008324 /* rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8325 * f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008326 * f_sleep(1.0);
8327 * f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE)
8328 */
8329
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008330 /* Clean up SDCCH lchans */
8331 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8332 f_perform_clear_test_ct(chan_cleanup[i]);
8333 }
8334
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008335 /* clean up config */
8336 f_ts_set_chcomb(0, 0, 6, "PDCH");
8337
8338 f_shutdown_helper();
8339}
8340
Stefan Sperling0796a822018-10-05 13:01:39 +02008341testcase TC_chopped_ipa_ping() runs on test_CT {
Stefan Sperling554123f2018-10-09 14:12:30 +02008342 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port, mp_bsc_ctrl_port};
Stefan Sperling0796a822018-10-05 13:01:39 +02008343 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8344 IPA_Testing.f_run_TC_chopped_ipa_ping(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8345 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008346 f_shutdown_helper();
Stefan Sperling0796a822018-10-05 13:01:39 +02008347}
8348
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008349testcase TC_chopped_ipa_payload() runs on test_CT {
8350 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port
8351 /* TODO: mp_bsc_ctrl_port does not work yet */};
8352 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8353 IPA_Testing.f_run_TC_chopped_ipa_payload(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8354 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008355 f_shutdown_helper();
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008356}
8357
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008358/* Verify the BSC sends the MS Power Parameters IE during CHAN ACT to make sure
8359 the BTS does autonomous MS power control loop */
8360testcase TC_assignment_verify_ms_power_params_ie() runs on test_CT {
8361 var MSC_ConnHdlr vc_conn;
8362 var TestHdlrParams pars := f_gen_test_hdlr_pars();
8363 //pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
8364 pars.exp_ms_power_params := true;
8365
8366 f_init(1, true);
8367 f_sleep(1.0);
8368 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
8369 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008370 f_shutdown_helper();
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008371}
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008372
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008373/* Verify activation and deactivation of the BCCH carrier power reduction mode */
8374testcase TC_c0_power_red_mode() runs on test_CT {
8375 f_init(1);
8376
8377 for (var integer red := 6; red >= 0; red := red - 2) {
8378 /* Configure BCCH carrier power reduction mode via the VTY */
8379 f_vty_transceive(BSCVTY, "bts 0 c0-power-reduction " & int2str(red));
8380
8381 /* Expect Osmocom specific BS Power Control message on the RSL */
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03008382 var template (present) RSL_Message tr_rsl_pdu := tr_RSL_BS_PWR_CTRL(
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008383 chan_nr := t_RslChanNr_BCCH(0),
8384 bs_power := tr_RSL_IE_BS_Power(red / 2));
8385 tr_rsl_pdu.msg_disc := tr_RSL_MsgDisc(RSL_MDISC_CCHAN, false);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008386 var RSL_Message unused := f_exp_ipa_rx(tr_rsl_pdu);
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008387
8388 /* Additionally verify the applied value over the CTRL interface */
8389 var CtrlValue cred := f_ctrl_get_bts(IPA_CTRL, 0, "c0-power-reduction");
8390 if (cred != int2str(red)) {
8391 setverdict(fail, "Unexpected BCCH carrier power reduction value ",
8392 cred, " (expected ", red, ")");
8393 }
8394 }
8395
8396 f_shutdown_helper();
8397}
8398
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008399/***********************************************************************
8400 * MSC Pooling
8401 ***********************************************************************/
8402
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008403template MobileIdentityLV ts_MI_TMSI_NRI_LV(integer nri_v, integer nri_bitlen := 10) :=
Harald Weltebf397612021-01-14 20:39:46 +01008404 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 +02008405
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008406private 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 +02008407runs on MSC_ConnHdlr {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008408 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008409 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008410 f_logp(BSCVTY, "Got RSL RR Release");
8411 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008412 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008413 f_logp(BSCVTY, "Got RSL Deact SACCH");
8414 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008415 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008416 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008417 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8418 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008419 break;
8420 }
8421 }
8422}
8423
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008424private altstep as_mgcp_ack_all_dlcx() runs on MSC_ConnHdlr {
8425 var MgcpCommand mgcp_cmd;
8426 [] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
8427 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
8428 repeat;
8429 }
8430}
8431
8432private altstep as_rsl_ack_all_rel_req() runs on MSC_ConnHdlr {
8433 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
8434 [] RSL.receive(tr_RSL_REL_REQ(g_chan_nr, ?)) {
8435 RSL.send(ts_RSL_REL_CONF(g_chan_nr, main_dcch));
8436 repeat;
8437 }
8438}
8439
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008440friend function f_perform_clear(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC,
8441 template PDU_ML3_NW_MS exp_rr_rel_tmpl := tr_RRM_RR_RELEASE)
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02008442runs on MSC_ConnHdlr {
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008443 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8444 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008445 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008446 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8447 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008448 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008449 f_logp(BSCVTY, "Got RSL RR Release");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008450 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008451 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008452 f_logp(BSCVTY, "Got RSL Deact SACCH");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008453 }
8454 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008455 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008456 /* Also drop the SCCP connection */
8457 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8458 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008459 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008460 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008461 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8462 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008463 }
8464 }
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008465 deactivate(ack_dlcx);
8466 deactivate(ack_rel_req);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008467}
8468
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01008469friend function f_perform_clear_no_rr_rel(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC)
8470runs on MSC_ConnHdlr {
8471 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8472 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
8473 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8474 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8475 interleave {
8476 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
8477 f_logp(BSCVTY, "Got RSL Deact SACCH");
8478 }
8479 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
8480 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8481 /* Also drop the SCCP connection */
8482 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8483 }
8484 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
8485 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
8486 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8487 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
8488 }
8489 }
8490 deactivate(ack_dlcx);
8491 deactivate(ack_rel_req);
8492}
8493
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01008494friend function f_perform_clear_no_lchan()
8495runs on MSC_ConnHdlr {
8496 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8497 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8498 BSSAP.receive(tr_BSSMAP_ClearComplete);
8499 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8500 /* Also drop the SCCP connection */
8501 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8502}
8503
Vadim Yanitskiy65d879d2022-06-23 18:15:39 +07008504friend function f_perform_clear_test_ct(DchanTuple dt)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008505 runs on test_CT
8506{
8507 /* Instruct BSC to clear channel */
8508 var BssmapCause cause := 0;
8509 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008510 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008511}
8512
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008513private function f_perform_compl_l3(RSL_DCHAN_PT rsl_pt, RSLEM_PROC_PT rsl_proc_pt,
8514 template PDU_ML3_MS_NW l3_info, boolean do_clear := true, boolean expect_bssmap_l3 := true)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008515runs on MSC_ConnHdlr {
8516 timer T := 10.0;
8517 var octetstring l3_enc := enc_PDU_ML3_MS_NW(valueof(l3_info));
8518
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008519 f_logp(BSCVTY, "establish channel, send Complete Layer 3 Info");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008520 f_create_bssmap_exp(l3_enc);
8521
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008522 /* RSL_Emulation.f_chan_est() on rsl_pt:
8523 * This is basically code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008524 * RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
8525 */
8526 var RSL_Message rx_rsl;
8527 var GsmRrMessage rr;
8528
8529 /* request a channel to be established */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008530 rsl_pt.send(ts_RSLDC_ChanRqd(g_pars.ra, g_pars.fn));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008531 /* expect immediate assignment.
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008532 * Code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008533 * rx_rsl := f_rx_or_fail(tr_RSL_IMM_ASSIGN);
8534 */
8535 timer Tt := 10.0;
8536
8537 /* request a channel to be established */
8538 Tt.start;
8539 alt {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008540 [] rsl_pt.receive(tr_RSL_IMM_ASSIGN) -> value rx_rsl {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008541 Tt.stop;
8542 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008543 [] rsl_pt.receive {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008544 setverdict(fail, "Unexpected RSL message on DCHAN");
8545 mtc.stop;
8546 }
8547 [] Tt.timeout {
8548 setverdict(fail, "Timeout waiting for RSL on DCHAN");
8549 mtc.stop;
8550 }
8551 }
8552 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
8553 g_chan_nr := rr.payload.imm_ass.chan_desc.chan_nr;
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008554 rsl_pt.send(ts_RSL_EST_IND(g_chan_nr, valueof(g_pars.link_id), l3_enc));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008555
8556
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008557 if (expect_bssmap_l3) {
8558 f_logp(BSCVTY, "expect BSSAP Complete Layer 3 Info at MSC");
8559 var template PDU_BSSAP exp_l3_compl;
8560 exp_l3_compl := tr_BSSMAP_ComplL3()
8561 if (g_pars.aoip == false) {
8562 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := omit;
8563 } else {
8564 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := ?;
8565 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008566
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008567 var PDU_BSSAP bssap;
8568 T.start;
8569 alt {
8570 [] BSSAP.receive(exp_l3_compl) -> value bssap {
8571 f_logp(BSCVTY, "received expected Complete Layer 3 Info at MSC");
8572 log("rx exp_l3_compl = ", bssap);
8573 }
8574 [] BSSAP.receive(tr_BSSMAP_ComplL3) {
8575 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received non-matching COMPLETE LAYER 3 INFORMATION");
8576 }
8577 [] T.timeout {
8578 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
8579 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008580 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008581
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008582 /* start ciphering, if requested */
8583 if (ispresent(g_pars.encr)) {
8584 f_logp(BSCVTY, "start ciphering");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008585 f_cipher_mode(g_pars.encr, rsl_pt := rsl_pt, rsl_proc_pt := rsl_proc_pt);
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008586 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008587 }
8588
8589 if (do_clear) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008590 f_perform_clear(rsl_pt, rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008591 }
8592 setverdict(pass);
8593 f_sleep(1.0);
8594}
8595
8596private function f_tc_mscpool_compl_l3(charstring id) runs on MSC_ConnHdlr {
8597 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8598 if (g_pars.mscpool.rsl_idx == 0) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008599 f_perform_compl_l3(RSL, RSL_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008600 } else if (g_pars.mscpool.rsl_idx == 1) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008601 f_perform_compl_l3(RSL1, RSL1_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008602 } else if (g_pars.mscpool.rsl_idx == 2) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008603 f_perform_compl_l3(RSL2, RSL2_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008604 }
8605}
8606
8607/* Various Complete Layer 3 by IMSI all end up with the first MSC, because the other MSCs are not connected. */
8608private function f_tc_mscpool_L3Compl_on_1_msc(charstring id) runs on MSC_ConnHdlr {
8609 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008610 f_perform_compl_l3(RSL, RSL_PROC, ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O) );
8611 f_perform_compl_l3(RSL, RSL_PROC, ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_IMSI_LV('001010000000002'H))) );
8612 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))) );
8613 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 +02008614}
8615testcase TC_mscpool_L3Compl_on_1_msc() runs on test_CT {
8616
8617 f_init(1, true);
8618 f_sleep(1.0);
8619 var MSC_ConnHdlr vc_conn;
8620 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008621
8622 f_ctrs_msc_init();
8623
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008624 vc_conn := f_start_handler(refers(f_tc_mscpool_L3Compl_on_1_msc), pars);
8625 vc_conn.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008626
8627 f_ctrs_msc_expect(0, "mscpool:subscr:new", 4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008628 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008629}
8630
8631/* Three Layer 3 Complete by IMSI are round-robin'ed across two connected MSCs */
8632/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8633 * just as well using only RSL. */
8634testcase TC_mscpool_L3Complete_by_imsi_round_robin() runs on test_CT {
8635
8636 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8637 f_sleep(1.0);
8638
8639 /* Control which MSC gets chosen next by the round-robin, otherwise
8640 * would be randomly affected by which other tests ran before this. */
8641 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8642
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008643 f_ctrs_msc_init();
8644
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008645 var MSC_ConnHdlr vc_conn1;
8646 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8647 pars1.mscpool.rsl_idx := 0;
8648 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
8649 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8650 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008651 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008652
8653 var MSC_ConnHdlr vc_conn2;
8654 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8655 pars2.mscpool.rsl_idx := 1;
8656 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
8657 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8658 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008659 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008660
8661 /* Test round-robin wrap to the first MSC */
8662 var MSC_ConnHdlr vc_conn3;
8663 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8664 pars3.mscpool.rsl_idx := 2;
8665 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))));
8666 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8667 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008668 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008669 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008670}
8671
8672/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 0
8673 * (configured in osmo-bsc.cfg). */
8674/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8675 * just as well using only RSL. */
8676testcase TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() runs on test_CT {
8677
8678 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8679 f_sleep(1.0);
8680
8681 /* Control which MSC gets chosen next by the round-robin, otherwise
8682 * would be randomly affected by which other tests ran before this. */
8683 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8684
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008685 f_ctrs_msc_init();
8686
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008687 var MSC_ConnHdlr vc_conn1;
8688 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8689 pars1.mscpool.rsl_idx := 0;
8690 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8691 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8692 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008693 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008694
8695 var MSC_ConnHdlr vc_conn2;
8696 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8697 pars2.mscpool.rsl_idx := 1;
8698 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8699 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8700 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008701 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008702
8703 /* Test round-robin wrap to the first MSC */
8704 var MSC_ConnHdlr vc_conn3;
8705 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8706 pars3.mscpool.rsl_idx := 2;
8707 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8708 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8709 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008710 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008711 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008712}
8713
8714/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 1
8715 * (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
8716 * NULL-NRI setting is stronger than that. */
8717/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8718 * just as well using only RSL. */
8719testcase TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() runs on test_CT {
8720
8721 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8722 f_sleep(1.0);
8723
8724 /* Control which MSC gets chosen next by the round-robin, otherwise
8725 * would be randomly affected by which other tests ran before this. */
8726 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8727
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008728 f_ctrs_msc_init();
8729
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008730 var MSC_ConnHdlr vc_conn1;
8731 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8732 pars1.mscpool.rsl_idx := 0;
8733 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8734 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8735 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008736 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008737
8738 var MSC_ConnHdlr vc_conn2;
8739 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8740 pars2.mscpool.rsl_idx := 1;
8741 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8742 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8743 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008744 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008745
8746 /* Test round-robin wrap to the first MSC */
8747 var MSC_ConnHdlr vc_conn3;
8748 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8749 pars3.mscpool.rsl_idx := 2;
8750 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8751 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8752 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008753 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008754 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008755}
8756
8757/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI not
8758 * assigned to any MSC (configured in osmo-bsc.cfg). */
8759/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8760 * just as well using only RSL. */
8761testcase TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() runs on test_CT {
8762
8763 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8764 f_sleep(1.0);
8765
8766 /* Control which MSC gets chosen next by the round-robin, otherwise
8767 * would be randomly affected by which other tests ran before this. */
8768 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8769
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008770 f_ctrs_msc_init();
8771
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008772 var MSC_ConnHdlr vc_conn1;
8773 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8774 pars1.mscpool.rsl_idx := 0;
8775 /* An NRI that is not assigned to any MSC */
8776 pars1.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(1023))));
8777 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8778 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008779 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008780
8781 var MSC_ConnHdlr vc_conn2;
8782 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8783 pars2.mscpool.rsl_idx := 1;
8784 /* An NRI that is not assigned to any MSC */
8785 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(768)), '00F110'O));
8786 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8787 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008788 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008789
8790 /* Test round-robin wrap to the first MSC */
8791 var MSC_ConnHdlr vc_conn3;
8792 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8793 pars3.mscpool.rsl_idx := 2;
8794 /* An NRI that is not assigned to any MSC */
8795 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_SS_ACT, valueof(ts_MI_TMSI_NRI_LV(819))));
8796 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8797 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008798 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008799 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008800}
8801
8802/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI
8803 * assigned to an MSC that is currently not connected (configured in osmo-bsc.cfg). */
8804/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8805 * just as well using only RSL. */
8806testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() runs on test_CT {
8807
8808 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8809 f_sleep(1.0);
8810
8811 /* Control which MSC gets chosen next by the round-robin, otherwise
8812 * would be randomly affected by which other tests ran before this. */
8813 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8814
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008815 f_ctrs_msc_init();
8816
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008817 var MSC_ConnHdlr vc_conn1;
8818 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8819 pars1.mscpool.rsl_idx := 0;
8820 /* An NRI that is assigned to an unconnected MSC */
8821 pars1.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(512))));
8822 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8823 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008824 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8825 f_ctrs_msc_add(0, "mscpool:subscr:new");
8826 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008827
8828 var MSC_ConnHdlr vc_conn2;
8829 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8830 pars2.mscpool.rsl_idx := 1;
8831 /* An NRI that is assigned to an unconnected MSC */
8832 pars2.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(767))));
8833 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8834 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008835 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8836 f_ctrs_msc_add(1, "mscpool:subscr:new");
8837 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008838
8839 /* Test round-robin wrap to the first MSC */
8840 var MSC_ConnHdlr vc_conn3;
8841 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8842 pars3.mscpool.rsl_idx := 2;
8843 /* An NRI that is assigned to an unconnected MSC */
8844 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(750)), '00F110'O));
8845 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8846 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008847 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8848 f_ctrs_msc_add(0, "mscpool:subscr:new");
8849 f_ctrs_msc_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008850 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008851}
8852
8853/* Three Layer 3 Complete by TMSI with valid NRI for the second MSC are all directed to the second MSC (configured in
8854 * osmo-bsc.cfg). */
8855/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8856 * just as well using only RSL. */
8857testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_1() runs on test_CT {
8858
8859 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8860 f_sleep(1.0);
8861
8862 /* All TMSIs in this test point at the second MSC, set the round robin to point at the first MSC to make sure
8863 * this is not using round-robin. */
8864 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8865
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008866 f_ctrs_msc_init();
8867
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008868 var MSC_ConnHdlr vc_conn1;
8869 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
8870 pars1.mscpool.rsl_idx := 0;
8871 /* An NRI of the second MSC's range (256-511) */
8872 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(256))));
8873 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8874 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008875 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008876
8877 var MSC_ConnHdlr vc_conn2;
8878 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8879 pars2.mscpool.rsl_idx := 1;
8880 /* An NRI of the second MSC's range (256-511) */
8881 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(260))));
8882 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8883 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008884 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008885
8886 var MSC_ConnHdlr vc_conn3;
8887 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8888 pars3.mscpool.rsl_idx := 2;
8889 /* An NRI of the second MSC's range (256-511) */
8890 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(511)), '00F110'O));
8891 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8892 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008893 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008894 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008895}
8896
8897/* Layer 3 Complete by TMSI with valid NRI for the third MSC are directed to the third MSC (configured in osmo-bsc.cfg),
8898 * while a round-robin remains unaffected by that. */
8899/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8900 * just as well using only RSL. */
8901testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_2() runs on test_CT {
8902
8903 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8904 f_sleep(1.0);
8905
8906 /* All TMSIs in this test point at the third MSC, set the round robin to point at the second MSC to make sure
8907 * this is not using round-robin. */
8908 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
8909
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008910 f_ctrs_msc_init();
8911
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008912 var MSC_ConnHdlr vc_conn1;
8913 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 2);
8914 pars1.mscpool.rsl_idx := 0;
8915 /* An NRI of the third MSC's range (512-767) */
8916 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(512))));
8917 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8918 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008919 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008920
8921 var MSC_ConnHdlr vc_conn2;
8922 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8923 pars2.mscpool.rsl_idx := 1;
8924 /* An NRI of the third MSC's range (512-767) */
8925 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(678))));
8926 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8927 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008928 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008929
8930 /* The above forwardings to third MSC have not affected the round robin, which still points at the second MSC */
8931 var MSC_ConnHdlr vc_conn3;
8932 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8933 pars3.mscpool.rsl_idx := 2;
8934 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000013'H)), '00F110'O));
8935 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8936 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008937 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008938 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008939}
8940
8941/* LU with a TMSI but indicating a different PLMN in its previous LAI: ignore the NRI. */
8942/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8943 * just as well using only RSL. */
8944testcase TC_mscpool_LU_by_tmsi_from_other_PLMN() runs on test_CT {
8945
8946 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8947 f_sleep(1.0);
8948
8949 /* The TMSIs in this test points at the second MSC, but since it is from a different PLMN, round-robin is used
8950 * instead, and hits msc 0. */
8951 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8952
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008953 f_ctrs_msc_init();
8954
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008955 /* An NRI of the second MSC's range (256-511), but a PLMN that doesn't match with osmo-bsc.cfg */
8956 var MSC_ConnHdlr vc_conn1;
8957 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8958 pars1.mscpool.rsl_idx := 0;
8959 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(260)), '99F999'O));
8960 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8961 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008962 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008963
8964 /* An NRI of the third MSC's range (512-767) and a matching PLMN gets directed by NRI. */
8965 var MSC_ConnHdlr vc_conn2;
8966 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8967 pars2.mscpool.rsl_idx := 1;
8968 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(555)), '00F110'O));
8969 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8970 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008971 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008972 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008973}
8974
8975/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by IMSI, which would be
8976 * round-robined to another MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
8977private function f_tc_mscpool_paging_imsi(charstring id) runs on MSC_ConnHdlr {
8978 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
8979 //cid_list := { cIl_allInBSS := ''O };
8980 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
8981 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
8982 var BSSAP_N_UNITDATA_req paging;
8983 var hexstring imsi := '001010000000123'H;
8984
8985 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8986
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008987 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008988 valueof(ts_BSSMAP_Paging(imsi, cid_list, omit, bssmap_chneed))));
8989 BSSAP.send(paging);
8990
8991 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
8992 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
8993 * channel number is picked here. */
8994 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
8995 f_rslem_register(0, new_chan_nr);
8996 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(imsi)));
8997 f_rslem_unregister(0, new_chan_nr);
8998
8999 /* Despite the round robin pointing at the second MSC ('roundrobin next 1'), the earlier Paging for the same IMSI
9000 * causes this Paging Response to go to the first MSC (bssap_idx := 0). */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02009001 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(valueof(ts_MI_IMSI_LV(imsi))) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009002 f_sleep(1.0);
9003}
9004testcase TC_mscpool_paging_and_response_imsi() runs on test_CT {
9005 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
9006 f_sleep(1.0);
9007
9008 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
9009 * second MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
9010 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
9011
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009012 f_ctrs_msc_init();
9013
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009014 var MSC_ConnHdlr vc_conn1;
9015 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9016 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009017 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
9018 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009019 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_imsi), pars1);
9020 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009021 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009022 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009023}
9024
9025/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by TMSI with an NRI value
9026 * that matches a different MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
9027private function f_tc_mscpool_paging_tmsi(charstring id) runs on MSC_ConnHdlr {
9028 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
9029 //cid_list := { cIl_allInBSS := ''O };
9030 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
9031 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
9032 var integer nri_v := 300; /* <-- second MSC's NRI */
Harald Weltebf397612021-01-14 20:39:46 +01009033 var octetstring tmsi := f_gen_tmsi(suffix := 0, nri_v := nri_v);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009034 var BSSAP_N_UNITDATA_req paging;
9035
9036 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9037
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009038 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009039 valueof(ts_BSSMAP_Paging('001010000000011'H, cid_list, tmsi, bssmap_chneed))));
9040 BSSAP.send(paging);
9041
9042 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
9043 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
9044 * channel number is picked here. */
9045 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
9046 f_rslem_register(0, new_chan_nr);
9047 RSL.receive(tr_RSL_PAGING_CMD(t_MI_TMSI(tmsi)));
9048 f_rslem_unregister(0, new_chan_nr);
9049
9050 /* Despite the NRI matching the second MSC (NRI from 'msc 1' in osmo-bsc.cfg) and round robin pointing at the
9051 * third MSC ('roundrobin next 2'), the earlier Paging for the same TMSI causes this Paging Response to go to
9052 * the first MSC (bssap_idx := 0). */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02009053 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(nri_v))) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009054 f_sleep(1.0);
9055}
9056testcase TC_mscpool_paging_and_response_tmsi() runs on test_CT {
9057 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
9058 f_sleep(1.0);
9059
9060 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
9061 * third MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
9062 f_vty_transceive(BSCVTY, "mscpool roundrobin next 2");
9063
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009064 f_ctrs_msc_init();
9065
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009066 var MSC_ConnHdlr vc_conn1;
9067 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9068 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009069 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
9070 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009071 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_tmsi), pars1);
9072 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009073 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009074 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009075}
9076
9077/* For round-robin, skip an MSC that has 'no allow-attach' set. */
9078/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
9079 * just as well using only RSL. */
9080testcase TC_mscpool_no_allow_attach_round_robin() runs on test_CT {
9081
9082 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9083 f_sleep(1.0);
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00009084 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
9085 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009086
9087 /* Control which MSC gets chosen next by the round-robin, otherwise
9088 * would be randomly affected by which other tests ran before this. */
9089 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9090
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009091 f_ctrs_msc_init();
9092
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009093 var MSC_ConnHdlr vc_conn1;
9094 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9095 pars1.mscpool.rsl_idx := 0;
9096 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
9097 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9098 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009099 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009100
9101 var MSC_ConnHdlr vc_conn2;
9102 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
9103 pars2.mscpool.rsl_idx := 1;
9104 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9105 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9106 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009107 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009108
9109 var MSC_ConnHdlr vc_conn3;
9110 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
9111 pars3.mscpool.rsl_idx := 2;
9112 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))));
9113 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9114 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009115 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009116 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009117}
9118
9119/* An MSC that has 'no allow-attach' set should still serve subscribers that are already attached according to their
9120 * TMSI NRI. */
9121testcase TC_mscpool_no_allow_attach_valid_nri() runs on test_CT {
9122
9123 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9124 f_sleep(1.0);
9125
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00009126 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
9127 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
9128
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009129 /* Control which MSC gets chosen next by the round-robin, otherwise
9130 * would be randomly affected by which other tests ran before this. */
9131 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9132
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009133 f_ctrs_msc_init();
9134
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009135 /* Round robin points at msc 0, but the valid NRI directs to msc 1, even though msc 1 has 'no allow-attach'. */
9136 var MSC_ConnHdlr vc_conn1;
9137 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
9138 pars1.mscpool.rsl_idx := 0;
9139 /* An NRI of the second MSC's range (256-511) */
9140 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_TMSI_NRI_LV(260))));
9141 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9142 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009143 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009144
9145 var MSC_ConnHdlr vc_conn2;
9146 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 0);
9147 pars2.mscpool.rsl_idx := 1;
9148 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9149 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9150 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009151 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009152
9153 var MSC_ConnHdlr vc_conn3;
9154 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 2);
9155 pars3.mscpool.rsl_idx := 2;
9156 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000003'H))));
9157 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9158 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009159 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009160 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009161}
9162
Philipp Maier783681c2020-07-16 16:47:06 +02009163/* Allow/Deny emergency calls globally via VTY */
9164private function f_vty_allow_emerg_msc(boolean allow) runs on test_CT {
9165 f_vty_enter_cfg_msc(BSCVTY, 0);
9166 if (allow) {
9167 f_vty_transceive(BSCVTY, "allow-emergency allow");
9168 } else {
9169 f_vty_transceive(BSCVTY, "allow-emergency deny");
9170 }
9171 f_vty_transceive(BSCVTY, "exit");
9172 f_vty_transceive(BSCVTY, "exit");
9173}
9174
9175/* Allow/Deny emergency calls per BTS via VTY */
9176private function f_vty_allow_emerg_bts(boolean allow, integer bts_nr) runs on test_CT {
9177 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9178 if (allow) {
9179 f_vty_transceive(BSCVTY, "rach emergency call allowed 1");
9180 } else {
9181 f_vty_transceive(BSCVTY, "rach emergency call allowed 0");
9182 }
9183 f_vty_transceive(BSCVTY, "exit");
9184 f_vty_transceive(BSCVTY, "exit");
Neels Hofmeyrb6ed80c2020-10-12 22:52:39 +00009185 f_vty_transceive(BSCVTY, "exit");
Philipp Maier783681c2020-07-16 16:47:06 +02009186}
9187
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02009188/* Allow/Forbid Fast Return after SRVCC on a given BTS via VTY */
9189private function f_vty_allow_srvcc_fast_return(boolean allow, integer bts_nr) runs on test_CT {
9190 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9191 if (allow) {
9192 f_vty_transceive(BSCVTY, "srvcc fast-return allow");
9193 } else {
9194 f_vty_transceive(BSCVTY, "srvcc fast-return forbid");
9195 }
9196 f_vty_transceive(BSCVTY, "exit");
9197 f_vty_transceive(BSCVTY, "exit");
9198 f_vty_transceive(BSCVTY, "exit");
9199}
9200
Pau Espin Pedrol14475352021-07-22 15:48:16 +02009201/* Allow/Forbid TCH for signalling if SDCCH exhausted on a given BTS via VTY */
9202private function f_vty_allow_tch_for_signalling(boolean allow, integer bts_nr) runs on test_CT {
9203 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9204 if (allow) {
9205 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 1");
9206 } else {
9207 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 0");
9208 }
9209 f_vty_transceive(BSCVTY, "exit");
9210 f_vty_transceive(BSCVTY, "exit");
9211 f_vty_transceive(BSCVTY, "exit");
9212}
9213
Pau Espin Pedrol35609792023-01-03 16:56:59 +01009214/* Begin assignment procedure and send an EMERGENCY SETUP (RR) */
Philipp Maier783681c2020-07-16 16:47:06 +02009215private function f_assignment_emerg_setup() runs on MSC_ConnHdlr {
9216 var PDU_ML3_MS_NW emerg_setup;
9217 var octetstring emerg_setup_enc;
9218 var RSL_Message emerg_setup_data_ind;
9219
9220 f_establish_fully(omit, omit);
9221
9222 emerg_setup := valueof(ts_ML3_MO_CC_EMERG_SETUP(1, valueof(ts_Bcap_voice)));
9223 emerg_setup_enc := enc_PDU_ML3_MS_NW(emerg_setup);
9224 emerg_setup_data_ind := valueof(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), emerg_setup_enc));
9225
9226 RSL.send(emerg_setup_data_ind);
9227}
9228
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009229/* expect EmergencySetup on BSSAP after calling f_assignment_emerg_setup() */
9230private function f_assignment_emerg_setup_exp_bssap()
9231runs on MSC_ConnHdlr {
Philipp Maier783681c2020-07-16 16:47:06 +02009232 var PDU_BSSAP emerg_setup_data_ind_bssap;
9233 var PDU_ML3_MS_NW emerg_setup;
9234 timer T := 3.0;
9235
Philipp Maier783681c2020-07-16 16:47:06 +02009236 T.start;
9237 alt {
9238 [] BSSAP.receive(tr_BSSAP_DTAP) -> value emerg_setup_data_ind_bssap {
9239 emerg_setup := dec_PDU_ML3_MS_NW(emerg_setup_data_ind_bssap.pdu.dtap);
9240 if (not isbound(emerg_setup.msgs.cc.emergencySetup)) {
9241 setverdict(fail, "no emergency setup");
9242 }
9243 }
9244 [] BSSAP.receive {
9245 setverdict(fail, "unexpected BSSAP message!");
9246 }
9247 [] T.timeout {
9248 setverdict(fail, "timout waiting for EMERGENCY SETUP!");
9249 }
9250 }
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009251}
9252
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009253private function f_assignment_emerg_setup_voice()
9254runs on MSC_ConnHdlr {
9255 /* Go on with voice call assignment */
9256 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
9257 var PDU_BSSAP ass_cmd := f_gen_ass_req();
9258
9259 /* Below speechOrDataIndicator and codecList are copied from an emergency call captured during tests.
9260 * They seem a bit weird (AMR-WB, and the order differ between speechId_DataIndicator and the codecList), but
9261 * seems a good idea to see how osmo-bsc reacts to this. */
9262 ass_cmd.pdu.bssmap.assignmentRequest.channelType := {
9263 elementIdentifier := '0B'O, /* overwritten */
9264 lengthIndicator := 0, /* overwritten */
9265 speechOrDataIndicator := '0001'B, /* speech */
9266 spare1_4 := '0000'B,
9267 channelRateAndType := ChRate_TCHForH_Fpref,
9268 speechId_DataIndicator := 'c2918105'O
9269 };
9270 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({
9271 ts_CodecHR, ts_CodecAMR_WB, ts_CodecEFR, ts_CodecFR}));
9272
9273 f_rslem_dchan_queue_enable();
9274
9275 var ExpectCriteria mgcpcrit := {
9276 connid := omit,
9277 endpoint := omit,
9278 transid := omit
9279 };
9280 f_create_mgcp_expect(mgcpcrit);
9281
9282 BSSAP.send(ass_cmd);
9283
9284 var AssignmentState st := valueof(ts_AssignmentStateInit);
9285 st.voice_call := true;
9286 st.is_assignment := false;
9287 alt {
9288 [] as_modify(st);
9289 [] as_Media();
9290 [st.modify_done] BSSAP.receive(exp_compl) {
9291 setverdict(pass);
9292 }
9293 }
9294
9295 /* Voice call carries on ... */
9296 f_sleep(2.0);
9297}
9298
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009299/* Test if the EMERGENCY SETUP gets passed on to the MSC via A when EMERGENCY
9300 * CALLS are permitted by the BSC config. */
9301private function f_TC_assignment_emerg_setup_allow(charstring id) runs on MSC_ConnHdlr {
9302
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009303 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
9304 * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
9305 * another lchan. */
9306 g_pars.ra := f_rnd_ra_emerg();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009307 f_assignment_emerg_setup();
9308 f_assignment_emerg_setup_exp_bssap();
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009309 f_assignment_emerg_setup_voice();
Philipp Maier783681c2020-07-16 16:47:06 +02009310
9311 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009312 f_perform_clear();
Philipp Maier783681c2020-07-16 16:47:06 +02009313}
9314
9315/* Test if the EMERGENCY SETUP gets blocked by the BSC if EMERGENCY CALLS are
9316 * forbidden by the BSC config. */
9317private function f_TC_assignment_emerg_setup_deny(charstring id) runs on MSC_ConnHdlr {
9318 var PDU_BSSAP emerg_setup_data_ind_bssap;
9319 timer T := 3.0;
9320
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009321 f_assignment_emerg_setup();
Philipp Maier783681c2020-07-16 16:47:06 +02009322
9323 T.start;
9324 alt {
9325 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
9326 setverdict(pass);
9327 }
9328 [] RSL.receive {
9329 setverdict(fail, "unexpected RSL message!");
9330 }
9331 [] T.timeout {
9332 setverdict(fail, "timout waiting for RR CHANNEL RELEASE!");
9333 }
9334 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009335 BSSAP.receive(tr_BSSMAP_ClearRequest);
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01009336 f_perform_clear_no_rr_rel();
Philipp Maier783681c2020-07-16 16:47:06 +02009337}
9338
9339/* EMERGENCY CALL situation #1, allowed globally and by BTS */
9340testcase TC_assignment_emerg_setup_allow() runs on test_CT {
9341 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9342 var MSC_ConnHdlr vc_conn;
9343
9344 f_init(1, true);
9345 f_sleep(1.0);
9346
9347 f_vty_allow_emerg_msc(true);
9348 f_vty_allow_emerg_bts(true, 0);
9349 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
9350 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009351 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009352}
9353
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +01009354/* Test MO emergency call using MobileIdentity=IMEI (possible for emergency
9355 * calls from phones without SIM card).
9356 * 3GPP TS 24.008 section 10.5.1.4, OS#5849 */
9357testcase TC_assignment_emerg_setup_allow_imei() runs on test_CT {
9358 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9359 var MSC_ConnHdlr vc_conn;
9360
9361 /* Remove IMSI set by f_gen_test_hdlr_pars(), then IMEI will be used to place the call */
9362 pars.imsi := omit;
9363
9364 f_init(1, true);
9365 f_sleep(1.0);
9366
9367 f_vty_allow_emerg_msc(true);
9368 f_vty_allow_emerg_bts(true, 0);
9369 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
9370 vc_conn.done;
9371 f_shutdown_helper();
9372}
9373
Philipp Maier783681c2020-07-16 16:47:06 +02009374/* EMERGENCY CALL situation #2, forbidden globally but allowed by BTS */
9375testcase TC_assignment_emerg_setup_deny_msc() runs on test_CT {
9376 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9377 var MSC_ConnHdlr vc_conn;
9378
9379 f_init(1, true);
9380 f_sleep(1.0);
9381
9382 f_vty_allow_emerg_msc(false);
9383 f_vty_allow_emerg_bts(true, 0);
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009384 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx): */
9385 pars.ra := f_rnd_ra_emerg();
Philipp Maier783681c2020-07-16 16:47:06 +02009386 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9387 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009388 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009389}
9390
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009391/* EMERGENCY CALL situation #3, allowed globally but forbidden by BTS.
9392 * The RACH req (and hence CHAN RQD) indicate other than emergency call.
9393 * Hence BSC only learns about it being an emergency call later during call setup.
9394 * If interested in the ra="emergency call" + deny bts policy case,
9395 * see TC_chan_rqd_emerg_deny.
9396 */
Philipp Maier783681c2020-07-16 16:47:06 +02009397testcase TC_assignment_emerg_setup_deny_bts() runs on test_CT {
9398 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9399 var MSC_ConnHdlr vc_conn;
9400
9401 /* Note: This simulates a spec violation by the MS, correct MS
9402 * implementations would not try to establish an emergency call because
9403 * the system information tells in advance that emergency calls are
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009404 * not allowed */
Philipp Maier783681c2020-07-16 16:47:06 +02009405
9406 f_init(1, true);
9407 f_sleep(1.0);
9408
9409 f_vty_allow_emerg_msc(true);
9410 f_vty_allow_emerg_bts(false, 0);
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009411 /* Note: Here we implicitly leave default g_pars.ra which is different than "emergency call" */
Philipp Maier783681c2020-07-16 16:47:06 +02009412 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9413 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009414 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009415}
9416
Philipp Maier82812002020-08-13 18:48:27 +02009417/* Test what happens when an emergency call arrives while all TCH channels are
9418 * busy, the BSC is expected to terminate one call in favor of the incoming
9419 * emergency call */
9420testcase TC_emerg_premption() runs on test_CT {
9421 var ASP_RSL_Unitdata rsl_ud;
9422 var integer i;
9423 var integer chreq_total, chreq_nochan;
9424 var RSL_Message rx_rsl;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009425 var octetstring l3_payload := gen_l3_valid_payload();
Philipp Maier82812002020-08-13 18:48:27 +02009426
9427 f_init(1);
9428 f_sleep(1.0);
9429
9430 f_vty_allow_emerg_msc(true);
9431 f_vty_allow_emerg_bts(true, 0);
9432
9433 /* Fill up all channels on the BTS */
9434 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
9435 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
9436 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 +02009437 f_chreq_act_ack('33'O, i);
Philipp Maier82812002020-08-13 18:48:27 +02009438 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009439 IPA_RSL[0][0].clear;
Philipp Maier82812002020-08-13 18:48:27 +02009440 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
9441 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
9442
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009443 /* Send EST IND for the first TCH, so we get to test the RR release cause */
9444 var RslChannelNr first_tch := valueof(t_RslChanNr_Bm(1));
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009445 f_ipa_tx(ts_RSL_EST_IND(first_tch, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009446
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009447 /* Accept BSSAP conn, so we get to test the Clear Request cause */
9448 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009449 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009450 var integer sccp_conn_id := rx_c_ind.connectionId;
9451 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
9452
Philipp Maier82812002020-08-13 18:48:27 +02009453 /* Send Channel request for emegergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009454 f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
Philipp Maier82812002020-08-13 18:48:27 +02009455
9456 /* Expect the BSC to release one (the first) TCH/F on the BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009457 f_expect_chan_rel(first_tch, expect_rr_chan_rel := true, expect_rll_rel_req := false,
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009458 expect_rr_cause := GSM48_RR_CAUSE_PREMPTIVE_REL);
Philipp Maier82812002020-08-13 18:48:27 +02009459
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009460 /* Also expect a BSSMAP Clear Request with PREEMPTION */
9461 var BSSAP_N_DATA_ind rx_clear_req;
9462 const myBSSMAP_Cause preemption := GSM0808_CAUSE_PREEMPTION;
9463 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_clear_req;
9464 log("XXX ", rx_clear_req);
9465 if (rx_clear_req.userData.pdu.bssmap.clearRequest.cause.causeValue != int2bit(enum2int(preemption), 7)) {
9466 setverdict(fail, "BSSMAP Clear Request: expected cause PREEMPTION");
9467 }
9468
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009469 /* Expect the BSC to send activate/assign the channel for the emergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009470 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009471 if (first_tch != rx_rsl.ies[0].body.chan_nr) {
9472 setverdict(fail, "different TCH lchan activated than expected");
9473 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009474 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(first_tch, 33));
9475 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Philipp Maier104f4c02020-09-11 18:12:18 +02009476
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009477 /* complete the BSSMAP Clear to satisfy the conn leak check */
9478 BSSAP.send(ts_BSSAP_DATA_req(sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(preemption))));
9479 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearComplete)) {
9480 BSSAP.send(ts_BSSAP_DISC_req(sccp_conn_id, 0));
9481 }
9482
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009483 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009484}
9485
9486/* Hopping parameters per a timeslot */
Vadim Yanitskiybc6654a2020-09-13 01:27:40 +07009487private type record length(0..64) of GsmArfcn ArfcnList;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009488private type record FHParamsTs {
9489 boolean enabled,
9490 uint6_t hsn,
9491 uint6_t maio,
9492 ArfcnList ma
9493};
9494
9495/* Hopping parameters per a transceiver */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009496private type record FHParamsTrx {
Philipp Maier798d8952021-10-19 14:43:19 +02009497 GsmBandArfcn arfcn,
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009498 FHParamsTs ts[8]
9499};
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009500
9501/* Randomly generate the hopping parameters for the given timeslot numbers */
9502private function f_TC_fh_params_gen(template integer tr_tn := (1, 3, 5))
9503runs on test_CT return FHParamsTrx {
9504 var FHParamsTrx fhp;
9505
Philipp Maier798d8952021-10-19 14:43:19 +02009506 /* Generate a random ARFCN in the range of 0 - 3. This ARFCN will
9507 * fall in the GSM900 band. */
9508 fhp.arfcn.arfcn := f_rnd_int(3);
9509 fhp.arfcn.pcs := false;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009510
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009511 for (var integer tn := 0; tn < 8; tn := tn + 1) {
9512 if (not match(tn, tr_tn)) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009513 fhp.ts[tn].enabled := false;
9514 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009515 continue;
9516 }
9517
9518 /* Random HSN / MAIO values: 0..63 */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009519 fhp.ts[tn].hsn := f_rnd_int(64);
9520 fhp.ts[tn].maio := f_rnd_int(64);
9521 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009522
9523 /* Random Mobile Allocation (hopping channels) */
9524 var integer ma_len := 2 + f_rnd_int(9); /* 2..10 channels */
9525 var integer step := 3 + f_rnd_int(4); /* 3..6 stepping */
9526 for (var integer i := 1; i <= ma_len; i := i + 1) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009527 fhp.ts[tn].ma := fhp.ts[tn].ma & { i * step };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009528 }
9529
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009530 fhp.ts[tn].enabled := true;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009531 }
9532
9533 log("f_TC_fh_params_gen(): ", fhp);
9534 return fhp;
9535}
9536
9537/* Make sure that the given Channel Description IE matches the hopping configuration */
9538private function f_TC_fh_params_match_chan_desc(in FHParamsTrx fhp, in ChannelDescription cd)
9539{
9540 var template (present) ChannelDescription tr_cd;
9541 var template (present) MaioHsn tr_maio_hsn;
9542 var uint3_t tn := cd.chan_nr.tn;
9543
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009544 if (fhp.ts[tn].enabled) {
9545 tr_maio_hsn := tr_HsnMaio(fhp.ts[tn].hsn, fhp.ts[tn].maio);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009546 tr_cd := tr_ChanDescH1(cd.chan_nr, tr_maio_hsn);
9547 } else {
Philipp Maier798d8952021-10-19 14:43:19 +02009548 tr_cd := tr_ChanDescH0(cd.chan_nr, fhp.arfcn.arfcn);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009549 }
9550
9551 if (not match(cd, tr_cd)) {
9552 setverdict(fail, "Channel Description IE does not match: ",
9553 cd, " vs expected ", tr_cd);
9554 }
9555}
9556
9557/* Make sure that the given Mobile Allocation IE matches the hopping configuration */
9558private function f_TC_fh_params_match_ma(in FHParamsTrx fhp, uint3_t tn,
9559 in MobileAllocationLV ma)
9560{
9561 var template MobileAllocationLV tr_ma := f_TC_fh_params_gen_tr_ma(fhp, tn, ma);
9562
9563 if (not match(ma, tr_ma)) {
9564 setverdict(fail, "Mobile Allocation IE does not match (tn := ",
9565 tn, "): ", ma, " vs expected: ", tr_ma);
9566 } else {
9567 setverdict(pass);
9568 }
9569}
9570
9571private function f_TC_fh_params_gen_tr_ma(in FHParamsTrx fhp, uint3_t tn,
9572 in MobileAllocationLV ma)
9573return template MobileAllocationLV {
9574 /* Mobile Allocation IE is expected to be empty if hopping is not enabled */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009575 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009576 return { len := 0, ma := ''B };
9577 }
9578
9579 var bitstring full_mask := f_pad_bit(''B, 1024, '0'B);
9580 var bitstring slot_mask := f_pad_bit(''B, 1024, '0'B);
9581 var bitstring ma_mask := ''B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009582
9583 /* Compose the full bit-mask (all channels, up to 1024 entries) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009584 for (var integer i := 0; i < lengthof(fhp.ts); i := i + 1) {
9585 for (var integer j := 0; j < lengthof(fhp.ts[i].ma); j := j + 1) {
9586 if (full_mask[fhp.ts[i].ma[j]] == '1'B)
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009587 { continue; }
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009588 full_mask[fhp.ts[i].ma[j]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009589 }
9590 }
9591
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009592 /* Take ARFCN of the TRX itself into account */
Philipp Maier798d8952021-10-19 14:43:19 +02009593 full_mask[fhp.arfcn.arfcn] := '1'B;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009594
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009595 /* Compose a bit-mask for the given timeslot number */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009596 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9597 slot_mask[fhp.ts[tn].ma[i]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009598 }
9599
9600 /* Finally, compose the Mobile Allocation bit-mask */
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009601 for (var integer i := 1; i < lengthof(full_mask); i := i + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009602 if (full_mask[i] != '1'B)
9603 { continue; }
9604
9605 /* FIXME: ma_mask := ma_mask & slot_mask[i]; // triggers a bug in TITAN */
9606 if (slot_mask[i] == '1'B) {
9607 ma_mask := ma_mask & '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009608 } else {
9609 ma_mask := ma_mask & '0'B;
9610 }
9611 }
9612
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009613 /* ARFCN 0 (if present) goes to the last position of the bit-mask */
9614 if (full_mask[0] == '1'B) {
9615 /* FIXME: ma_mask := ma_mask & slot_mask[0]; // triggers a bug in TITAN */
9616 if (slot_mask[0] == '1'B) {
9617 ma_mask := ma_mask & '1'B;
9618 } else {
9619 ma_mask := ma_mask & '0'B;
9620 }
9621 }
9622
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009623 /* Ensure that ma_mask is octet-aligned */
Vadim Yanitskiy2aa02522020-09-06 14:05:23 +07009624 var integer ma_mask_len := (lengthof(ma_mask) + 8 - 1) / 8;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009625 ma_mask := f_pad_bit(ma_mask, ma_mask_len * 8, '0'B);
9626
9627 return { len := ma_mask_len, ma := ma_mask };
9628}
9629
Philipp Maier798d8952021-10-19 14:43:19 +02009630/* Configure the appropriate band for a given arfcn, exc */
9631private function f_TC_set_band_by_arfcn(integer bts_nr, GsmBandArfcn arfcn) runs on test_CT
9632{
9633 var charstring band;
9634 var GsmBandArfcn arfcn_ := valueof(ts_GsmBandArfcn(arfcn.arfcn, arfcn.pcs, false));
9635
9636 select (arfcn_) {
9637 case (tr_GsmBandArfcn((259..293), false, ?)) { band := "GSM450"; }
9638 case (tr_GsmBandArfcn((306..340), false, ?)) { band := "GSM480"; }
9639 case (tr_GsmBandArfcn((438..511), false, ?)) { band := "GSM750"; }
9640 case (tr_GsmBandArfcn((128..251), false, ?)) { band := "GSM850"; }
9641 case (tr_GsmBandArfcn((0..124), false, ?)) { band := "GSM900"; }
9642 case (tr_GsmBandArfcn((955..1023), false, ?)) { band := "GSM900"; }
9643 case (tr_GsmBandArfcn((512..885), false, ?)) { band := "DCS1800"; }
9644 case (tr_GsmBandArfcn((512..810), true, ?)) { band := "PCS1900"; }
9645 case else { return; }
9646 }
9647
9648 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9649 f_vty_transceive(BSCVTY, "band " & band);
9650 f_vty_transceive(BSCVTY, "end");
9651}
9652
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009653/* Configure the hopping parameters in accordance with the given record */
9654private function f_TC_fh_params_set(in FHParamsTrx fhp,
9655 uint8_t bts_nr := 0,
9656 uint8_t trx_nr := 0)
9657runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009658
9659 f_TC_set_band_by_arfcn(bts_nr, fhp.arfcn);
9660
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009661 /* Enter the configuration node for the given BTS/TRX numbers */
9662 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9663
Philipp Maier798d8952021-10-19 14:43:19 +02009664 f_vty_transceive(BSCVTY, "arfcn " & int2str(fhp.arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009665
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009666 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009667 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9668
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009669 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009670 f_vty_transceive(BSCVTY, "hopping enabled 0");
9671 f_vty_transceive(BSCVTY, "exit"); /* go back */
9672 continue;
9673 }
9674
9675 /* Configure HSN / MAIO values */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009676 f_vty_transceive(BSCVTY, "hopping sequence-number " & int2str(fhp.ts[tn].hsn));
9677 f_vty_transceive(BSCVTY, "hopping maio " & int2str(fhp.ts[tn].maio));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009678
9679 /* Configure the Mobile Allocation (hopping channels) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009680 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9681 f_vty_transceive(BSCVTY, "hopping arfcn add " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009682 }
9683
9684 f_vty_transceive(BSCVTY, "hopping enabled 1");
9685 f_vty_transceive(BSCVTY, "exit"); /* go back */
9686 }
9687
9688 f_vty_transceive(BSCVTY, "end");
9689}
9690
9691/* Disable frequency hopping on all timeslots */
9692private function f_TC_fh_params_unset(in FHParamsTrx fhp,
9693 uint8_t bts_nr := 0,
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009694 uint8_t trx_nr := 0,
Philipp Maier798d8952021-10-19 14:43:19 +02009695 GsmBandArfcn arfcn := {pcs := false, arfcn := 871})
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009696runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009697
9698 f_TC_set_band_by_arfcn(bts_nr, arfcn);
9699
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009700 /* Enter the configuration node for the given BTS/TRX numbers */
9701 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9702
Philipp Maier798d8952021-10-19 14:43:19 +02009703 f_vty_transceive(BSCVTY, "arfcn " & int2str(arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009704
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009705 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009706 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9707
9708 /* Delete all ARFCNs from the Mobile Allocation (if any) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009709 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9710 f_vty_transceive(BSCVTY, "hopping arfcn del " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009711 }
9712
9713 f_vty_transceive(BSCVTY, "hopping enabled 0");
9714 f_vty_transceive(BSCVTY, "exit"); /* go back */
9715 }
9716
9717 f_vty_transceive(BSCVTY, "end");
9718 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9719}
9720
9721/* Verify presence and correctness of the hopping parameters (HSN, MAIO)
9722 * in the Channel Identification IE of the RSL CHANnel ACTIVation message. */
9723testcase TC_fh_params_chan_activ() runs on test_CT {
9724 var FHParamsTrx fhp := f_TC_fh_params_gen();
9725 var RSL_Message rsl_msg;
9726 var RSL_IE_Body ie;
9727
9728 f_init_vty();
9729
9730 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9731 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9732
9733 f_init(1);
9734
9735 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9736 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009737 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9738 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009739
9740 /* Make sure that Channel Identification IE is present */
9741 if (not f_rsl_find_ie(rsl_msg, RSL_IE_CHAN_IDENT, ie)) {
9742 setverdict(fail, "RSL Channel Identification IE is absent");
9743 continue;
9744 }
9745
9746 /* Make sure that hopping parameters (HSN/MAIO) match */
9747 f_TC_fh_params_match_chan_desc(fhp, ie.chan_ident.ch_desc.v);
9748
9749 /* "Mobile Allocation shall be included but empty" - let's check this */
9750 if (ie.chan_ident.ma.v.len != 0) {
9751 setverdict(fail, "Mobile Allocation IE is not empty: ",
9752 ie.chan_ident.ma, ", despite it shall be");
9753 continue;
9754 }
9755 }
9756
9757 /* Disable frequency hopping */
9758 f_TC_fh_params_unset(fhp);
9759
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009760 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009761}
9762
9763/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Immediate Assignment */
9764testcase TC_fh_params_imm_ass() runs on test_CT {
9765 var FHParamsTrx fhp := f_TC_fh_params_gen();
9766 var RSL_Message rsl_msg;
9767 var RSL_IE_Body ie;
9768
9769 f_init_vty();
9770
9771 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9772 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9773
9774 f_init(1);
9775
9776 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9777 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009778 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9779 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009780
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009781 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9782 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009783
9784 /* Make sure that Full Immediate Assign Info IE is present */
9785 if (not f_rsl_find_ie(rsl_msg, RSL_IE_FULL_IMM_ASS_INFO, ie)) {
9786 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
9787 continue;
9788 }
9789
9790 /* Decode the actual Immediate Assignment message */
9791 var GsmRrMessage rr_msg := dec_GsmRrMessage(ie.full_imm_ass_info.payload);
9792 if (not match(rr_msg.header, t_RrHeader(IMMEDIATE_ASSIGNMENT, ?))) {
9793 setverdict(fail, "Failed to match Immediate Assignment: ", rr_msg);
9794 continue;
9795 }
9796
9797 /* Make sure that hopping parameters (HSN/MAIO) match */
9798 f_TC_fh_params_match_chan_desc(fhp, rr_msg.payload.imm_ass.chan_desc);
9799
9800 /* Make sure that the Mobile Allocation IE matches */
9801 f_TC_fh_params_match_ma(fhp, rr_msg.payload.imm_ass.chan_desc.chan_nr.tn,
9802 rr_msg.payload.imm_ass.mobile_allocation);
9803 }
9804
9805 /* Disable frequency hopping */
9806 f_TC_fh_params_unset(fhp);
Philipp Maier82812002020-08-13 18:48:27 +02009807
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009808 f_shutdown_helper();
Philipp Maier82812002020-08-13 18:48:27 +02009809}
9810
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009811/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Assignment Command */
9812testcase TC_fh_params_assignment_cmd() runs on test_CT {
9813 var FHParamsTrx fhp := f_TC_fh_params_gen();
9814 var RSL_Message rsl_msg;
9815 var RSL_IE_Body ie;
9816
9817 f_init_vty();
9818
9819 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9820 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9821
9822 f_init(1);
9823
9824 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02009825 vc_MGCP[0].stop;
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009826
9827 var template PDU_BSSAP ass_cmd := f_gen_ass_req();
9828 ass_cmd.pdu.bssmap.assignmentRequest.codecList := ts_BSSMAP_IE_CodecList({ts_CodecFR});
9829
9830 /* CS domain (TCH): 4 (TCH/F) + 2 (TCH/H) channels available
9831 * NOTE: only 3 SDCCH/4 channels are available on CCCH+SDCCH4+CBCH */
9832 for (var integer i := 0; i < 3; i := i + 1) {
9833 /* Establish a dedicated channel, so we can trigger (late) TCH assignment */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009834 var DchanTuple dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009835
9836 /* Send a BSSMAP Assignment Command, expect CHANnel ACTIVation */
9837 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009838 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009839
9840 /* ACKnowledge CHANnel ACTIVation, expect RSL DATA REQuest */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009841 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9842 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009843
9844 /* Make sure that L3 Information IE is present */
9845 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
9846 setverdict(fail, "RSL L3 Information IE is absent");
9847 continue;
9848 }
9849
9850 /* Decode the L3 message and make sure it is (RR) Assignment Command */
9851 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
9852 if (not match(l3_msg.header, t_RrL3Header(ASSIGNMENT_COMMAND))) {
9853 setverdict(fail, "Failed to match Assignment Command: ", l3_msg);
9854 continue;
9855 }
9856
9857 /* Make sure that hopping parameters (HSN/MAIO) match */
9858 var ChannelDescription chan_desc := l3_msg.payload.ass_cmd.chan_desc;
9859 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9860
9861 /* Make sure that Cell Channel Description IE is present if FH is enabled */
9862 if (chan_desc.h and not ispresent(l3_msg.payload.ass_cmd.cell_chan_desc)) {
Vadim Yanitskiy38d069d2020-09-02 17:18:57 +07009863 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009864 continue;
9865 }
9866
9867 /* Make sure that the Mobile Allocation IE matches (if present) */
9868 var boolean ma_present := ispresent(l3_msg.payload.ass_cmd.mobile_allocation);
9869 if (chan_desc.h and ma_present) {
9870 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
9871 l3_msg.payload.ass_cmd.mobile_allocation.v);
9872 } else if (chan_desc.h and not ma_present) {
9873 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
9874 continue;
9875 } else if (not chan_desc.h and ma_present) {
9876 setverdict(fail, "FH disabled, but Mobile Allocation IE is present");
9877 continue;
9878 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009879
9880 f_perform_clear_test_ct(dt);
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009881 }
9882
9883 /* Give the IUT some time to release all channels */
9884 f_sleep(3.0);
9885
9886 /* Disable frequency hopping */
9887 f_TC_fh_params_unset(fhp);
9888
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009889 f_shutdown_helper();
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009890}
9891
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009892/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Handover Command */
9893private function f_TC_fh_params_handover_cmd(in FHParamsTrx fhp)
9894runs on test_CT {
9895 var RSL_Message rsl_msg;
9896 var RSL_IE_Body ie;
9897 var DchanTuple dt;
9898
9899 /* Establish a dedicated channel, so we can trigger handover */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009900 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiyc18ff472021-11-18 20:15:37 +03009901 f_sleep(0.5);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009902
9903 /* Trigger handover from BTS0 to BTS1 */
9904 f_bts_0_cfg(BSCVTY, { "neighbor bts 1" });
9905 f_vty_handover(BSCVTY, 0, 0, dt.rsl_chan_nr, 1);
9906
9907 /* Expect RSL CHANnel ACTIVation on BTS1/TRX0/TS1 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009908 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx := {1, 0});
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009909
9910 /* ACKnowledge channel activation and expect (RR) Handover Command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009911 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33), idx := {1, 0});
9912 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009913
9914 /* Make sure that L3 Information IE is present */
9915 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
9916 setverdict(fail, "RSL L3 Information IE is absent");
9917 return;
9918 }
9919
9920 /* Decode the L3 message and make sure it is (RR) Handover Command */
9921 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
9922 if (not match(l3_msg.header, t_RrL3Header(HANDOVER_COMMAND))) {
9923 setverdict(fail, "Failed to match Handover Command: ", l3_msg);
9924 return;
9925 }
9926
9927 /* Make sure that we've got SDCCH/8 on TS1 (expected to be hopping) */
9928 var ChannelDescription chan_desc := l3_msg.payload.ho_cmd.chan_desc;
9929 if (not match(chan_desc.chan_nr, t_RslChanNr_SDCCH8(1, ?))) {
9930 setverdict(fail, "Unexpected channel number: ", chan_desc.chan_nr);
9931 return;
9932 }
9933
9934 /* Make sure that hopping parameters (HSN/MAIO) match */
9935 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9936
9937 /* Make sure that Cell Channel Description IE is present */
9938 if (not ispresent(l3_msg.payload.ho_cmd.cell_chan_desc)) {
9939 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
9940 return;
9941 }
9942
9943 /* Make sure that the Mobile Allocation (after time) IE is present and matches */
9944 var boolean ma_present := ispresent(l3_msg.payload.ho_cmd.mobile_allocation);
9945 if (ma_present) {
9946 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
9947 l3_msg.payload.ho_cmd.mobile_allocation.v);
9948 } else {
9949 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
9950 return;
9951 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009952
9953 f_perform_clear_test_ct(dt);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009954}
9955testcase TC_fh_params_handover_cmd() runs on test_CT {
9956 var FHParamsTrx fhp := f_TC_fh_params_gen();
9957
9958 f_init_vty();
9959
9960 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8 on BTS1/TRX0 */
9961 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
9962
9963 f_vty_transceive(BSCVTY, "timeslot 0");
9964 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
9965 f_vty_transceive(BSCVTY, "exit"); /* go back */
9966
9967 f_vty_transceive(BSCVTY, "timeslot 1");
9968 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8");
9969 f_vty_transceive(BSCVTY, "end"); /* we're done */
9970
9971 f_TC_fh_params_set(fhp, 1); /* Enable frequency hopping on BTS1 */
9972 f_vty_transceive(BSCVTY, "drop bts connection 1 oml");
9973
9974 f_init(2);
9975
9976 f_TC_fh_params_handover_cmd(fhp);
9977
9978 /* Disable frequency hopping on BTS1 */
9979 f_TC_fh_params_unset(fhp, 1);
9980
9981 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
9982 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
9983
9984 f_vty_transceive(BSCVTY, "timeslot 0");
9985 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
9986 f_vty_transceive(BSCVTY, "exit"); /* go back */
9987
9988 f_vty_transceive(BSCVTY, "timeslot 1");
9989 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
9990 f_vty_transceive(BSCVTY, "end"); /* we're done */
9991
9992 f_shutdown_helper();
9993}
9994
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009995/* Verify the hopping parameters in System Information Type 4 */
9996testcase TC_fh_params_si4_cbch() runs on test_CT {
9997 var FHParamsTrx fhp := f_TC_fh_params_gen(tr_tn := 1);
9998 var ASP_RSL_Unitdata rx_rsl_ud;
9999 timer T := 5.0;
10000
10001 f_init_vty();
10002
10003 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8+CBCH */
10004 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
10005
10006 f_vty_transceive(BSCVTY, "timeslot 0");
10007 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
10008 f_vty_transceive(BSCVTY, "exit"); /* go back */
10009
10010 f_vty_transceive(BSCVTY, "timeslot 1");
10011 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8+cbch");
10012 f_vty_transceive(BSCVTY, "end"); /* we're done */
10013
10014 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
10015 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
10016
10017 f_init(1);
10018
10019 T.start;
10020 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010021 [] 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 +070010022 var RSL_IE_Body ie := rx_rsl_ud.rsl.ies[2].body; /* FULL BCCH Information IE */
10023 var SystemInformation si := dec_SystemInformation(ie.other.payload);
10024
10025 /* Make sure that what we decoded is System Information Type 4 */
10026 if (si.header.message_type != SYSTEM_INFORMATION_TYPE_4) {
10027 setverdict(fail, "RSL FULL BCCH Information IE contains: ", si);
10028 repeat;
10029 }
10030
10031 /* Make sure that CBCH Channel Description IE is present */
10032 if (not ispresent(si.payload.si4.cbch_chan_desc)) {
10033 setverdict(fail, "CBCH Channel Description IE is absent");
10034 break;
10035 }
10036
10037 /* Finally, check the hopping parameters (HSN, MAIO) */
10038 var ChannelDescription chan_desc := si.payload.si4.cbch_chan_desc.v;
10039 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
10040
10041 /* 3GPP TS 44.018, section 9.1.36.2 "CBCH Mobile Allocation":
10042 * The CBCH Mobile Allocation IE *shall* be present if FH is enabled. */
10043 if (chan_desc.h and not ispresent(si.payload.si4.cbch_mobile_alloc)) {
10044 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
10045 break;
10046 } else if (chan_desc.h and ispresent(si.payload.si4.cbch_mobile_alloc)) {
10047 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
10048 si.payload.si4.cbch_mobile_alloc.v);
10049 }
10050 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010051 [] IPA_RSL[0][0].receive { repeat; }
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010052 [] T.timeout {
10053 setverdict(fail, "Timeout waiting for RSL BCCH INFOrmation (SI4)");
10054 }
10055 }
10056
10057 /* Disable frequency hopping */
10058 f_TC_fh_params_unset(fhp);
10059
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +070010060 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010061 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
10062
10063 f_vty_transceive(BSCVTY, "timeslot 0");
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +070010064 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010065 f_vty_transceive(BSCVTY, "exit"); /* go back */
10066
10067 f_vty_transceive(BSCVTY, "timeslot 1");
10068 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
10069 f_vty_transceive(BSCVTY, "end"); /* we're done */
10070
Vadim Yanitskiy21726312020-09-04 01:45:36 +070010071 f_shutdown_helper();
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010072}
10073
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010074template (value) PDU_BSSAP_LE ts_BSSMAP_LE_BSSLAP(template (value) BSSLAP_PDU bsslap)
10075 := ts_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, data := enc_BSSLAP_PDU(valueof(bsslap)));
10076
10077private function f_match_bsslap(PDU_BSSAP_LE got_bsslap_msg,
10078 template (present) BSSLAP_PDU expect_bsslap)
10079{
10080 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(got_bsslap_msg.pdu.bssmap.co_info.bsslap_apdu.data);
10081 if (not match(bsslap, expect_bsslap)) {
10082 log("EXPECTING BSSLAP: ", expect_bsslap);
10083 log("GOT BSSLAP: ", bsslap);
10084 setverdict(fail, "BSSLAP is not as expected");
10085 mtc.stop;
10086 }
10087 setverdict(pass);
10088}
10089
10090/* GAD: this is an Ellipsoid point with uncertainty circle, encoded as in 3GPP TS 23.032 §7.3.2. */
10091const octetstring gad_ell_point_unc_circle := '10b0646d0d5f6627'O;
10092
10093private function f_expect_bsslap(template (present) BSSLAP_PDU expect_rx_bsslap) runs on MSC_ConnHdlr {
10094 var PDU_BSSAP_LE rx_bsslap;
10095 BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap);
10096 f_match_bsslap(rx_bsslap, expect_rx_bsslap);
10097}
10098
10099/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10100 * Request on Lb interface. Either with or without the SMLC doing a BSSLAP TA Request. */
10101private function f_lcs_loc_req_for_active_ms(boolean do_ta_request := false) runs on MSC_ConnHdlr {
10102 f_sleep(1.0);
10103
10104 f_establish_fully(omit, omit);
10105 f_bssap_le_register_imsi(g_pars.imsi, omit);
10106
10107 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10108 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10109
10110 var PDU_BSSAP_LE plr;
10111 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10112
10113 if (not do_ta_request) {
10114 /* verify TA Layer 3 in APDU. First the APDU type (BSSLAP), then the BSSLAP data contents. */
10115 var template BSSMAP_LE_IE_APDU expect_apdu := tr_BSSMAP_LE_APDU(BSSMAP_LE_PROT_BSSLAP, ?);
10116 if (not match(plr.pdu.bssmap.perf_loc_req.bsslap_apdu, expect_apdu)) {
10117 log("EXPECTING BSSMAP-LE APDU IE ", expect_apdu);
10118 log("GOT BSSMAP-LE APDU IE ", plr.pdu.bssmap.perf_loc_req.bsslap_apdu);
10119 setverdict(fail, "BSSMAP-LE APDU IE is not as expected");
10120 mtc.stop;
10121 }
10122 var template BSSLAP_PDU expect_ta_layer3 := tr_BSSLAP_TA_Layer3(tr_BSSLAP_IE_TA(0));
10123 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(plr.pdu.bssmap.perf_loc_req.bsslap_apdu.data);
10124 if (not match(bsslap, expect_ta_layer3)) {
10125 log("EXPECTING BSSLAP TA Layer 3: ", expect_ta_layer3);
10126 log("GOT BSSLAP: ", bsslap);
10127 setverdict(fail, "BSSLAP is not as expected");
10128 mtc.stop;
10129 }
10130 /* OsmoBSC directly sent the TA as BSSLAP APDU in the BSSMAP-LE Perform Location Request to the SMLC. The SMLC
10131 * has no need to request the TA from the BSC and directly responds. */
10132 } else {
10133 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10134 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10135 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10136 }
10137
10138 /* SMLC got the TA from the BSC, now responds with geo information data. */
10139 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10140 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10141 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10142
10143 /* The LCS was using an active A-interface conn. It should still remain active after this. */
10144 f_mo_l3_transceive();
10145
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010146 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010147
10148 f_sleep(2.0);
10149 setverdict(pass);
10150}
10151
10152/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10153 * Request on Lb interface. Without the SMLC doing a BSSLAP TA Request. */
10154private function f_tc_lcs_loc_req_for_active_ms(charstring id) runs on MSC_ConnHdlr {
10155 f_lcs_loc_req_for_active_ms(false);
10156}
10157testcase TC_lcs_loc_req_for_active_ms() runs on test_CT {
10158 var MSC_ConnHdlr vc_conn;
10159 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10160
10161 f_init(1, true);
10162 f_sleep(1.0);
10163 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms), pars);
10164 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010165 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010166}
10167
10168/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10169 * Request on Lb interface. With the SMLC doing a BSSLAP TA Request. */
10170private function f_tc_lcs_loc_req_for_active_ms_ta_req(charstring id) runs on MSC_ConnHdlr {
10171 f_lcs_loc_req_for_active_ms(true);
10172}
10173testcase TC_lcs_loc_req_for_active_ms_ta_req() runs on test_CT {
10174 var MSC_ConnHdlr vc_conn;
10175 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10176
10177 f_init(1, true);
10178 f_sleep(1.0);
10179 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_ta_req), pars);
10180 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010181 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010182}
10183
10184/* Clear the A-interface conn only, without doing anything on Abis. Useful for LCS, for cases where there is only an A
10185 * conn without an active lchan. */
10186private function f_clear_A_conn() runs on MSC_ConnHdlr
10187{
10188 var BssmapCause cause := 0;
10189 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
10190 BSSAP.receive(tr_BSSMAP_ClearComplete);
10191 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
10192
10193 timer no_more_bssap := 5.0;
10194 no_more_bssap.start;
10195 alt {
10196 [] no_more_bssap.timeout { break; }
10197 [] BSSAP.receive(tr_BSSAP_BSSMAP) {
10198 setverdict(fail, "Expected no more BSSAP after Clear Complete");
10199 mtc.stop;
10200 }
10201 }
10202 setverdict(pass);
10203}
10204
10205/* Verify that the A-interface connection is still working, and then clear it, without doing anything on Abis. Useful
10206 * for LCS, for cases where there is only an A conn without an active lchan. */
10207private function f_verify_active_A_conn_and_clear() runs on MSC_ConnHdlr
10208{
10209 f_logp(BSCVTY, "f_verify_active_A_conn_and_clear: test A link, then clear");
10210
10211 /* When an lchan is active, we can send some L3 data from the BTS side and verify that it shows up on the other
10212 * side towards the MSC. When there is no lchan, this is not possible. To probe whether the A-interface
10213 * connection is still up, we need something that echos back on the A-interface. Another LCS request! */
10214 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10215 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10216 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10217
10218 /* Right, the Perform Location Request showed up on Lb, now we can clear the A conn. */
10219 f_clear_A_conn();
10220 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10221 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10222}
10223
10224/* With *no* active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10225 * Request on Lb interface. BSC will Page for the subscriber as soon as we (virtual SMLC) request the TA via BSSLAP.
10226 */
10227private function f_tc_lcs_loc_req_for_idle_ms(charstring id) runs on MSC_ConnHdlr {
10228 f_sleep(1.0);
10229
10230 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10231 f_bssap_le_register_imsi(g_pars.imsi, omit);
10232
10233 /* Register to receive the Paging Command */
10234 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10235 g_chan_nr := new_chan_nr;
10236 f_rslem_register(0, g_chan_nr);
10237
10238 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10239 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10240 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10241 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10242
10243 var PDU_BSSAP_LE plr;
10244 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10245
10246 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10247 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10248
10249 /* OsmoBSC needs to Page */
10250 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi)));
10251 f_logp(BSCVTY, "got Paging Command");
10252
10253 /* MS requests channel. Since the Paging was for LCS, the Paging Response does not trigger a Complete Layer 3 to
10254 * the MSC, and releases the lchan directly. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010255 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(valueof(ts_MI_IMSI_LV(g_pars.imsi))), do_clear := false, expect_bssmap_l3 := false);
10256 f_expect_lchan_rel(RSL, RSL_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010257
10258 /* From the Paging Response, the TA is now known to the BSC, and it responds to the SMLC. */
10259
10260 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10261
10262 /* SMLC got the TA from the BSC, now responds with geo information data. */
10263 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10264 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10265
10266 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10267
10268 /* The lchan is gone, the A-interface conn was created for the LCS only.
10269 * Still it is clearly the MSC's job to decide whether to tear down the conn or not. */
10270 f_verify_active_A_conn_and_clear();
10271
10272 f_sleep(2.0);
10273 setverdict(pass);
10274}
10275testcase TC_lcs_loc_req_for_idle_ms() 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
10282 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10283 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10284
10285 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms), pars);
10286 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010287 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010288}
10289
10290/* With no active lchan, start BSSMAP Perform Location Request on A interface, but omit IMSI; expect failure response.
10291 */
10292private function f_tc_lcs_loc_req_no_subscriber(charstring id) runs on MSC_ConnHdlr {
10293 f_sleep(1.0);
10294
10295 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10296 f_bssap_le_register_imsi(g_pars.imsi, omit);
10297
10298 /* provoke an abort by omitting both IMSI and IMEI */
10299 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10300 valueof(ts_BSSMAP_Perform_Location_Request(omit,
10301 ts_CellId_CGI('262'H, '42'H, 23, 42)))));
10302 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10303
10304 /* BSC tells MSC about failure */
10305 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10306 locationEstimate := omit, positioningData := omit,
10307 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_DATA_MISSING_IN_REQ)));
10308
10309 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10310 f_verify_active_A_conn_and_clear();
10311
10312 f_sleep(2.0);
10313 setverdict(pass);
10314}
10315testcase TC_lcs_loc_req_no_subscriber() runs on test_CT {
10316 var MSC_ConnHdlr vc_conn;
10317 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10318
10319 f_init(1, true);
10320 f_sleep(1.0);
10321
10322 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10323 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10324
10325 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_no_subscriber), pars);
10326 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010327 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010328}
10329
10330/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10331 * BSSMAP-LE Perform Location Response (before or after sending a BSSLAP TA Request) */
10332private function f_lcs_loc_req_for_active_ms_le_timeout(boolean do_ta) runs on MSC_ConnHdlr {
10333 f_sleep(1.0);
10334
10335 f_establish_fully(omit, omit);
10336 f_bssap_le_register_imsi(g_pars.imsi, omit);
10337
10338 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10339 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10340
10341 var PDU_BSSAP_LE plr;
10342 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10343
10344 if (do_ta) {
10345 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10346 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10347 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10348 }
10349
10350 /* SMLC fails to respond, BSC runs into timeout */
10351 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_SYSTEM_FAILURE));
10352 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10353
10354 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10355 locationEstimate := omit, positioningData := omit,
10356 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_SYSTEM_FAILURE)));
10357
10358 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10359 f_verify_active_A_conn_and_clear();
10360
10361 f_sleep(2.0);
10362 setverdict(pass);
10363}
10364
10365/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10366 * BSSMAP-LE Perform Location Response, without sending a BSSLAP TA Request. */
10367private function f_tc_lcs_loc_req_for_active_ms_le_timeout(charstring id) runs on MSC_ConnHdlr {
10368 f_lcs_loc_req_for_active_ms_le_timeout(false);
10369}
10370
10371testcase TC_lcs_loc_req_for_active_ms_le_timeout() runs on test_CT {
10372 var MSC_ConnHdlr vc_conn;
10373 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10374
10375 f_init(1, true);
10376 f_sleep(1.0);
10377 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout), pars);
10378 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010379 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010380}
10381
10382/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10383 * BSSMAP-LE Perform Location Response, after sending a BSSLAP TA Request. */
10384private function f_tc_lcs_loc_req_for_active_ms_le_timeout2(charstring id) runs on MSC_ConnHdlr {
10385 f_lcs_loc_req_for_active_ms_le_timeout(true);
10386}
10387
10388testcase TC_lcs_loc_req_for_active_ms_le_timeout2() runs on test_CT {
10389 var MSC_ConnHdlr vc_conn;
10390 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10391
10392 f_init(1, true);
10393 f_sleep(1.0);
10394 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout2), pars);
10395 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010396 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010397}
10398
10399/* With *no* active lchan, start a Perform Location Request, expecting that the MS will be Paged. */
10400private function f_tc_lcs_loc_req_for_idle_ms_no_pag_resp(charstring id) runs on MSC_ConnHdlr {
10401 f_sleep(1.0);
10402
10403 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10404 f_bssap_le_register_imsi(g_pars.imsi, omit);
10405
10406 /* Register to receive the Paging Command */
10407 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10408 g_chan_nr := new_chan_nr;
10409 f_rslem_register(0, g_chan_nr);
10410
10411 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10412 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10413 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10414 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10415
10416 var PDU_BSSAP_LE plr;
10417 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10418
10419 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10420 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10421
10422 /* OsmoBSC needs to Page */
10423 var PDU_BSSAP_LE rx_bsslap;
10424 alt {
10425 [] RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi))) {
10426 f_logp(BSCVTY, "got Paging Command");
10427 repeat;
10428 }
10429 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10430 /* MS does not respond to Paging, TA Req runs into timeout. */
10431 f_match_bsslap(rx_bsslap, tr_BSSLAP_Abort(?));
10432 }
10433 }
10434
10435 /* SMLC responds with failure */
10436 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(omit, BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10437 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10438
10439 /* BSC tells MSC about failure */
10440 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10441 locationEstimate := omit, positioningData := omit,
10442 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_REQUEST_ABORTED)));
10443
10444 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10445 f_verify_active_A_conn_and_clear();
10446
10447 f_sleep(2.0);
10448 setverdict(pass);
10449}
10450testcase TC_lcs_loc_req_for_idle_ms_no_pag_resp() runs on test_CT {
10451 var MSC_ConnHdlr vc_conn;
10452 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10453
10454 f_init(1, true);
10455 f_sleep(1.0);
10456
10457 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10458 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10459
10460 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms_no_pag_resp), pars);
10461 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010462 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010463}
10464
10465/* During an ongoing Location Request, the MS sends a CM Service Request. Expect the same A-conn to be re-used / taken
10466 * over. */
10467private function f_tc_cm_service_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10468 f_sleep(1.0);
10469
10470 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10471 f_bssap_le_register_imsi(g_pars.imsi, omit);
10472
10473 /* Register to receive the Paging Command */
10474 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10475 g_chan_nr := new_chan_nr;
10476 f_rslem_register(0, g_chan_nr);
10477
10478 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10479 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10480 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10481 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10482
10483 var PDU_BSSAP_LE plr;
10484 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10485
10486 /* As the A-interface conn was established for LCS, the MS coincidentally decides to issue a CM Service Request
10487 * and establish Layer 3. It should use the existing A-interface conn. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010488 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 +020010489 do_clear := false, expect_bssmap_l3 := true);
10490
10491 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10492 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10493
10494 /* OsmoBSC already has an lchan, no need to Page, just returns the TA */
10495 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10496
10497 /* SMLC got the TA from the BSC, now responds with geo information data. */
10498 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10499 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10500 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10501
10502 /* The lchan should still exist, it was from a CM Service Request. */
10503 f_mo_l3_transceive();
10504
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010505 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010506
10507 f_sleep(2.0);
10508 setverdict(pass);
10509}
10510testcase TC_cm_service_during_lcs_loc_req() runs on test_CT {
10511 var MSC_ConnHdlr vc_conn;
10512 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10513
10514 f_init(1, true);
10515 f_sleep(1.0);
10516
10517 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10518 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10519
10520 vc_conn := f_start_handler(refers(f_tc_cm_service_during_lcs_loc_req), pars);
10521 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010522 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010523}
10524
10525/* During an ongoing Perform Location Request, do a Handover, an expect a BSSLAP Reset message from the BSC to indicate
10526 * the new lchan after handover. */
10527private function f_tc_ho_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10528 f_sleep(1.0);
10529
10530 f_establish_fully(omit, omit);
10531 f_bssap_le_register_imsi(g_pars.imsi, omit);
10532
10533 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10534 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10535
10536 var PDU_BSSAP_LE plr;
10537 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10538
10539 /* SMLC ponders the Location Request, in the meantime the BSC decides to handover */
10540 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
10541
10542 var HandoverState hs := {
10543 rr_ho_cmpl_seen := false,
10544 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +020010545 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010546 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010547 };
10548 /* issue hand-over command on VTY */
10549 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
10550 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
10551 f_rslem_suspend(RSL1_PROC);
10552
10553 /* From the MGW perspective, a handover is is characterized by
10554 * performing one MDCX operation with the MGW. So we expect to see
10555 * one more MDCX during handover. */
10556 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
10557
10558 alt {
10559 [] as_handover(hs);
10560 }
10561
10562 var PDU_BSSAP_LE rx_bsslap;
10563
10564 interleave {
10565 /* Expect the BSC to inform the MSC about the handover */
10566 [] BSSAP.receive(tr_BSSMAP_HandoverPerformed);
10567
10568 /* Expect the BSC to inform the SMLC about the handover */
10569 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10570 f_match_bsslap(rx_bsslap, tr_BSSLAP_Reset(BSSLAP_CAUSE_INTRA_BSS_HO));
10571 }
10572 }
10573
10574 /* SMLC now responds with geo information data. */
10575 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10576 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10577 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10578
10579 /* lchan still active */
10580 f_mo_l3_transceive(RSL1);
10581
10582 /* MSC decides it is done now. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010583 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010584
10585 f_sleep(2.0);
10586 setverdict(pass);
10587}
10588testcase TC_ho_during_lcs_loc_req() runs on test_CT {
10589 var MSC_ConnHdlr vc_conn;
10590 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10591
10592 f_init(2, true);
10593 f_sleep(1.0);
10594 vc_conn := f_start_handler(refers(f_tc_ho_during_lcs_loc_req), pars);
10595 vc_conn.done;
Oliver Smith39f53072022-10-27 14:44:04 +020010596 f_shutdown_helper(ho := true);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010597}
10598
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010599private function f_tc_emerg_call_and_lcs_loc_req(charstring id) runs on MSC_ConnHdlr
10600{
10601 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
10602 * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
10603 * another lchan. */
Pau Espin Pedrol1809bce2023-01-03 16:54:41 +010010604 g_pars.ra := f_rnd_ra_emerg();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010605 f_assignment_emerg_setup();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +010010606 f_assignment_emerg_setup_exp_bssap();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010607
10608 /* Here would usually be a CC Call Proceeding from the MSC, but what does the BSC care about DTAP. */
10609
10610 /* Do a Location Request in-between the CC call setup */
10611 f_bssap_le_register_imsi(g_pars.imsi, omit);
10612 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10613 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10614 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10615 /* SMLC got the TA from the BSC, now responds with geo information data. */
10616 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10617 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10618 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10619
Pau Espin Pedrol14076d32023-01-03 17:07:59 +010010620 f_assignment_emerg_setup_voice();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010621
10622 setverdict(pass);
10623 f_perform_clear();
10624}
10625
10626testcase TC_emerg_call_and_lcs_loc_req() runs on test_CT {
10627 var MSC_ConnHdlr vc_conn;
10628 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10629
10630 f_init(1, true);
10631 f_sleep(1.0);
10632 f_vty_allow_emerg_msc(true);
10633 f_vty_allow_emerg_bts(true, 0);
10634 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req), pars);
10635 vc_conn.done;
10636 f_shutdown_helper();
10637}
10638
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020010639private altstep no_bssmap_clear_req() runs on MSC_ConnHdlr {
10640 [] BSSAP.receive(tr_BSSMAP_ClearRequest) {
10641 setverdict(fail, "unexpected BSSMAP Clear Request");
10642 mtc.stop;
10643 }
10644}
10645
10646private type enumerated RslRel {
10647 RSLREL_REL_IND,
10648 RSLREL_CONN_FAIL
10649};
10650
10651private function f_emerg_call_and_lcs_loc_req_early_lchan_release(RslRel rsl_rel) runs on MSC_ConnHdlr
10652{
10653 g_pars.ra := f_rnd_ra_emerg();
10654 f_assignment_emerg_setup();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +010010655 f_assignment_emerg_setup_exp_bssap();
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020010656
10657 /* Start a Location Request to locate the emergency */
10658 f_bssap_le_register_imsi(g_pars.imsi, omit);
10659 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10660 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10661 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10662
10663 /* 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
10664 * do a Clear Command when the Location Response arrives. */
10665 activate(no_bssmap_clear_req());
10666
10667 /* the lchan gets interrupted while the Location Request has no response */
10668 select (rsl_rel) {
10669 case (RSLREL_REL_IND) {
10670 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
10671 f_expect_lchan_rel(RSL, RSL_PROC);
10672 }
10673 case (RSLREL_CONN_FAIL) {
10674 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
10675 }
10676 case else {
10677 setverdict(fail, "Unknown RslRel type");
10678 mtc.stop;
10679 }
10680 }
10681
10682 /* Still expect the Location Response to find its way to the MSC. */
10683 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10684 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10685 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10686
10687 setverdict(pass);
10688
10689 select (rsl_rel) {
10690 case (RSLREL_REL_IND) {
10691 f_perform_clear_no_lchan();
10692 }
10693 case (RSLREL_CONN_FAIL) {
10694 f_perform_clear();
10695 }
10696 }
10697}
10698
10699private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind(charstring id) runs on MSC_ConnHdlr
10700{
10701 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_REL_IND);
10702}
10703
10704testcase TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() runs on test_CT {
10705 var MSC_ConnHdlr vc_conn;
10706 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10707
10708 f_init(1, true);
10709 f_sleep(1.0);
10710 f_vty_allow_emerg_msc(true);
10711 f_vty_allow_emerg_bts(true, 0);
10712 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind), pars);
10713 vc_conn.done;
10714 f_shutdown_helper();
10715}
10716
10717private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail(charstring id) runs on MSC_ConnHdlr
10718{
10719 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_CONN_FAIL);
10720}
10721
10722testcase TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() runs on test_CT {
10723 var MSC_ConnHdlr vc_conn;
10724 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10725
10726 f_init(1, true);
10727 f_sleep(1.0);
10728 f_vty_allow_emerg_msc(true);
10729 f_vty_allow_emerg_bts(true, 0);
10730 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail), pars);
10731 vc_conn.done;
10732 f_shutdown_helper();
10733}
10734
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010735/* Attempt Complete Layer 3 without any MSC available (OS#4832) */
10736private function f_tc_no_msc(charstring id) runs on MSC_ConnHdlr {
10737 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10738
10739 /* Also disable attach for the single connected MSC */
10740 f_vty_msc_allow_attach(BSCVTY, { false });
10741
10742 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) ));
10743 f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
10744
10745 /* No MSC is found, expecting a proper release on RSL */
10746 interleave {
10747 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
10748 f_logp(BSCVTY, "Got RSL RR Release");
10749 }
10750 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
10751 f_logp(BSCVTY, "Got RSL Deact SACCH");
10752 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020010753 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010754 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
10755 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020010756 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010757 }
10758 }
10759 setverdict(pass);
10760}
10761testcase TC_no_msc() runs on test_CT {
10762
10763 f_init(1, true);
10764 f_sleep(1.0);
10765 var MSC_ConnHdlr vc_conn;
10766 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10767
10768 f_ctrs_bsc_init(counternames_bsc_mscpool);
10769
10770 vc_conn := f_start_handler(refers(f_tc_no_msc), pars);
10771 vc_conn.done;
10772
10773 f_ctrs_bsc_add("mscpool:subscr:no_msc");
10774 f_ctrs_bsc_verify();
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010775 f_shutdown_helper();
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010776}
10777
Harald Welte0ea2d5e2018-04-07 21:40:29 +020010778/* Dyn PDCH todo:
10779 * activate OSMO as TCH/F
10780 * activate OSMO as TCH/H
10781 * does the BSC-located PCU socket get the updated INFO?
10782 * what if no PCU is connected at the time?
10783 * is the info correct on delayed PCU (re)connect?
10784 */
Harald Welte94e0c342018-04-07 11:33:23 +020010785
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010786private function f_TC_refuse_mode_modif_to_vamos(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +020010787 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020010788 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010789
10790 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
10791 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
10792 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
10793 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
10794 g_pars.ass_codec_list.codecElements[0];
10795 if (isvalue(g_pars.expect_mr_s0_s7)) {
10796 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
10797 g_pars.expect_mr_s0_s7;
10798 }
10799 }
10800 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
10801 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
10802 log("expecting ASS COMPL like this: ", exp_compl);
10803
10804 f_establish_fully(ass_cmd, exp_compl);
10805
Neels Hofmeyr8746b0d2021-06-01 17:25:39 +020010806 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 +000010807
10808 var RSL_Message rsl;
10809
10810 timer T := 5.0;
10811 T.start;
10812 alt {
10813 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
10814 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
10815 log("Rx L3 from net: ", l3);
10816 if (ischosen(l3.msgs.rrm.channelModeModify)) {
10817 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
10818 mtc.stop;
10819 }
10820 }
10821 [] RSL.receive(tr_RSL_MODE_MODIFY_REQ(g_chan_nr, ?)) -> value rsl {
10822 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
10823 mtc.stop;
10824 }
10825 [] T.timeout {
10826 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related Mode Modify should happen. */
10827 setverdict(pass);
10828 }
10829 }
10830 T.stop;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010831
10832 f_perform_clear();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010833}
10834
10835/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel Mode Modify to VAMOS mode is refused by
10836 * osmo-bsc. */
10837testcase TC_refuse_mode_modif_to_vamos() runs on test_CT {
10838 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10839 var MSC_ConnHdlr vc_conn;
10840
10841 f_init(1, true);
10842 f_sleep(1.0);
10843
10844 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10845 vc_conn := f_start_handler(refers(f_TC_refuse_mode_modif_to_vamos), pars);
10846 vc_conn.done;
10847 f_shutdown_helper();
10848}
10849
10850/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel activation to VAMOS mode is refused by osmo-bsc.
10851 */
10852testcase TC_refuse_chan_act_to_vamos() runs on test_CT {
10853 f_init_vty();
10854
10855 f_init(1, false);
10856 f_sleep(1.0);
10857
10858 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 activate-vamos fr");
10859
10860 var ASP_RSL_Unitdata rx_rsl_ud;
10861 timer T := 5.0;
10862
10863 T.start;
10864 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010865 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(?, IPAC_PROTO_RSL_TRX0)) -> value rx_rsl_ud {
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010866 if (rx_rsl_ud.rsl.msg_type == RSL_MT_CHAN_ACTIV) {
10867 T.stop;
10868 setverdict(fail, "CHANnel ACTivate in VAMOS mode succeeded even though BTS does not support VAMOS");
10869 mtc.stop;
10870 }
10871 repeat;
10872 }
10873 [] T.timeout {
10874 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related CHANnel ACTivate should happen. */
10875 setverdict(pass);
10876 }
10877 }
10878}
10879
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010880private function f_TC_reassignment_codec(charstring id) runs on MSC_ConnHdlr {
10881 /* First fully set up a speech lchan */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010882 f_assignment_codec(id, do_perform_clear := false);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010883
10884 /* Trigger re-assignment to another lchan */
10885 var AssignmentState assignment_st := valueof(ts_AssignmentStateInit);
10886
10887 /* Re-Assignment should tell the MGW endpoint the new lchan's RTP address and port, so expecting to see exactly
10888 * one MDCX on MGCP. */
10889 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].mdcx_seen_exp + 1;
10890
10891 /* The new lchan will see all-new IPAC_CRCX and IPAC_MDCX messages telling the BTS the same RTP address and port
10892 * as the old lchan used. */
10893 g_media.bts.ipa_crcx_seen := false;
10894 g_media.bts.ipa_mdcx_seen := false;
10895
10896 /* Send different BTS side RTP port number for the new lchan */
10897 g_media.bts.bts.port_nr := 4223;
10898
10899 f_rslem_register(0, valueof(ts_RslChanNr_Bm(2))); /* <-- FIXME: can we somehow infer the timeslot that will be used? */
10900
10901 /* Trigger re-assignment. */
10902 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot " & int2str(g_chan_nr.tn) & " sub-slot 0 assignment");
10903
10904 timer T := 5.0;
10905 T.start;
10906 alt {
10907 [] as_assignment(assignment_st);
10908 [] as_Media();
10909 [] T.timeout {
10910 break;
10911 }
10912 }
10913
10914 if (not assignment_st.assignment_done) {
10915 setverdict(fail, "Assignment did not complete");
10916 mtc.stop;
10917 }
10918
10919 f_check_mgcp_expectations()
10920 setverdict(pass);
10921
10922 f_sleep(2.0);
10923 log("show lchan summary: ", f_vty_transceive_ret(BSCVTY, "show lchan summary"));
10924
10925 /* Instruct BSC to clear channel */
10926 var BssmapCause cause := 0;
10927 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
10928 interleave {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010929 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {}
10930 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020010931 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010932 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020010933 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010934 }
10935 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
10936 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
10937 }
10938 }
Neels Hofmeyr40a45d12021-09-23 22:57:12 +020010939 f_expect_dlcx_conns();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010940
10941 f_sleep(0.5);
10942}
10943
10944testcase TC_reassignment_fr() runs on test_CT {
10945 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10946 var MSC_ConnHdlr vc_conn;
10947
10948 f_init(1, true);
10949 f_sleep(1.0);
10950
Neels Hofmeyrac432fa2021-11-02 16:45:56 +010010951 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010952
10953 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10954 vc_conn := f_start_handler(refers(f_TC_reassignment_codec), pars);
10955 vc_conn.done;
10956
10957 /* from f_establish_fully() */
10958 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
10959 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
10960 /* from re-assignment */
10961 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
10962 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
10963 f_ctrs_bsc_and_bts_verify();
10964 f_shutdown_helper();
10965}
10966
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010967const charstring REEST_LOST_CONNECTION := "REEST_LOST_CONNECTION";
10968const charstring REEST_CLEAR := "REEST_CLEAR";
10969const charstring REEST_CLEAR_DONE := "REEST_CLEAR_DONE";
10970
10971/* CM Re-Establishment, 3GPP TS 24.008 4.5.1.6.
10972 * The MS <-> BTS loses radio connection, MS shows up on second BTS and asks for CM Re-Establishment.
10973 * BSC should establish a separate A conn for the same MS, the original A conn is then cleared by
10974 * the MSC as the CM Re-Establishment is handled.
10975 *
10976 * MS bts0 bts1 bsc msc test-component
10977 * |<----->|<----------------->|<-0-->| _1 Establish channel on bts 0
10978 * | | _1 wait a bit, to settle down
10979 * |<-x x--| | _1 "lose connection"
10980 * | | REEST_LOST_CONNECTION
10981 * |----------------->|------->|--1-->| _2 new A-conn: Chan Rqd, Imm Ass, Compl L3 with CM Re-Establishment Req
10982 * | | REEST_CLEAR
10983 * | |<-0---| _1 Clear Command on first A-conn
10984 * | |--0-->| _1 Clear Complete
10985 * | |<----------------->| | _1 Release first channel
10986 * | | REEST_CLEAR_DONE
10987 * |<-----------------|<-------|<-1---| _2 Chan Activ, Assignment Command
10988 * |<-----------------|<-------|<-1---| _2 Clear Command, Release
10989 *
10990 */
10991private function f_tc_cm_reestablishment_1(charstring id) runs on MSC_ConnHdlr {
10992 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
10993 var PDU_BSSAP ass_cmd := f_gen_ass_req();
10994
10995 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
10996 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10997
10998 f_establish_fully(ass_cmd, exp_compl);
10999
11000 /* The original channel loses connection, MS attemts CM Re-Establishment on another cell, see
11001 * f_tc_cm_reestablishment_2(). This established channel stays active until MSC sends a Clear Command. The time
11002 * when exactly that happens is determined by f_tc_cm_reestablishment_2(). */
11003 f_sleep(2.0);
11004 COORD.send(REEST_LOST_CONNECTION);
11005
11006 alt {
11007 [] COORD.receive(REEST_CLEAR);
11008 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
11009 setverdict(fail, "Unexpected channel release");
11010 mtc.stop;
11011 }
11012 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
11013 setverdict(fail, "Unexpected channel release");
11014 mtc.stop;
11015 }
11016 }
11017 f_perform_clear()
Neels Hofmeyr969abd02021-09-23 22:24:08 +020011018 f_create_mgcp_delete_ep(g_media.mgcp_ep);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011019 COORD.send(REEST_CLEAR_DONE);
11020}
11021
11022private function f_tc_cm_reestablishment_2(charstring id) runs on MSC_ConnHdlr {
11023 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
11024
11025 /* The MS lost the connection on the first channel, now establishes another one */
11026 COORD.receive(REEST_LOST_CONNECTION);
11027
11028 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
11029 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REESTABL_REQ(mi));
11030 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
11031
11032 f_create_bssmap_exp(l3_enc);
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011033 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 +020011034 BSSAP.receive(tr_BSSMAP_ComplL3(l3_enc));
11035
11036 /* MSC got the CM Re-Establishment request and first off clears the previous conn. */
11037 COORD.send(REEST_CLEAR);
11038 COORD.receive(REEST_CLEAR_DONE);
11039
11040 f_sleep(2.0);
11041
11042 /* Answer the CM Re-Establishment with an Assignment Command. */
11043 var template PDU_BSSAP expect_assignment_compl := f_gen_exp_compl();
11044 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11045 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11046 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11047
11048 var AssignmentState st := valueof(ts_AssignmentStateInit);
11049 st.voice_call := true;
11050 st.is_assignment := true;
11051
11052 var ExpectCriteria mgcpcrit := {
11053 connid := omit,
11054 endpoint := omit,
11055 transid := omit
11056 };
11057 f_create_mgcp_expect(mgcpcrit);
11058
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011059 f_rslem_dchan_queue_enable(RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011060
11061 BSSAP.send(ass_cmd);
11062
11063 var PDU_BSSAP bssap;
11064
11065 alt {
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011066 [] as_assignment(st, rsl_pt := RSL1, rsl_proc_pt := RSL1_PROC);
11067 [] as_Media_ipacc(RSL1, RSL2);
11068 [] as_Media_mgw();
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011069 [st.assignment_done] BSSAP.receive(expect_assignment_compl) {
11070 break;
11071 }
11072 }
11073
11074 f_sleep(3.0);
11075
11076 f_logp(BSCVTY, "f_tc_cm_reestablishment_2 clearing");
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011077 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011078}
11079
11080testcase TC_cm_reestablishment() runs on test_CT {
11081 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
11082 var MSC_ConnHdlr vc_conn1;
11083
11084 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
11085 var MSC_ConnHdlr vc_conn2;
11086 pars2.imsi := pars1.imsi;
11087 pars2.media_nr := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011088 pars2.expect_tsc := c_BtsParams[1].tsc;
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011089
11090 f_init(2, true, guard_timeout := 40.0);
11091 f_sleep(1.0);
11092
11093 vc_conn1 := f_start_handler_create(pars1);
11094 vc_conn2 := f_start_handler_create(pars2);
11095 connect(vc_conn1:COORD, vc_conn2:COORD);
11096 f_start_handler_run(vc_conn1, refers(f_tc_cm_reestablishment_1), pars1);
11097 f_start_handler_run(vc_conn2, refers(f_tc_cm_reestablishment_2), pars2);
11098 vc_conn1.done;
11099 vc_conn2.done;
11100
11101 f_shutdown_helper();
11102}
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000011103
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011104function f_exp_ipa_rx_nonfatal(template (present) RSL_Message t_rx,
11105 boolean ignore_other_rx := true,
11106 BtsTrxIdx idx := {0, 0},
11107 float Tval := 2.0)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011108runs on test_CT return template (omit) RSL_Message {
11109 var ASP_RSL_Unitdata rx_rsl_ud;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011110 timer T := Tval;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011111
11112 T.start;
11113 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011114 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011115 T.stop;
11116 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011117 [ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
11118 [not ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011119 log("f_exp_ipa_rx_nonfatal(): Got different message than ", t_rx);
11120 T.stop;
11121 return omit;
11122 }
11123 [] T.timeout {
11124 return omit;
11125 }
11126 }
11127 return rx_rsl_ud.rsl;
11128}
11129
11130private function f_vty_set_imm_ass(TELNETasp_PT pt, BtsNr bts_nr := 0, charstring imm_ass_setting := "post-chan-ack") {
11131 f_vty_enter_cfg_bts(pt, bts_nr);
11132 f_vty_transceive(pt, "immediate-assignment " & imm_ass_setting);
11133 f_vty_transceive(pt, "exit");
11134 f_vty_transceive(pt, "exit");
11135 f_vty_transceive(pt, "exit");
11136}
11137
11138private function f_verify_imm_ass(RSL_Message imm_ass, template uint8_t ra := ?, template GsmFrameNumber fn := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +030011139 template (present) RslChannelNr chan_nr := ?,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011140 template (present) uint12_t arfcn := ?,
11141 template (present) uint3_t tsc := ?)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011142{
11143 var RSL_IE_Body full_imm_ass_info;
11144 if (not f_rsl_find_ie(imm_ass, RSL_IE_FULL_IMM_ASS_INFO, full_imm_ass_info)) {
11145 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
11146 mtc.stop;
11147 }
11148
11149 var GsmRrMessage rr_imm_ass := dec_GsmRrMessage(full_imm_ass_info.full_imm_ass_info.payload);
11150 var template GsmRrMessage expect_imm_ass := tr_IMM_ASS(ra := ra,
11151 fn := fn,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011152 ch_desc := tr_ChanDescH0(chan_nr, arfcn, tsc),
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011153 page_mode := ?);
11154 if (not match(rr_imm_ass, expect_imm_ass)) {
11155 log("Error: expected ", expect_imm_ass, " got ", rr_imm_ass);
11156 setverdict(fail, "Failed to match Immediate Assignment");
11157 mtc.stop;
11158 }
11159}
11160
11161testcase TC_imm_ass_post_chan_ack() runs on test_CT {
11162 var RSL_Message chan_act;
11163 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011164 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011165
11166 f_init(1, false);
11167 f_sleep(1.0);
11168
11169 /* (should be the default anyway, just to make things clear) */
11170 f_vty_set_imm_ass(BSCVTY, 0, "post-chan-ack");
11171
11172 /* RA containing reason=LU */
11173 var GsmFrameNumber fn := 2342;
11174 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011175 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011176
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011177 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011178
11179 /* First send the Chan Act ACK */
11180 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011181 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011182 var RSL_IE_Body chan_ident_ie;
11183 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11184 setverdict(fail, "RSL Channel Identification IE is absent");
11185 mtc.stop;
11186 }
11187
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011188 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn + 10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011189
11190 /* Then expect the Immediate Assignment, after we ACKed the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011191 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011192
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011193 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11194 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011195
11196 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011197 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011198
11199 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011200 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011201 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011202 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11203
11204 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011205 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011206 f_shutdown_helper();
11207}
11208
11209testcase TC_imm_ass_pre_chan_ack() runs on test_CT {
11210 var RSL_Message chan_act;
11211 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011212 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011213
11214 f_init(1, false);
11215 f_sleep(1.0);
11216
11217 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11218
11219 /* RA containing reason=LU */
11220 var GsmFrameNumber fn := 2342;
11221 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011222 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011223
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011224 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011225 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011226 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011227 var RSL_IE_Body chan_ident_ie;
11228 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11229 setverdict(fail, "RSL Channel Identification IE is absent");
11230 mtc.stop;
11231 }
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011232
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011233 /* (set bts 0 cfg back to default) */
11234 f_vty_set_imm_ass(BSCVTY);
11235
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011236 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011237 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011238 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11239 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011240
11241 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011242 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011243
11244 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011245 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011246
11247 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011248 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011249 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011250 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11251
11252 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011253 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011254 f_shutdown_helper();
11255}
11256
Neels Hofmeyr23158742021-09-07 19:08:07 +020011257testcase TC_imm_ass_pre_ts_ack() runs on test_CT {
11258 var RSL_Message chan_act;
11259 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011260 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyr23158742021-09-07 19:08:07 +020011261
11262 f_init(1, false);
11263 f_sleep(1.0);
11264
11265 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11266
11267 /* RA containing reason=LU */
11268 var GsmFrameNumber fn := 2342;
11269 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011270 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011271
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011272 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011273 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011274 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr23158742021-09-07 19:08:07 +020011275 var RSL_IE_Body chan_ident_ie;
11276 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11277 setverdict(fail, "RSL Channel Identification IE is absent");
11278 mtc.stop;
11279 }
11280
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011281 /* (set bts 0 cfg back to default) */
11282 f_vty_set_imm_ass(BSCVTY);
11283
Neels Hofmeyr23158742021-09-07 19:08:07 +020011284 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011285 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011286 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11287 chan_ident_ie.chan_ident.ch_desc.v.tsc);
11288
11289 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011290 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011291
11292 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011293 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011294
11295 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011296 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011297 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr23158742021-09-07 19:08:07 +020011298 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11299
11300 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011301 f_perform_clear_test_ct(dt);
Neels Hofmeyr23158742021-09-07 19:08:07 +020011302 f_shutdown_helper();
11303}
11304
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011305testcase TC_imm_ass_pre_chan_ack_dyn_ts() runs on test_CT {
11306 /* change Timeslot 6 before f_init() starts RSL */
11307 f_init_vty();
11308 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11309 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11310
11311 f_init(1, false);
11312 f_sleep(1.0);
11313
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011314 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011315 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11316 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011317 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11318 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011319
11320 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11321 f_ts_set_chcomb(0, 0, 6, "PDCH");
11322
11323 /* block all static timeslots so that the dyn TS will be used */
11324 f_disable_all_tch_f();
11325 f_disable_all_tch_h();
11326 f_disable_all_sdcch();
11327
11328 var RSL_Message chan_act;
11329 var RSL_Message imm_ass;
11330
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011331 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11332
11333 /* RA containing reason=LU */
11334 var GsmFrameNumber fn := 2342;
11335 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011336 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011337
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011338 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011339 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
11340 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011341
11342 /* Now activation as SDCCH8 */
11343 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011344 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011345
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011346 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011347 var RSL_IE_Body chan_ident_ie;
11348 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11349 setverdict(fail, "RSL Channel Identification IE is absent");
11350 mtc.stop;
11351 }
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011352
11353 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011354 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011355 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11356 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011357
11358 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011359 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011360
11361 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011362 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011363
11364 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011365 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011366 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011367 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11368
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011369 /* (set bts 0 cfg back to default) */
11370 f_vty_set_imm_ass(BSCVTY);
11371
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011372 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011373 f_perform_clear_test_ct(dt);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011374 f_shutdown_helper();
11375}
11376
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011377testcase TC_imm_ass_pre_ts_ack_dyn_ts() runs on test_CT {
11378 /* change Timeslot 6 before f_init() starts RSL */
11379 f_init_vty();
11380 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11381 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11382
11383 f_init(1, false);
11384 f_sleep(1.0);
11385
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011386 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011387 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11388 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011389 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11390 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011391
11392 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11393 f_ts_set_chcomb(0, 0, 6, "PDCH");
11394
11395 /* block all static timeslots so that the dyn TS will be used */
11396 f_disable_all_tch_f();
11397 f_disable_all_tch_h();
11398 f_disable_all_sdcch();
11399
11400 var RSL_Message chan_act;
11401 var RSL_Message imm_ass;
11402
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011403 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11404
11405 /* RA containing reason=LU */
11406 var GsmFrameNumber fn := 2342;
11407 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011408 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011409
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011410 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011411 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011412
11413 /* And already the Immediate Assignment even before the PDCH Deact ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011414 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011415
11416 /* continue the Osmo style PDCH Deact (usual chan rel) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011417 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011418
11419 /* Now activation as SDCCH8 */
11420 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011421 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011422
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011423 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011424 var RSL_IE_Body chan_ident_ie;
11425 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11426 setverdict(fail, "RSL Channel Identification IE is absent");
11427 mtc.stop;
11428 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011429 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011430
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011431 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11432 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011433
11434 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011435 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011436
11437 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011438 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011439 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011440 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11441
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011442 /* (set bts 0 cfg back to default) */
11443 f_vty_set_imm_ass(BSCVTY);
11444
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011445 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011446 f_perform_clear_test_ct(dt);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011447 f_shutdown_helper();
11448}
11449
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011450/* GET and SET the bts.N.trx.M.rf_locked CTRL variable */
11451testcase TC_ctrl_trx_rf_locked() runs on test_CT {
11452 var MSC_ConnHdlr vc_conn;
11453
11454 f_init(nr_bts := 2, handler_mode := true, nr_msc := 1);
11455 f_sleep(1.0);
11456
11457 /* BTS 0, 1, 2 are OML unlocked, only BTS 0, 1 are actually connected to RSL. */
11458 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11459 "0,0,operational,unlocked,on,rsl-up;" &
11460 "1,0,operational,unlocked,on,rsl-up;" &
11461 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011462 "2,1,operational,unlocked,on,rsl-down;" &
11463 "2,2,operational,unlocked,on,rsl-down;" &
11464 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011465 "3,0,inoperational,locked,on,rsl-down;");
11466
11467 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock BTS 1 TRX 0");
11468 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11469 /* give it a moment to settle the FSM status */
11470 f_sleep(1.0);
11471
11472 /* Now BTS 1 TRX 0 should reflect "locked". Note the RF policy stays "on", because this is still handled
11473 * globally in osmo-bsc. Probably after sending "rf_locked 1" for a TRX, that TRX should reflect an RF policy
11474 * of "off"? But that's for a future patch if at all. */
11475 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11476 "0,0,operational,unlocked,on,rsl-up;" &
11477 "1,0,operational,locked,on,rsl-up;" &
11478 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011479 "2,1,operational,unlocked,on,rsl-down;" &
11480 "2,2,operational,unlocked,on,rsl-down;" &
11481 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011482 "3,0,inoperational,locked,on,rsl-down;");
11483
11484 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock the already locked TRX, nothing should change");
11485 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11486 f_sleep(1.0);
11487 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11488 "0,0,operational,unlocked,on,rsl-up;" &
11489 "1,0,operational,locked,on,rsl-up;" &
11490 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011491 "2,1,operational,unlocked,on,rsl-down;" &
11492 "2,2,operational,unlocked,on,rsl-down;" &
11493 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011494 "3,0,inoperational,locked,on,rsl-down;");
11495
11496 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock BTS 1 TRX 0");
11497 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "0");
11498 f_sleep(1.0);
11499 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11500 "0,0,operational,unlocked,on,rsl-up;" &
11501 "1,0,operational,unlocked,on,rsl-up;" &
11502 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011503 "2,1,operational,unlocked,on,rsl-down;" &
11504 "2,2,operational,unlocked,on,rsl-down;" &
11505 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011506 "3,0,inoperational,locked,on,rsl-down;");
11507
11508 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an already unlocked TRX, nothing should change");
11509 f_ctrl_set(IPA_CTRL, "bts.0.trx.0.rf_locked", "0");
11510 f_sleep(1.0);
11511 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11512 "0,0,operational,unlocked,on,rsl-up;" &
11513 "1,0,operational,unlocked,on,rsl-up;" &
11514 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011515 "2,1,operational,unlocked,on,rsl-down;" &
11516 "2,2,operational,unlocked,on,rsl-down;" &
11517 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011518 "3,0,inoperational,locked,on,rsl-down;");
11519
11520 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an inoperational TRX");
11521 f_ctrl_set(IPA_CTRL, "bts.3.trx.0.rf_locked", "0");
11522 f_sleep(1.0);
11523 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11524 "0,0,operational,unlocked,on,rsl-up;" &
11525 "1,0,operational,unlocked,on,rsl-up;" &
11526 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011527 "2,1,operational,unlocked,on,rsl-down;" &
11528 "2,2,operational,unlocked,on,rsl-down;" &
11529 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011530 "3,0,inoperational,locked,on,rsl-down;");
11531
11532 f_shutdown_helper();
11533}
11534
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011535const CounterNameVals counternames_cm_serv_rej := {
11536 { "cm_serv_rej", 0 },
11537 { "cm_serv_rej:imsi_unknown_in_hlr", 0 },
11538 { "cm_serv_rej:illegal_ms", 0 },
11539 { "cm_serv_rej:imsi_unknown_in_vlr", 0 },
11540 { "cm_serv_rej:imei_not_accepted", 0 },
11541 { "cm_serv_rej:illegal_me", 0 },
11542 { "cm_serv_rej:plmn_not_allowed", 0 },
11543 { "cm_serv_rej:loc_not_allowed", 0 },
11544 { "cm_serv_rej:roaming_not_allowed", 0 },
11545 { "cm_serv_rej:network_failure", 0 },
11546 { "cm_serv_rej:synch_failure", 0 },
11547 { "cm_serv_rej:congestion", 0 },
11548 { "cm_serv_rej:srv_opt_not_supported", 0 },
11549 { "cm_serv_rej:rqd_srv_opt_not_supported", 0 },
11550 { "cm_serv_rej:srv_opt_tmp_out_of_order", 0 },
11551 { "cm_serv_rej:call_can_not_be_identified", 0 },
11552 { "cm_serv_rej:incorrect_message", 0 },
11553 { "cm_serv_rej:invalid_mandantory_inf", 0 },
11554 { "cm_serv_rej:msg_type_not_implemented", 0 },
11555 { "cm_serv_rej:msg_type_not_compatible", 0 },
11556 { "cm_serv_rej:inf_eleme_not_implemented", 0 },
11557 { "cm_serv_rej:condtional_ie_error", 0 },
11558 { "cm_serv_rej:msg_not_compatible", 0 },
11559 { "cm_serv_rej:protocol_error", 0 },
11560 { "cm_serv_rej:retry_in_new_cell", 0 }
11561};
11562
11563private function f_TC_cm_serv_rej(charstring id) runs on MSC_ConnHdlr
11564{
11565 f_create_chan_and_exp();
Vadim Yanitskiya7fc5a62021-12-04 20:10:08 +030011566 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011567 BSSAP.send(ts_PDU_DTAP_MT(ts_CM_SERV_REJ('02'O), '00'O));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011568 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_CM_SERV_REJ));
11569 f_perform_clear();
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011570 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011571}
11572testcase TC_cm_serv_rej() runs on test_CT {
11573 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11574 var MSC_ConnHdlr vc_conn;
11575
11576 f_init(1, true);
11577 f_sleep(1.0);
11578
11579 f_ctrs_bts_init(1, counternames_cm_serv_rej);
11580
11581 vc_conn := f_start_handler(refers(f_TC_cm_serv_rej), pars);
11582 vc_conn.done;
11583
11584 f_ctrs_bts_add(0, "cm_serv_rej", 1);
11585 f_ctrs_bts_add(0, "cm_serv_rej:imsi_unknown_in_hlr", 1);
11586 f_ctrs_bts_verify();
11587
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011588 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011589 f_shutdown_helper();
11590}
11591
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011592/* Reproduce a segfault happening when the SDCCH (primary) lchan is lost in-between a TCH Channel Activ and its Channel
11593 * Activ Ack (SYS#5627). */
11594private function f_TC_lost_sdcch_during_assignment(charstring id) runs on MSC_ConnHdlr {
11595 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Vadim Yanitskiyf0310e32021-10-26 00:30:59 +030011596
11597 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11598 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011599
11600 var BSSMAP_FIELD_CodecType codecType;
11601 codecType := valueof(ass_cmd.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType);
11602
11603 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
11604
11605 /* First establish a signalling lchan */
11606 f_create_chan_and_exp();
11607 f_rslem_dchan_queue_enable();
11608
11609 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011610
11611 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
Oliver Smith735b47c2023-02-15 16:03:54 +010011612 activate(as_Media_mgw());
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011613
11614 var RslChannelNr chan_nr := { u := { ch0 := RSL_CHAN_NR_Bm_ACCH }, tn := 1 };
11615 f_rslem_register(0, chan_nr);
11616
11617 f_rslem_set_auto_chan_act_ack(RSL_PROC, false);
11618 BSSAP.send(ass_cmd);
11619
11620
11621 /* Wait for the Channel Activ for the TCH channel */
11622 var ASP_RSL_Unitdata rx_rsl_ud;
11623 RSL.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), sid := ?)) -> value rx_rsl_ud;
11624
11625 /* make the original SDCCH disappear */
11626 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
11627
11628 /* and ACK the TCH channel activation. This caused a segfault up to OsmoBSC 1.7.0 (SYS#5627) */
11629 RSL.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_ACK(chan_nr, 23), rx_rsl_ud.streamId));
11630
11631 interleave {
11632 [] BSSAP.receive(tr_BSSMAP_AssignmentFail);
11633 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
11634 }
11635
11636 BSSAP.send(ts_BSSMAP_ClearCommand(0));
11637 BSSAP.receive(tr_BSSMAP_ClearComplete);
11638 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
11639
11640 var MgcpCommand mgcp;
Vadim Yanitskiy6be4cf42022-06-04 21:25:47 +060011641 var MGCP_RecvFrom mrf;
11642 var template MgcpMessage msg_dlcx := { command := tr_DLCX };
11643 alt {
11644 [g_pars.aoip] MGCP.receive(tr_DLCX) -> value mgcp {
11645 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
11646 }
11647 [not g_pars.aoip] MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
11648 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, MgcpMessage:{
11649 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
11650 }));
11651 }
11652 }
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011653
11654 f_sleep(0.5);
11655}
11656testcase TC_lost_sdcch_during_assignment() runs on test_CT {
11657 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11658 var MSC_ConnHdlr vc_conn;
11659
Oliver Smith735b47c2023-02-15 16:03:54 +010011660 pars.fail_on_dlcx := false;
11661
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011662 f_init(1, true);
11663 f_sleep(1.0);
11664
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011665 vc_conn := f_start_handler(refers(f_TC_lost_sdcch_during_assignment), pars);
11666 vc_conn.done;
11667
11668 f_shutdown_helper();
11669}
11670
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011671const CounterNameVals counternames_bsc_bts_all_available_allocated := {
11672 { "all_allocated:sdcch", 0 },
11673 { "all_allocated:static_sdcch", 0 },
11674 { "all_allocated:tch", 0 },
11675 { "all_allocated:static_tch", 0 }
11676}
11677
11678private function f_all_allocated_expect_counter_change(charstring_list expect_changed) runs on test_CT
11679{
11680 /* Make sure counters settle first */
11681 f_sleep(1.0);
11682
11683 /* Take a baseline of counters */
11684 f_ctrs_bsc_and_bts_init(1, counternames_bsc_bts_all_available_allocated);
11685
11686 /* Elapse some time so that we see changes in counters, hopefully where expected */
11687 f_sleep(2.0);
11688
11689 /* Get new counters */
11690 var charstring_list all_changed := {};
11691 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bsc", g_ctr_bsc);
11692 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bts", g_ctr_bts);
11693
11694 /* Compare with expectations */
11695 var charstring_list all_expect_changed := {};
11696 for (var integer i := 0; i < lengthof(expect_changed); i := i + 1) {
11697 all_expect_changed := all_expect_changed & { "bsc.0." & expect_changed[i], "bts.0." & expect_changed[i] };
11698 }
11699 f_counter_name_vals_expect_changed_list(all_changed, all_expect_changed);
11700}
11701
11702testcase TC_ratectr_all_available_allocated() runs on test_CT {
11703 var ASP_RSL_Unitdata rsl_ud;
11704 var integer i;
11705 var integer chreq_total, chreq_nochan;
11706
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011707 f_init(1, guard_timeout := 60.0);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011708 f_sleep(1.0);
11709
11710 /* Exhaust all dedicated SDCCH lchans.
11711 /* GSM 44.018 Table 9.1.8.2:
11712 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11713 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011714 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011715 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011716 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 +020011717 }
11718
11719 /* Since only bts 0 is connected, expecting all_allocated to become true for both bts 0 and the "global" bsc
11720 * level.
11721 * All SDCCH are now occupied. */
11722 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11723
11724 /* Also fill up all remaining (TCH) channels */
11725 for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011726 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 +020011727 }
11728
11729 /* All TCH are now also occupied */
11730 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11731 "all_allocated:tch", "all_allocated:static_tch"});
11732
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011733 /* Clean up SDCCH lchans */
11734 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
11735 f_perform_clear_test_ct(chan_cleanup[i]);
11736 }
11737
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011738 f_shutdown_helper();
11739}
11740
11741testcase TC_ratectr_all_available_allocated_dyn() runs on test_CT {
11742 var ASP_RSL_Unitdata rsl_ud;
11743 var integer i;
11744 var integer chreq_total, chreq_nochan;
11745
11746 f_init_vty();
11747 f_ts_set_chcomb(0, 0, 2, "TCH/F_TCH/H_PDCH");
11748 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11749 /* Now we have 3 TCH/F, 1 OSMO_DYN, 1 TCH/H */
11750
11751 f_init(1, guard_timeout := 60.0);
11752 f_sleep(1.0);
11753
11754 /* The dyn TS wants to activate PDCH mode, ACK that. */
11755 var RslChannelNr chan_nr;
11756 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011757 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11758 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011759
11760 /* Exhaust all dedicated SDCCH lchans.
11761 /* GSM 44.018 Table 9.1.8.2:
11762 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11763 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011764 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011765 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011766 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 +020011767 }
11768
11769 /* The static SDCCH should now be occupied, while still 3x8 dynamic SDCCH potentially remain. So only
11770 * all_allocated:static_sdcch is counted, all_allocated:sdcch remains zero. */
11771 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch"});
11772
11773 /* Request more SDCCH, hence convert the first dyn TS to SDCCH8.
11774 * Will release them later, so remember all the DchanTuples. */
11775 var DchanTuples dyn_sddch := {};
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011776 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 +020011777
11778 /* Also occupy the seven other SDCCH of the dyn TS */
11779 for (i := 0; i < 7; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011780 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 +020011781 }
11782
11783 /* Now all dynamic SDCCH are also occupied, so for the first time all_allocated:sdcch will trigger... */
11784 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11785
11786 /* occupy the remaining TCH, three TCH/F and two TCH/H lchans */
11787 for (i := 0; i < 5; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011788 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 +020011789 }
11790
11791 /* All TCH lchans are now also occupied, both static and dynamic */
11792 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11793 "all_allocated:tch", "all_allocated:static_tch"});
11794
11795 /* Starting to release the dyn TS: as soon as the first SDCCH gets released, all_allocated:sdcch stops
11796 * incrementing. */
11797 var BssmapCause cause := 0;
11798 var DchanTuple dt := dyn_sddch[0];
11799 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011800 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011801
11802 /* one dyn TS SDCCH is free again, so only the static_sdcch should increment. For tch, both static and dynamic
11803 * count as occupied, so those still both increment. */
11804 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch",
11805 "all_allocated:tch", "all_allocated:static_tch"});
11806
11807 /* Release the remaining SDCCH of the dyn TS, so it becomes available as TCH again */
11808 for (i := 1; i < lengthof(dyn_sddch); i := i+1) {
11809 dt := dyn_sddch[i];
11810 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011811 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011812 }
11813
11814 /* All SDCCH on the dyn TS are released, the dyn TS wants to activate PDCH again */
11815 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011816 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11817 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011818
11819 /* Now all channels are occupied except the dyn TS, so expecting only the static counters to increment */
11820 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch", "all_allocated:static_tch"});
11821
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011822 /* Clean up SDCCH lchans */
11823 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
11824 f_perform_clear_test_ct(chan_cleanup[i]);
11825 }
11826
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011827 /* clean up config */
11828 f_ts_reset_chcomb(0);
11829
11830 f_shutdown_helper();
11831}
11832
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011833private function f_TC_chan_alloc_algo(DchanTuple dt, BtsTrxIdx idx)
11834runs on test_CT {
11835 /* MSC sends an Assignment Request */
11836 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11837 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11838 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11839 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
11840
11841 /* Expect the BSC to allocate a TCH channel on the given BTS/TRX */
11842 var RSL_Message rsl_chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
11843 /* Send CHAN ACT NACK, so that the requested TCH channel becomes BORKEN */
11844 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(rsl_chan_act.ies[0].body.chan_nr, RSL_ERR_EQUIPMENT_FAIL), idx);
11845 /* Expect to receive an Assignment Failure */
11846 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail));
11847}
11848
11849testcase TC_chan_alloc_algo_ascending() runs on test_CT {
11850 /* We need to access BTS2, which has 4 TRXs */
11851 f_init(nr_bts := 3);
11852
11853 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020011854 vc_MGCP[0].stop;
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011855
11856 f_vty_enter_cfg_bts(BSCVTY, 2);
11857 f_vty_transceive(BSCVTY, "channel allocator ascending");
11858 f_vty_transceive(BSCVTY, "end");
11859
11860 /* Expect the BSC to allocate 4 x TCH/F channels on BTS2/TRX0 */
11861 for (var integer i := 0; i < 4; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011862 var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), {2, 0});
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011863 f_TC_chan_alloc_algo(dt, {2, 0});
11864 f_perform_clear_test_ct(dt);
11865 }
11866
11867 /* At this point all 4 x TCH/F channels are BORKEN, but they will be
11868 * resurrected upon the A-bis/OML link re-establishment. */
11869 f_shutdown_helper();
11870}
11871
11872testcase TC_chan_alloc_algo_descending() runs on test_CT {
11873 /* We need to access BTS2, which has 4 TRXs */
11874 f_init(nr_bts := 3);
11875
11876 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020011877 vc_MGCP[0].stop;
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011878
11879 f_vty_enter_cfg_bts(BSCVTY, 2);
11880 f_vty_transceive(BSCVTY, "channel allocator descending");
11881 f_vty_transceive(BSCVTY, "end");
11882
11883 /* Expect the BSC to allocate 5 x TCH/F channels on BTS2/TRX3 */
11884 for (var integer i := 0; i < 5; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011885 var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), {2, 0});
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011886 f_TC_chan_alloc_algo(dt, {2, 3});
11887 f_perform_clear_test_ct(dt);
11888 }
11889
11890 /* At this point all 5 x TCH/F channels are BORKEN, but they will be
11891 * resurrected upon the A-bis/OML link re-establishment. */
11892 f_shutdown_helper();
11893}
11894
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011895testcase TC_chan_alloc_algo_ass_dynamic() runs on test_CT {
11896 const BtsTrxIdx TRX0 := {2, 0};
11897 const BtsTrxIdx TRX3 := {2, 3};
11898
11899 /* We need to access BTS2, which has 4 TRXs */
11900 f_init(nr_bts := 3);
11901
11902 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020011903 vc_MGCP[0].stop;
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011904
11905 f_vty_enter_cfg_bts(BSCVTY, 2);
11906 f_vty_transceive(BSCVTY, "channel allocator mode assignment dynamic");
11907 f_vty_transceive(BSCVTY, "channel allocator dynamic-param ul-rxlev thresh 50 avg-num 2");
11908 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 0");
11909 f_vty_transceive(BSCVTY, "end");
11910
11911 var DchanTuple dt;
11912
11913 f_logp(BSCVTY, "Case a) Unknown Uplink RxLev, fall-back to ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011914 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011915 f_TC_chan_alloc_algo(dt, TRX0);
11916 f_perform_clear_test_ct(dt);
11917
11918 f_logp(BSCVTY, "Case b) Not enough RxLev samples, use ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011919 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011920 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
11921 ts_RSL_IE_UplinkMeas(30, 0),
11922 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070011923 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011924 f_TC_chan_alloc_algo(dt, TRX0);
11925 f_perform_clear_test_ct(dt);
11926
11927 f_logp(BSCVTY, "Case c) Uplink RxLev below the threshold, use ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011928 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011929 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
11930 ts_RSL_IE_UplinkMeas(45, 0),
11931 ts_RSL_IE_BS_Power(0)), TRX0);
11932 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
11933 ts_RSL_IE_UplinkMeas(48, 0),
11934 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070011935 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011936 f_TC_chan_alloc_algo(dt, TRX0);
11937 f_perform_clear_test_ct(dt);
11938
11939 f_logp(BSCVTY, "Case d) Uplink RxLev above the threshold, use descending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011940 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011941 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
11942 ts_RSL_IE_UplinkMeas(50, 0),
11943 ts_RSL_IE_BS_Power(0)), TRX0);
11944 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
11945 ts_RSL_IE_UplinkMeas(58, 0),
11946 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070011947 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011948 f_TC_chan_alloc_algo(dt, TRX3);
11949 f_perform_clear_test_ct(dt);
11950
11951 f_vty_enter_cfg_bts(BSCVTY, 2);
11952 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 90");
11953 f_vty_transceive(BSCVTY, "end");
11954
11955 f_logp(BSCVTY, "Case e) Uplink RxLev above the threshold, but C0 load is not");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011956 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011957 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
11958 ts_RSL_IE_UplinkMeas(50, 0),
11959 ts_RSL_IE_BS_Power(0)), TRX0);
11960 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
11961 ts_RSL_IE_UplinkMeas(58, 0),
11962 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070011963 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011964 f_TC_chan_alloc_algo(dt, TRX0);
11965 f_perform_clear_test_ct(dt);
11966
11967 f_vty_enter_cfg_bts(BSCVTY, 2);
11968 f_vty_transceive(BSCVTY, "channel allocator ascending");
11969 f_vty_transceive(BSCVTY, "end");
11970
11971 /* At this point some TCH/F channels are BORKEN, but they will be
11972 * resurrected upon the A-bis/OML link re-establishment. */
11973 f_shutdown_helper();
11974}
11975
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020011976private function f_vty_mgw_enable(integer mgw_nr := 1) runs on test_CT {
11977 var rof_charstring cmds := {
11978 "remote-ip " & mp_test_ip,
11979 "remote-port " & int2str(2427 + mgw_nr)
11980 };
11981 f_vty_config3(BSCVTY, {"network", "mgw " & int2str(mgw_nr)}, cmds);
11982 f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " reconnect")
11983}
11984private function f_vty_mgw_disable(integer mgw_nr := 1) runs on test_CT {
11985 f_vty_config3(BSCVTY, {"network"}, { "no mgw " &int2str(mgw_nr) });
11986}
11987private function f_vty_mgw_block(integer mgw_nr := 1, boolean blocked := true) runs on test_CT {
11988 var charstring arg;
11989 if (blocked) {
11990 arg := "block";
11991 } else {
11992 arg := "unblock";
11993 }
11994 f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " " & arg);
11995}
11996private const charstring COORD_CMD_ESTABLISHED := "COORD_CMD_ESTABLISHED";
11997private function f_TC_mgwpool_call_seq_1(charstring id) runs on MSC_ConnHdlr {
11998 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
11999 var PDU_BSSAP ass_cmd := f_gen_ass_req();
12000 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12001 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12002
12003 f_establish_fully(ass_cmd, exp_compl);
12004 COORD.send(COORD_CMD_ESTABLISHED);
12005
12006 COORD.receive(COORD_CMD_ESTABLISHED);
12007 f_perform_clear()
12008 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12009}
12010private function f_TC_mgwpool_call_seq_2(charstring id) runs on MSC_ConnHdlr {
12011 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12012 var PDU_BSSAP ass_cmd := f_gen_ass_req();
12013 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12014 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12015
12016
12017 COORD.receive(COORD_CMD_ESTABLISHED);
12018 f_establish_fully(ass_cmd, exp_compl);
12019 COORD.send(COORD_CMD_ESTABLISHED);
12020
12021 f_perform_clear()
12022 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12023}
12024/* Test load is spread around 2 available MGWs */
12025testcase TC_mgwpool_all_used() runs on test_CT {
12026 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12027 var MSC_ConnHdlr vc_conn1;
12028 pars1.mgwpool_idx := 0;
12029
12030 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12031 var MSC_ConnHdlr vc_conn2;
12032 pars2.mgwpool_idx := 1;
12033
12034 f_init(1, true, nr_mgw := 2);
12035 f_sleep(1.0);
12036
12037 f_vty_mgw_enable(1);
12038
12039 vc_conn1 := f_start_handler_create(pars1);
12040 vc_conn2 := f_start_handler_create(pars2);
12041 connect(vc_conn1:COORD, vc_conn2:COORD);
12042 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12043 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12044 vc_conn1.done;
12045 vc_conn2.done;
12046
12047 f_vty_mgw_disable(1);
12048
12049 f_shutdown_helper();
12050}
12051
12052/* Test blocked MGW in the pool are not selected */
12053testcase TC_mgwpool_blocked_not_used() runs on test_CT {
12054 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12055 var MSC_ConnHdlr vc_conn1;
12056 pars1.mgwpool_idx := 0;
12057
12058 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12059 var MSC_ConnHdlr vc_conn2;
12060 pars2.mgwpool_idx := 0; /* expect it in the first one, since the second will be blocked */
12061 pars2.media_nr := 2;
12062
12063 f_init(1, true, nr_mgw := 2);
12064 f_sleep(1.0);
12065
12066 f_vty_mgw_enable(1);
12067 f_vty_mgw_block(1, true);
12068
12069 vc_conn1 := f_start_handler_create(pars1);
12070 vc_conn2 := f_start_handler_create(pars2);
12071 connect(vc_conn1:COORD, vc_conn2:COORD);
12072 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12073 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12074 vc_conn1.done;
12075 vc_conn2.done;
12076
12077 f_vty_mgw_disable(1);
12078
12079 f_shutdown_helper();
12080}
12081
Pau Espin Pedrol3f41e322022-10-20 19:34:43 +020012082/* Test BTS pinning to an MGW is applied */
12083testcase TC_mgwpool_pin_bts() runs on test_CT {
12084 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12085 var MSC_ConnHdlr vc_conn1;
12086 pars1.mgwpool_idx := 0;
12087
12088 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12089 var MSC_ConnHdlr vc_conn2;
12090 pars2.mgwpool_idx := 0; /* expect it in the first one, since the BTS is pinned to the first MGW */
12091 pars2.media_nr := 2;
12092
12093 f_init(1, true, nr_mgw := 2);
12094 f_sleep(1.0);
12095
12096 f_vty_mgw_enable(1);
12097 f_vty_cfg_bts(BSCVTY, 0, { "mgw pool-target 0" });
12098
12099 vc_conn1 := f_start_handler_create(pars1);
12100 vc_conn2 := f_start_handler_create(pars2);
12101 connect(vc_conn1:COORD, vc_conn2:COORD);
12102 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12103 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12104 vc_conn1.done;
12105 vc_conn2.done;
12106
12107 f_vty_cfg_bts(BSCVTY, 0, { "no mgw pool-target" } );
Vadim Yanitskiy389d7e02022-10-25 17:44:05 +070012108 f_vty_mgw_disable(1);
Pau Espin Pedrol3f41e322022-10-20 19:34:43 +020012109
12110 f_shutdown_helper();
12111}
12112
Oliver Smithc9a5f532022-10-21 11:32:23 +020012113private function f_tc_ho_meas_rep_multi_band(charstring id) runs on MSC_ConnHdlr {
12114 g_pars := f_gen_test_hdlr_pars();
12115 var PDU_BSSAP ass_req := f_gen_ass_req();
12116 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12117 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12118 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12119 f_establish_fully(ass_req, exp_compl);
12120
12121 /* Send a measurement report with bad rxlev except on 3rd entry. The
12122 * measurement report is divided into two sub lists, as described in
12123 * 3GPP TS 04.08 § 10.5.2.20. */
12124 var NcellReports neighbor_rep := {
12125 /* Sub list 1: same band */
Oliver Smitha6773042022-10-24 12:56:30 +020012126 { rxlev := 0, bcch_freq := 0, bsic := 12 }, /* ARFCN 800, band 1800, LAC 98 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012127 /* Sub list 2: different band */
Oliver Smitha6773042022-10-24 12:56:30 +020012128 { rxlev := 0, bcch_freq := 1, bsic := 13 }, /* ARFCN 200, band 850, LAC 97 */
12129 { rxlev := 40, bcch_freq := 2, bsic := 14 }, /* ARFCN 1000, band 900, LAC 99 */
12130 { rxlev := 0, bcch_freq := 3, bsic := 11 } /* ARFCN 0, band 900, LAC 96 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012131 };
12132 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
12133 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
12134 l3_mr, 0));
12135
12136 /* Expect a handover to the third entry. If the BSC parsed the report
Oliver Smitha6773042022-10-24 12:56:30 +020012137 * correctly, the third entry has LAC 99. */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012138 var template BSSMAP_FIELD_CellIdentificationList cid_list := {
Oliver Smitha6773042022-10-24 12:56:30 +020012139 cIl_LAC := { ts_BSSMAP_CI_LAC(99) }
Oliver Smithc9a5f532022-10-21 11:32:23 +020012140 };
12141 alt {
12142 [] BSSAP.receive(tr_BSSMAP_HandoverRequired(cid_list := cid_list)) {
12143 setverdict(pass);
12144 }
12145 [] BSSAP.receive(tr_BSSMAP_HandoverRequired()) {
12146 setverdict(fail, "Handover has unexpected LAC in Cell Identification List. The BSC probably"
12147 & " didn't parse the multi-band measurement report correctly.");
12148 }
12149 }
12150
12151 f_ho_out_of_this_bsc(skip_meas_rep := true);
12152}
12153testcase TC_ho_meas_rep_multi_band() runs on test_CT {
12154 /* Verify that the BSC parses the measurement report correctly when
12155 * neighbors in multiple bands are configured (OS#5717). See
12156 * gsm_arfcn2band_rc() in libosmocore src/gsm/gsm_utils.c for the
12157 * ARFCN -> band mapping. The MS is connected to band 1800. */
12158 var MSC_ConnHdlr vc_conn;
12159
12160 f_init_vty();
12161 f_bts_0_cfg(BSCVTY,
12162 {"neighbor-list mode automatic",
12163 "handover 1",
12164 "handover algorithm 2",
12165 "handover2 window rxlev averaging 1",
12166 "no neighbors",
12167 "neighbor lac 99 arfcn 1000 bsic any", /* band 900 */
12168 "neighbor lac 98 arfcn 800 bsic any", /* band 1800 */
12169 "neighbor lac 97 arfcn 200 bsic any", /* band 850 */
Oliver Smitha6773042022-10-24 12:56:30 +020012170 "neighbor lac 96 arfcn 0 bsic any"}); /* band 900 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012171 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
12172
12173 f_init(1, true);
12174 f_sleep(1.0);
12175
12176 f_ctrs_bsc_and_bts_handover_init();
12177
12178 vc_conn := f_start_handler(refers(f_tc_ho_meas_rep_multi_band));
12179 vc_conn.done;
12180
12181 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
12182 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
12183 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
12184 f_ctrs_bsc_and_bts_add(0, "handover:completed");
12185 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
12186 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
12187 f_ctrs_bsc_and_bts_verify();
12188 f_shutdown_helper(ho := true);
12189}
12190
Harald Welte28d943e2017-11-25 15:00:50 +010012191control {
Harald Welte898113b2018-01-31 18:32:21 +010012192 /* CTRL interface testing */
Harald Welte4003d112017-12-09 22:35:39 +010012193 execute( TC_ctrl_msc_connection_status() );
Stefan Sperlingb041b3d2018-01-03 17:14:55 +010012194 execute( TC_ctrl_msc0_connection_status() );
Neels Hofmeyrf65ce872021-09-23 18:40:10 +020012195 /* In SCCPlite tests, only one MSC is configured. These tests assume that three MSCs are configured, so only run
12196 * these in the AoIP test suite. */
12197 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12198 execute( TC_stat_num_msc_connected_1() );
12199 execute( TC_stat_num_msc_connected_2() );
12200 execute( TC_stat_num_msc_connected_3() );
12201 }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +020012202 execute( TC_stat_num_bts_connected_1() );
12203 execute( TC_stat_num_bts_connected_2() );
12204 execute( TC_stat_num_bts_connected_3() );
Harald Welte96c94412017-12-09 03:12:45 +010012205 execute( TC_ctrl() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012206 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER) {
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +020012207 execute( TC_ctrl_location() );
12208 }
Harald Welte898113b2018-01-31 18:32:21 +010012209
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020012210 execute( TC_si_default() );
Neels Hofmeyr66aeba42020-07-06 02:21:21 +020012211 execute( TC_si2quater_2_earfcns() );
12212 execute( TC_si2quater_3_earfcns() );
12213 execute( TC_si2quater_4_earfcns() );
12214 execute( TC_si2quater_5_earfcns() );
12215 execute( TC_si2quater_6_earfcns() );
Neels Hofmeyrad132f22020-07-08 02:20:16 +020012216 execute( TC_si2quater_12_earfcns() );
12217 execute( TC_si2quater_23_earfcns() );
12218 execute( TC_si2quater_32_earfcns() );
12219 execute( TC_si2quater_33_earfcns() );
12220 execute( TC_si2quater_42_earfcns() );
12221 execute( TC_si2quater_48_earfcns() );
12222 execute( TC_si2quater_49_earfcns() );
Pau Espin Pedrol85a84432020-07-20 18:45:03 +020012223 execute( TC_si_acc_rotate() );
Alexander Couzens4ad3a352020-09-10 22:29:12 +020012224 execute( TC_si_acc_ramp_rotate() );
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020012225
Harald Welte898113b2018-01-31 18:32:21 +010012226 /* RSL DCHAN Channel ACtivation / Deactivation */
Harald Welteae026692017-12-09 01:03:01 +010012227 execute( TC_chan_act_noreply() );
Harald Welte4003d112017-12-09 22:35:39 +010012228 execute( TC_chan_act_counter() );
Harald Welteae026692017-12-09 01:03:01 +010012229 execute( TC_chan_act_ack_noest() );
Philipp Maier9c60a622020-07-09 15:08:46 +020012230 execute( TC_chan_act_ack_noest_emerg() );
Philipp Maier606f07d2020-08-12 17:21:58 +020012231 execute( TC_chan_rqd_emerg_deny() );
Harald Welteae026692017-12-09 01:03:01 +010012232 execute( TC_chan_act_ack_est_ind_noreply() );
12233 execute( TC_chan_act_ack_est_ind_refused() );
Harald Welte618ef642017-12-14 14:58:20 +010012234 execute( TC_chan_act_nack() );
Harald Welte799c97b2017-12-14 17:50:30 +010012235 execute( TC_chan_exhaustion() );
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +070012236 execute( TC_chan_deact_silence() );
Harald Welte4003d112017-12-09 22:35:39 +010012237 execute( TC_chan_rel_rll_rel_ind() );
12238 execute( TC_chan_rel_conn_fail() );
12239 execute( TC_chan_rel_hard_clear() );
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +020012240 execute( TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() );
12241 execute( TC_chan_rel_last_eutran_plmn_hard_clear_csfb() );
Harald Welte99787102019-02-04 10:41:36 +010012242 execute( TC_chan_rel_hard_clear_csfb() );
Harald Welted8c36cd2017-12-09 23:05:31 +010012243 execute( TC_chan_rel_hard_rlsd() );
Harald Welte550daf92018-06-11 19:22:13 +020012244 execute( TC_chan_rel_hard_rlsd_ms_dead() );
Harald Welte85804d42017-12-10 14:11:58 +010012245 execute( TC_chan_rel_a_reset() );
Pau Espin Pedrolc675b612020-01-09 19:55:40 +010012246 execute( TC_chan_rel_sccp_tiar_timeout() );
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +020012247 execute( TC_chan_rel_rr_cause() );
Harald Welte6f521d82017-12-11 19:52:02 +010012248
Harald Weltecfe2c962017-12-15 12:09:32 +010012249 execute( TC_outbound_connect() );
Harald Welte898113b2018-01-31 18:32:21 +010012250
12251 /* Assignment related */
Harald Welte16a4adf2017-12-14 18:54:01 +010012252 execute( TC_assignment_cic_only() );
Harald Welte235ebf12017-12-15 14:18:16 +010012253 execute( TC_assignment_csd() );
12254 execute( TC_assignment_ctm() );
12255 execute( TC_assignment_sign() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020012256 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12257 execute( TC_assignment_aoip_tla_v6() );
12258 }
Harald Welte235ebf12017-12-15 14:18:16 +010012259 execute( TC_assignment_fr_a5_0() );
12260 execute( TC_assignment_fr_a5_1() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012261 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte8f67d1d2018-05-25 20:38:42 +020012262 execute( TC_assignment_fr_a5_1_codec_missing() );
12263 }
Harald Welte235ebf12017-12-15 14:18:16 +010012264 execute( TC_assignment_fr_a5_3() );
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +020012265 execute( TC_assignment_fr_a5_4() );
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +020012266 execute( TC_assignment_fr_a5_4_fail() );
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +020012267 execute( TC_assignment_fr_a5_not_sup() );
Harald Welte3c86ea02018-05-10 22:28:05 +020012268 execute( TC_ciph_mode_a5_0() );
12269 execute( TC_ciph_mode_a5_1() );
Oliver Smith50b98122021-07-09 15:00:28 +020012270 execute( TC_ciph_mode_a5_2_0() );
Oliver Smith1dff88d2021-07-09 08:45:51 +020012271 execute( TC_ciph_mode_a5_2_1() );
Harald Welte3c86ea02018-05-10 22:28:05 +020012272 execute( TC_ciph_mode_a5_3() );
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +020012273 execute( TC_ciph_mode_a5_4() );
Harald Welte16a4adf2017-12-14 18:54:01 +010012274
Harald Welte60aa5762018-03-21 19:33:13 +010012275 execute( TC_assignment_codec_fr() );
Neels Hofmeyr559d5d02021-04-16 16:50:49 +020012276 execute( TC_assignment_codec_fr_by_mode_modify() );
Harald Welte60aa5762018-03-21 19:33:13 +010012277 execute( TC_assignment_codec_hr() );
12278 execute( TC_assignment_codec_efr() );
12279 execute( TC_assignment_codec_amr_f() );
12280 execute( TC_assignment_codec_amr_h() );
Philipp Maier8a581d22019-03-26 18:32:48 +010012281
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012282 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier8a581d22019-03-26 18:32:48 +010012283 execute( TC_assignment_codec_amr_f_S1() );
12284 execute( TC_assignment_codec_amr_h_S1() );
12285 execute( TC_assignment_codec_amr_f_S124() );
12286 execute( TC_assignment_codec_amr_h_S124() );
12287 execute( TC_assignment_codec_amr_f_S0() );
12288 execute( TC_assignment_codec_amr_f_S02() );
12289 execute( TC_assignment_codec_amr_f_S024() );
12290 execute( TC_assignment_codec_amr_f_S0247() );
12291 execute( TC_assignment_codec_amr_h_S0() );
12292 execute( TC_assignment_codec_amr_h_S02() );
12293 execute( TC_assignment_codec_amr_h_S024() );
12294 execute( TC_assignment_codec_amr_h_S0247() );
12295 execute( TC_assignment_codec_amr_f_S01234567() );
12296 execute( TC_assignment_codec_amr_f_S0234567() );
12297 execute( TC_assignment_codec_amr_f_zero() );
12298 execute( TC_assignment_codec_amr_f_unsupp() );
12299 execute( TC_assignment_codec_amr_h_S7() );
Neels Hofmeyr21863562020-11-26 00:34:33 +000012300 execute( TC_assignment_codec_amr_f_start_mode_auto() );
12301 execute( TC_assignment_codec_amr_h_start_mode_auto() );
Neels Hofmeyr3eb94562020-11-26 02:40:26 +000012302 execute( TC_assignment_codec_amr_f_start_mode_4() );
12303 execute( TC_assignment_codec_amr_h_start_mode_4() );
Neels Hofmeyr454d7922020-11-26 02:24:57 +000012304 execute( TC_assignment_codec_amr_startmode_cruft() );
Philipp Maier8a581d22019-03-26 18:32:48 +010012305 }
Harald Welte60aa5762018-03-21 19:33:13 +010012306
Philipp Maierac09bfc2019-01-08 13:41:39 +010012307 execute( TC_assignment_codec_fr_exhausted_req_hr() );
12308 execute( TC_assignment_codec_fr_exhausted_req_fr() );
12309 execute( TC_assignment_codec_fr_exhausted_req_fr_hr() );
12310 execute( TC_assignment_codec_fr_exhausted_req_hr_fr() );
12311 execute( TC_assignment_codec_hr_exhausted_req_fr() );
12312 execute( TC_assignment_codec_hr_exhausted_req_hr() );
12313 execute( TC_assignment_codec_hr_exhausted_req_hr_fr() );
12314 execute( TC_assignment_codec_hr_exhausted_req_fr_hr() );
12315 execute( TC_assignment_codec_req_hr_fr() );
12316 execute( TC_assignment_codec_req_fr_hr() );
Pau Espin Pedrol14475352021-07-22 15:48:16 +020012317 execute( TC_assignment_sdcch_exhausted_req_signalling() );
12318 execute( TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() );
12319 execute( TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() );
Philipp Maierac09bfc2019-01-08 13:41:39 +010012320
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +020012321 execute( TC_assignment_codec_hr_osmux_on() );
Pau Espin Pedrol23510fb2021-07-20 17:00:38 +020012322 execute( TC_assignment_osmux() );
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020012323 execute( TC_assignment_osmux_cn() );
12324 execute( TC_assignment_osmux_bts() );
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +020012325
Harald Welte898113b2018-01-31 18:32:21 +010012326 /* RLL Establish Indication on inactive DCHAN / SAPI */
Harald Welte5cd20ed2017-12-13 21:03:20 +010012327 execute( TC_rll_est_ind_inact_lchan() );
12328 execute( TC_rll_est_ind_inval_sapi1() );
12329 execute( TC_rll_est_ind_inval_sapi3() );
12330 execute( TC_rll_est_ind_inval_sacch() );
12331
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +070012332 /* DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
12333 execute( TC_tch_dlci_link_id_sapi() );
12334
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070012335 /* SAPI N Reject triggered by RLL establishment failures */
12336 execute( TC_rll_rel_ind_sapi_n_reject() );
12337 execute( TC_rll_err_ind_sapi_n_reject() );
12338 execute( TC_rll_timeout_sapi_n_reject() );
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +070012339 execute( TC_rll_sapi_n_reject_dlci_cc() );
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070012340
Harald Welte898113b2018-01-31 18:32:21 +010012341 /* Paging related tests */
Harald Welte6f521d82017-12-11 19:52:02 +010012342 execute( TC_paging_imsi_nochan() );
12343 execute( TC_paging_tmsi_nochan() );
12344 execute( TC_paging_tmsi_any() );
12345 execute( TC_paging_tmsi_sdcch() );
12346 execute( TC_paging_tmsi_tch_f() );
12347 execute( TC_paging_tmsi_tch_hf() );
12348 execute( TC_paging_imsi_nochan_cgi() );
12349 execute( TC_paging_imsi_nochan_lac_ci() );
12350 execute( TC_paging_imsi_nochan_ci() );
12351 execute( TC_paging_imsi_nochan_lai() );
12352 execute( TC_paging_imsi_nochan_lac() );
12353 execute( TC_paging_imsi_nochan_all() );
Harald Welte751d3eb2018-01-31 15:51:06 +010012354 execute( TC_paging_imsi_nochan_plmn_lac_rnc() );
12355 execute( TC_paging_imsi_nochan_rnc() );
12356 execute( TC_paging_imsi_nochan_lac_rnc() );
12357 execute( TC_paging_imsi_nochan_lacs() );
12358 execute( TC_paging_imsi_nochan_lacs_empty() );
Stefan Sperling049a86e2018-03-20 15:51:00 +010012359 execute( TC_paging_imsi_nochan_cgi_unknown_cid() );
Harald Welte10985002017-12-12 09:29:15 +010012360 execute( TC_paging_imsi_a_reset() );
Harald Weltee65d40e2017-12-13 00:09:06 +010012361 execute( TC_paging_imsi_load() );
Philipp Maier779a7922018-02-16 11:00:37 +010012362 execute( TC_paging_counter() );
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +010012363 execute( TC_paging_resp_unsol() );
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +020012364 execute( TC_paging_500req() );
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +020012365 execute( TC_paging_450req_no_paging_load_ind() );
Pau Espin Pedrol07657ae2023-01-03 12:08:05 +010012366 execute( TC_paging_imsi_nochan_ci_resp_invalid_mi() );
Harald Welte4e9b9cc2017-12-14 18:31:02 +010012367
12368 execute( TC_rsl_drop_counter() );
Stefan Sperling830dc9d2018-02-12 21:08:28 +010012369 execute( TC_rsl_unknown_unit_id() );
12370
12371 execute( TC_oml_unknown_unit_id() );
Harald Welte898113b2018-01-31 18:32:21 +010012372
12373 execute( TC_classmark() );
Harald Welteeddf0e92020-06-21 19:42:15 +020012374 execute( TC_common_id() );
Harald Welte898113b2018-01-31 18:32:21 +010012375 execute( TC_unsol_ass_fail() );
Harald Welteea99a002018-01-31 20:46:43 +010012376 execute( TC_unsol_ass_compl() );
Harald Weltefbf9b5e2018-01-31 20:41:23 +010012377 execute( TC_unsol_ho_fail() );
Harald Weltee3bd6582018-01-31 22:51:25 +010012378 execute( TC_err_82_short_msg() );
Harald Weltee9e02e42018-01-31 23:36:25 +010012379 execute( TC_err_84_unknown_msg() );
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012380
Harald Welte261af4b2018-02-12 21:20:39 +010012381 execute( TC_ho_int() );
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +020012382 execute( TC_ho_int_a5_0() );
12383 execute( TC_ho_int_a5_1() );
12384 execute( TC_ho_int_a5_3() );
12385 execute( TC_ho_int_a5_4() );
Neels Hofmeyr5f144212020-11-03 15:41:58 +000012386 execute( TC_ho_int_radio_link_failure() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012387
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012388 /* TC_ho_out_of_this_bsc is run last, see comment below */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +020012389 execute( TC_ho_out_fail_no_msc_response() );
12390 execute( TC_ho_out_fail_rr_ho_failure() );
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +020012391 execute( TC_ho_out_fail_no_result_after_ho_cmd() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012392
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012393 execute( TC_ho_into_this_bsc() );
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +020012394 execute( TC_ho_into_this_bsc_a5_0() );
12395 execute( TC_ho_into_this_bsc_a5_1() );
12396 execute( TC_ho_into_this_bsc_a5_3() );
12397 execute( TC_ho_into_this_bsc_a5_4() );
Neels Hofmeyr93182e02022-02-17 21:59:07 +010012398 execute( TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() );
12399 execute( TC_ho_into_this_bsc_a5_1_3() );
Neels Hofmeyr907b23b2022-02-17 21:58:47 +010012400 execute( TC_ho_into_this_bsc_a5_mismatch() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020012401 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12402 execute( TC_ho_into_this_bsc_tla_v6() );
12403 }
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +020012404 execute( TC_srvcc_eutran_to_geran() );
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +030012405 execute( TC_srvcc_eutran_to_geran_a5_3() );
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +010012406 execute( TC_srvcc_eutran_to_geran_src_sai() );
Pau Espin Pedrol35801c32021-04-19 13:03:20 +020012407 execute( TC_srvcc_eutran_to_geran_ho_out() );
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +020012408 execute( TC_srvcc_eutran_to_geran_forbid_fast_return() );
12409 execute( TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012410 execute( TC_ho_in_fail_msc_clears() );
12411 execute( TC_ho_in_fail_msc_clears_after_ho_detect() );
12412 execute( TC_ho_in_fail_no_detect() );
12413 execute( TC_ho_in_fail_no_detect2() );
Oliver Smith7a8594a2023-02-13 14:30:49 +010012414 execute( TC_ho_in_fail_mgw_mdcx_timeout() );
Oliver Smith4eed06f2023-02-15 15:43:19 +010012415 execute( TC_ho_in_fail_ipa_crcx_timeout() );
Neels Hofmeyra23f3b12022-03-02 19:57:12 +010012416 execute( TC_ho_into_this_bsc_sccp_cr_without_bssap() );
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012417
Neels Hofmeyr91401012019-07-11 00:42:35 +020012418 execute( TC_ho_neighbor_config_1() );
12419 execute( TC_ho_neighbor_config_2() );
12420 execute( TC_ho_neighbor_config_3() );
12421 execute( TC_ho_neighbor_config_4() );
12422 execute( TC_ho_neighbor_config_5() );
12423 execute( TC_ho_neighbor_config_6() );
12424 execute( TC_ho_neighbor_config_7() );
12425
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012426 execute( TC_bssap_rlsd_does_not_cause_bssmap_reset() );
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010012427 execute( TC_bssmap_clear_does_not_cause_bssmap_reset() );
Neels Hofmeyrfd445c32018-03-09 15:39:31 +010012428 execute( TC_ms_rel_ind_does_not_cause_bssmap_reset() );
Harald Welte94e0c342018-04-07 11:33:23 +020012429
12430 execute( TC_dyn_pdch_ipa_act_deact() );
12431 execute( TC_dyn_pdch_ipa_act_nack() );
12432 execute( TC_dyn_pdch_osmo_act_deact() );
12433 execute( TC_dyn_pdch_osmo_act_nack() );
Pau Espin Pedrol37a4c152021-11-16 19:02:23 +010012434 execute( TC_dyn_ts_sdcch8_act_deact() );
12435 execute( TC_dyn_ts_sdcch8_all_subslots_used() );
12436 execute( TC_dyn_ts_sdcch8_tch_call_act_deact() );
12437 execute( TC_dyn_ts_sdcch8_act_nack() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012438
Stefan Sperling0796a822018-10-05 13:01:39 +020012439 execute( TC_chopped_ipa_ping() );
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +020012440 execute( TC_chopped_ipa_payload() );
Stefan Sperling0796a822018-10-05 13:01:39 +020012441
Pau Espin Pedrol8f773632019-11-05 11:46:53 +010012442 /* Power control related */
12443 execute( TC_assignment_verify_ms_power_params_ie() );
Vadim Yanitskiy4b233042021-06-30 00:58:43 +020012444 execute( TC_c0_power_red_mode() );
Neels Hofmeyr4f118412020-06-04 15:25:10 +020012445
12446 /* MSC pooling */
12447 /* FIXME: in SCCPlite, indicating how many MSCs should be connected does currently not work. Since
12448 * RESET->RESET-ACK is unconditionally negotiated for all configured MSCs, they always all appear as connected
12449 * to osmo-bsc. The MSC pooling tests however require disconnecting selected MSCs, and hence don't work out as
12450 * intended on SCCPlite. So for now, run these only for SCCP/M3UA. */
12451 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12452 execute( TC_mscpool_L3Compl_on_1_msc() );
12453 execute( TC_mscpool_L3Complete_by_imsi_round_robin() );
12454 execute( TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() );
12455 execute( TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() );
12456 execute( TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() );
12457 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() );
12458 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_1() );
12459 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_2() );
12460 execute( TC_mscpool_LU_by_tmsi_from_other_PLMN() );
12461 execute( TC_mscpool_paging_and_response_imsi() );
12462 execute( TC_mscpool_paging_and_response_tmsi() );
12463 execute( TC_mscpool_no_allow_attach_round_robin() );
12464 execute( TC_mscpool_no_allow_attach_valid_nri() );
12465 }
12466
Harald Welte99f3ca02018-06-14 13:40:29 +020012467 execute( TC_early_conn_fail() );
12468 execute( TC_late_conn_fail() );
Oliver Smithaf03bef2021-08-24 15:34:51 +020012469 execute( TC_stats_conn_fail() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012470
Philipp Maier783681c2020-07-16 16:47:06 +020012471 /* Emergency call handling (deny / allow) */
12472 execute( TC_assignment_emerg_setup_allow() );
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +010012473 execute( TC_assignment_emerg_setup_allow_imei() );
Philipp Maier783681c2020-07-16 16:47:06 +020012474 execute( TC_assignment_emerg_setup_deny_msc() );
12475 execute( TC_assignment_emerg_setup_deny_bts() );
Philipp Maier82812002020-08-13 18:48:27 +020012476 execute( TC_emerg_premption() );
12477
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +070012478 /* Frequency hopping parameters handling */
12479 execute( TC_fh_params_chan_activ() );
12480 execute( TC_fh_params_imm_ass() );
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070012481 execute( TC_fh_params_assignment_cmd() );
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070012482 execute( TC_fh_params_handover_cmd() );
Vadim Yanitskiyca974032020-09-01 07:20:39 +070012483 execute( TC_fh_params_si4_cbch() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012484
12485 if (mp_enable_lcs_tests) {
12486 execute( TC_lcs_loc_req_for_active_ms() );
12487 execute( TC_lcs_loc_req_for_active_ms_ta_req() );
12488 execute( TC_lcs_loc_req_for_idle_ms() );
12489 execute( TC_lcs_loc_req_no_subscriber() );
12490 execute( TC_lcs_loc_req_for_active_ms_le_timeout() );
12491 execute( TC_lcs_loc_req_for_active_ms_le_timeout2() );
12492 execute( TC_lcs_loc_req_for_idle_ms_no_pag_resp() );
12493 execute( TC_cm_service_during_lcs_loc_req() );
12494 execute( TC_ho_during_lcs_loc_req() );
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020012495 execute( TC_emerg_call_and_lcs_loc_req() );
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020012496 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() );
12497 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012498 }
Neels Hofmeyrbf037052020-10-28 22:52:02 +000012499
12500 execute( TC_no_msc() );
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000012501
12502 execute( TC_refuse_chan_act_to_vamos() );
12503 execute( TC_refuse_mode_modif_to_vamos() );
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000012504
12505 execute( TC_reassignment_fr() );
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020012506
12507 execute( TC_cm_reestablishment() );
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020012508
12509 execute( TC_imm_ass_post_chan_ack() );
12510 execute( TC_imm_ass_pre_chan_ack() );
Neels Hofmeyr23158742021-09-07 19:08:07 +020012511 execute( TC_imm_ass_pre_ts_ack() );
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020012512 execute( TC_imm_ass_pre_chan_ack_dyn_ts() );
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020012513 execute( TC_imm_ass_pre_ts_ack_dyn_ts() );
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020012514
12515 execute( TC_ctrl_trx_rf_locked() );
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012516
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020012517 execute( TC_ratectr_all_available_allocated() );
12518 execute( TC_ratectr_all_available_allocated_dyn() );
12519
Neels Hofmeyrb7581872021-11-07 14:02:49 +010012520 execute( TC_cm_serv_rej() );
12521
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012522 execute( TC_lost_sdcch_during_assignment() );
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012523
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012524 /* Channel allocator */
12525 execute( TC_chan_alloc_algo_ascending() );
12526 execute( TC_chan_alloc_algo_descending() );
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012527 execute( TC_chan_alloc_algo_ass_dynamic() );
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012528
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012529 /* MGW pool */
Pau Espin Pedrol4e431832023-02-08 12:43:47 +010012530 execute( TC_mgwpool_all_used() );
12531 execute( TC_mgwpool_blocked_not_used() );
12532 execute( TC_mgwpool_pin_bts() );
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012533
Oliver Smithc9a5f532022-10-21 11:32:23 +020012534 execute( TC_ho_meas_rep_multi_band() );
12535
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012536 /* Run TC_ho_out_of_this_bsc last, because it may trigger a segfault before osmo-bsc's patch
12537 * with change-id I5a3345ab0005a73597f5c27207480912a2f5aae6 */
12538 execute( TC_ho_out_of_this_bsc() );
Harald Welte28d943e2017-11-25 15:00:50 +010012539}
12540
12541}