blob: bfab0fa4dc8fcc4220256f447842517dcb756c8e [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
Oliver Smith15890b42023-03-08 14:12:28 +01002098 /* Establish SDCCH (invalid DataIndicator for exp_fail) */
Oliver Smithaf03bef2021-08-24 15:34:51 +02002099 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
Oliver Smith15890b42023-03-08 14:12:28 +01002100 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := 'ff'O;
Oliver Smithaf03bef2021-08-24 15:34:51 +02002101 f_establish_fully(ass_cmd, exp_fail);
2102
2103 /* Expect stats to be 0 */
2104 var StatsDExpects expect := {
2105 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 0, max := 0},
2106 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 0, max := 0}
2107 };
2108 f_statsd_expect(expect);
2109
2110 /* Simulate CONN FAIL IND on SDCCH */
2111 RSL.send(ts_ASP_RSL_UD(
2112 ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL),
2113 IPAC_PROTO_RSL_TRX0));
2114
Neels Hofmeyr58be48a2021-09-07 18:39:21 +02002115 f_sleep(1.0);
2116
Oliver Smithaf03bef2021-08-24 15:34:51 +02002117 /* Expect stats to be 1 */
2118 expect := {
2119 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 1, max := 1},
2120 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 1, max := 1}
2121 };
2122 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002123 BSSAP.receive(tr_BSSMAP_ClearRequest);
2124 f_perform_clear();
Oliver Smithaf03bef2021-08-24 15:34:51 +02002125}
2126testcase TC_stats_conn_fail() runs on test_CT {
2127 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2128 var MSC_ConnHdlr vc_conn;
2129
2130 f_init(1, true);
2131 f_sleep(1.0);
2132
2133 vc_conn := f_start_handler(refers(f_TC_stats_conn_fail), pars);
2134 vc_conn.done;
2135
2136 f_shutdown_helper();
2137}
2138
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002139function f_expect_chan_rel(RslChannelNr rsl_chan_nr,
2140 BtsTrxIdx idx := {0, 0},
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002141 boolean expect_deact_sacch := true,
2142 boolean expect_rr_chan_rel := true,
2143 boolean expect_rll_rel_req := true,
Harald Welte99787102019-02-04 10:41:36 +01002144 boolean handle_rll_rel := true,
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002145 template CellSelIndValue expect_cells := omit,
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002146 template (present) RR_Cause expect_rr_cause := ?
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002147 ) runs on test_CT {
Harald Welte91d54a52018-01-28 15:35:07 +01002148
2149 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002150 var boolean got_deact_sacch := false;
2151 var boolean got_rr_chan_rel := false;
2152 var boolean got_rll_rel_req := false;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002153 var ASP_RSL_Unitdata ud;
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002154 var RSL_IE_Body l3_ie;
2155 var PDU_ML3_NW_MS l3;
2156 var RR_Cause got_cause;
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002157 log("f_expect_chan_rel() expecting: expect_deact_sacch=", expect_deact_sacch, " expect_rr_chan_rel=", expect_rr_chan_rel,
2158 " expect_rll_rel_req=", expect_rll_rel_req);
Harald Welte91d54a52018-01-28 15:35:07 +01002159 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002160 [] 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 +01002161 got_deact_sacch := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002162 repeat;
2163 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002164 [] 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 +01002165 got_rr_chan_rel := true;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002166
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002167 if (f_rsl_find_ie(ud.rsl, RSL_IE_L3_INFO, l3_ie) == false) {
2168 setverdict(fail, "cannot find L3");
2169 mtc.stop;
2170 }
2171 l3 := dec_PDU_ML3_NW_MS(l3_ie.l3_info.payload);
2172
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002173 if (not istemplatekind(expect_cells, "omit")) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002174 var CellSelIndValue cells := dec_CellSelIndValue(
2175 l3.msgs.rrm.channelRelease.cellSelectionIndicator.cellSelectionIndicatorValue);
2176
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002177 log("GOT RR CHANNEL RELEASE WITH CELLS: ", cells);
2178 if (match(cells, expect_cells)) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002179 setverdict(pass);
2180 } else {
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002181 log("EXPECTED CELLS: ", expect_cells);
2182 setverdict(fail, "Received cells list on RR Channel Release does not match expectations");
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002183 }
2184 }
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002185
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002186 int2enum(oct2int(l3.msgs.rrm.channelRelease.rRCause.valuePart), got_cause);
2187 log("GOT CAUSE CODE: ", l3.msgs.rrm.channelRelease.rRCause.valuePart, " = ", got_cause);
2188 if (match(got_cause, expect_rr_cause)) {
2189 setverdict(pass);
2190 } else {
2191 log("EXPECTED CAUSE CODE: ", expect_rr_cause);
2192 setverdict(fail, "Received RR Channel Release Cause code does not match expectations");
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002193 }
Harald Welte99787102019-02-04 10:41:36 +01002194 repeat;
2195 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002196 [] 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 +01002197 got_rll_rel_req := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002198 /* FIXME: Why are we getting this for LinkID SACCH? */
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002199 if (handle_rll_rel) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002200 f_ipa_tx(ts_RSL_REL_CONF(rsl_chan_nr, main_dcch));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002201 }
Harald Welte91d54a52018-01-28 15:35:07 +01002202 repeat;
2203 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002204 [] 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 +01002205 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002206 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(rsl_chan_nr));
Harald Welte91d54a52018-01-28 15:35:07 +01002207 }
2208 /* ignore any user data */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002209 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeR(?))) {
Harald Welte91d54a52018-01-28 15:35:07 +01002210 repeat;
2211 }
2212 }
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002213
2214 log("f_expect_chan_rel() summary: got_deact_sacch=", got_deact_sacch, " got_rr_chan_rel=", got_rr_chan_rel,
2215 " got_rll_rel_req=", got_rll_rel_req);
2216
2217 if (expect_deact_sacch != got_deact_sacch) {
2218 setverdict(fail, "f_expect_chan_rel(): expect_deact_sacch=", expect_deact_sacch, " got_deact_sacch=", got_deact_sacch);
2219 }
2220 if (expect_rr_chan_rel != got_rr_chan_rel) {
2221 setverdict(fail, "f_expect_chan_rel(): expect_rr_chan_rel=", expect_rr_chan_rel, " got_rr_chan_rel=", got_rr_chan_rel);
2222 }
2223 if (expect_rll_rel_req != got_rll_rel_req) {
2224 setverdict(fail, "f_expect_chan_rel(): expect_rll_rel_req=", expect_rll_rel_req, " got_rll_rel_req=", got_rll_rel_req);
2225 }
Harald Welte91d54a52018-01-28 15:35:07 +01002226}
2227
Harald Welte4003d112017-12-09 22:35:39 +01002228/* Test behavior of channel release after hard Clear Command from MSC */
2229testcase TC_chan_rel_hard_clear() runs on test_CT {
2230 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002231 var DchanTuple dt;
Harald Welte4003d112017-12-09 22:35:39 +01002232
Harald Welte89d42e82017-12-17 16:42:41 +01002233 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002234
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002235 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002236
2237 /* Instruct BSC to clear channel */
2238 var BssmapCause cause := 0;
2239 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2240
2241 /* expect Clear Complete from BSC on A */
2242 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2243 /* release the SCCP connection */
2244 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2245 }
2246
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002247 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002248 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002249}
2250
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002251function f_TC_chan_rel_last_eutran_plmn_hard_clear(boolean tx_csfb_ind) runs on test_CT {
2252 var BSSAP_N_DATA_ind rx_di;
2253 var DchanTuple dt;
2254
2255 f_init(1);
2256
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002257 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002258 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2259 /* yet when generating the EUTRAN neigh list in RR CHannel Release) */
2260 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
2261
2262 /* Instruct BSC to clear channel */
2263 var BssmapCause cause := 0;
2264 if (tx_csfb_ind) {
2265 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2266 } else {
2267 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2268 }
2269
2270 /* expect Clear Complete from BSC on A */
2271 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2272 /* release the SCCP connection */
2273 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2274 }
2275
2276 /* 1 neighbor is added by default in osmo-bts.cfg and
2277 SystemInformationConfig_default, use that: */
2278 var template CellSelIndValue exp_cells := f_tr_rr_chan_rel_earfcns(1);
2279
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002280 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 +02002281 f_shutdown_helper();
2282}
2283
2284/* Test behavior of RR Channel rRelease after Clear Command without CSFB indicator
2285 from MSC, previously receiving any CommonID containing the "Last Used E-UTRAN
2286 PLMN Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2287 EUTRAN neighbor list sent later on by BSC in RR Channel, so receiving CSFB
2288 Indicator or not shouldn't matter at all. */
2289testcase TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() runs on test_CT {
2290 f_TC_chan_rel_last_eutran_plmn_hard_clear(false);
2291}
2292
2293/* Test behavior of RR Channel rRelease after Clear Command with CSFB indicator from
2294 MSC, previously receiving any CommonID containing the "Last Used E-UTRAN PLMN
2295 Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2296 EUTRAN neighbor list sent later on by BSC in RR Channel. */
2297testcase TC_chan_rel_last_eutran_plmn_hard_clear_csfb() runs on test_CT {
2298 f_TC_chan_rel_last_eutran_plmn_hard_clear(true);
2299}
2300
2301/* Test behavior of RR Channel Release after Clear Command with CSFB indicator from
2302 MSC, without receiving any CommonID containing the "Last Used E-UTRAN PLMN
2303 Id". According to spec (TS 48.008 version 16.0.0 Release 16 "3.2.1.21") the
2304 CSFB Indicator should not be used anymore, and hence, there should be no
2305 EUTRAN neighbor list sent by BSC in RR Channel release since no CommonId with
2306 Last Used E-UTRAN PLMN Id" IE was sent for this conn. */
Harald Welte99787102019-02-04 10:41:36 +01002307testcase TC_chan_rel_hard_clear_csfb() runs on test_CT {
2308 var BSSAP_N_DATA_ind rx_di;
2309 var DchanTuple dt;
2310
2311 f_init(1);
2312
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002313 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte99787102019-02-04 10:41:36 +01002314
2315 /* Instruct BSC to clear channel */
2316 var BssmapCause cause := 0;
2317 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2318
2319 /* expect Clear Complete from BSC on A */
2320 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2321 /* release the SCCP connection */
2322 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2323 }
2324
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002325 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002326 f_shutdown_helper();
Harald Welte99787102019-02-04 10:41:36 +01002327}
2328
Harald Welted8c36cd2017-12-09 23:05:31 +01002329/* Test behavior of channel release after hard RLSD from MSC */
2330testcase TC_chan_rel_hard_rlsd() runs on test_CT {
Harald Welted8c36cd2017-12-09 23:05:31 +01002331 var DchanTuple dt;
Harald Welted8c36cd2017-12-09 23:05:31 +01002332
Harald Welte89d42e82017-12-17 16:42:41 +01002333 f_init(1);
Harald Welted8c36cd2017-12-09 23:05:31 +01002334
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002335 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welted8c36cd2017-12-09 23:05:31 +01002336
2337 /* release the SCCP connection */
2338 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2339
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002340 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002341 f_shutdown_helper();
Harald Welted8c36cd2017-12-09 23:05:31 +01002342}
2343
Harald Welte550daf92018-06-11 19:22:13 +02002344/* Test behavior of channel release after hard RLSD from MSC and MS is not responding to RLL REL REQ */
2345testcase TC_chan_rel_hard_rlsd_ms_dead() runs on test_CT {
2346 var DchanTuple dt;
2347
2348 f_init(1);
2349
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002350 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte550daf92018-06-11 19:22:13 +02002351
2352 /* release the SCCP connection */
2353 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2354
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002355 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002356 f_shutdown_helper();
Harald Welte550daf92018-06-11 19:22:13 +02002357}
2358
Harald Welte85804d42017-12-10 14:11:58 +01002359/* Test behavior of channel release after BSSMAP RESET from MSC */
2360testcase TC_chan_rel_a_reset() runs on test_CT {
Harald Welte85804d42017-12-10 14:11:58 +01002361 var DchanTuple dt;
Harald Welte85804d42017-12-10 14:11:58 +01002362
Harald Welte89d42e82017-12-17 16:42:41 +01002363 f_init(1);
Harald Welte85804d42017-12-10 14:11:58 +01002364
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002365 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte85804d42017-12-10 14:11:58 +01002366
2367 /* Clear the queue, it might still contain stuff like IMMEDIATE ASSIGN */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002368 IPA_RSL[0][0].clear;
Harald Welte85804d42017-12-10 14:11:58 +01002369
2370 /* perform BSSAP RESET, expect RESET ACK and DISC.ind on connection */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002371 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 +01002372 interleave {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002373 [] 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 +01002374 [] BSSAP.receive(tr_BSSAP_DISC_ind(dt.sccp_conn_id, ?, ?)) { }
2375 }
2376
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002377 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002378 f_shutdown_helper();
Harald Welte85804d42017-12-10 14:11:58 +01002379}
2380
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002381/* Verify T(iar) triggers and releases the channel */
2382testcase TC_chan_rel_sccp_tiar_timeout() runs on test_CT {
2383 var DchanTuple dt;
2384
2385 /* Set T(iar) in BSC low enough that it will trigger before other side
2386 has time to keep alive with a T(ias). Keep recommended ratio of
2387 T(iar) >= T(ias)*2 */
2388 g_bsc_sccp_timer_ias := 2;
2389 g_bsc_sccp_timer_iar := 5;
2390
2391 f_init(1);
2392
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002393 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002394 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002395 f_shutdown_helper();
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002396}
2397
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002398private function f_tc_chan_rel_rr_cause(myBSSMAP_Cause clear_cmd_cause,
2399 template (present) RR_Cause expect_rr_cause)
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002400runs on test_CT
2401{
2402 var DchanTuple dt;
2403
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002404 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002405 var BssmapCause cause := 0;
2406 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(clear_cmd_cause))));
2407 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2408 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2409 }
2410
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002411 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 +02002412}
2413
2414/* Test that Clear Command cause codes affect the RR Channel Release cause code */
2415testcase TC_chan_rel_rr_cause() runs on test_CT {
2416 f_init(1);
2417
2418 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_CALL_CONTROL, GSM48_RR_CAUSE_NORMAL);
2419 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_HANDOVER_SUCCESSFUL, GSM48_RR_CAUSE_NORMAL);
2420 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_PREEMPTION, GSM48_RR_CAUSE_PREMPTIVE_REL);
2421 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, GSM48_RR_CAUSE_PROT_ERROR_UNSPC);
2422 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
2423 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_EQUIPMENT_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
Vadim Yanitskiye18aebb2021-01-03 13:10:43 +01002424
2425 f_shutdown_helper();
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002426}
2427
Harald Welte5cd20ed2017-12-13 21:03:20 +01002428/* Test behavior if RSL EST IND for non-active channel */
2429testcase TC_rll_est_ind_inact_lchan() runs on test_CT {
2430 timer T := 2.0;
2431
Harald Welte89d42e82017-12-17 16:42:41 +01002432 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002433
Harald Welte5cd20ed2017-12-13 21:03:20 +01002434 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002435 var octetstring l3_payload := gen_l3_valid_payload();
2436 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002437
2438 T.start;
2439 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002440 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002441 setverdict(fail, "MSC received COMPL L3 for non-active lchan");
2442 }
2443 [] BSSAP.receive {}
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002444 [] IPA_RSL[0][0].receive {}
Harald Welte5cd20ed2017-12-13 21:03:20 +01002445 [] T.timeout {}
2446 }
2447
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002448 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002449}
2450
2451/* Test behavior if RSL EST IND for invalid SAPI */
2452testcase TC_rll_est_ind_inval_sapi1() runs on test_CT {
2453 var RslChannelNr chan_nr;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002454 var octetstring l3_payload;
Harald Welte5cd20ed2017-12-13 21:03:20 +01002455
Harald Welte89d42e82017-12-17 16:42:41 +01002456 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002457
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002458 chan_nr := f_chreq_act_ack();
2459 l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002460
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002461 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(1)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002462
2463 timer T := 2.0;
2464 T.start;
2465 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002466 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002467 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 1");
2468 }
2469 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002470 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002471 [] T.timeout {}
2472 }
2473
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002474 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002475}
2476
2477/* Test behavior if RSL EST IND for invalid SAPI */
2478testcase TC_rll_est_ind_inval_sapi3() runs on test_CT {
2479 timer T := 2.0;
2480
Harald Welte89d42e82017-12-17 16:42:41 +01002481 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002482
2483 var RslChannelNr chan_nr := f_chreq_act_ack();
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002484 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002485
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002486 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(3)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002487
2488 T.start;
2489 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002490 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002491 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 3");
2492 }
2493 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002494 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002495 [] T.timeout {}
2496 }
2497
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002498 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002499}
2500
2501/* Test behavior if RSL EST IND for invalid SACCH */
2502testcase TC_rll_est_ind_inval_sacch() runs on test_CT {
2503 timer T := 2.0;
2504
Harald Welte89d42e82017-12-17 16:42:41 +01002505 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002506
2507 var RslChannelNr chan_nr := f_chreq_act_ack();
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002508 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002509
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002510 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_SACCH(0)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002511
2512 T.start;
2513 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002514 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002515 setverdict(fail, "MSC received COMPL L3 for invalid Link SACCH");
2516 }
2517 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002518 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002519 [] T.timeout {}
2520 }
2521
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002522 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002523}
2524
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002525/* Verify DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
2526private function f_TC_tch_dlci_link_id_sapi(charstring id) runs on MSC_ConnHdlr {
2527 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
2528 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2529
2530 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
2531 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
2532
2533 f_establish_fully(ass_cmd, exp_compl);
2534
2535 /* SAPI0 has already been established by f_establish_fully(), establish SAPI3 */
2536 RSL.send(ts_RSL_EST_IND(g_chan_nr, ts_RslLinkID_SACCH(3), '0904'O));
2537 /* Expect BSSAP/DTAP on SAPI3 (DLCI IE) */
2538 BSSAP.receive(PDU_BSSAP:{
2539 discriminator := '1'B,
2540 spare := '0000000'B,
2541 dlci := 'C3'O,
2542 lengthIndicator := ?,
2543 pdu := { dtap := '0904'O }
2544 });
2545
2546 /* Send messages on DCCH/SAPI0 and ACCH/SAPI3 */
2547 for (var integer i := 0; i < 32; i := i + 1) {
2548 var octetstring l3 := '09'O & f_rnd_octstring(14);
2549 var template (value) RslLinkId link_id;
2550 var template (value) OCT1 dlci;
2551
2552 if (i mod 2 == 0) {
2553 /* SAPI0 on FACCH or SDCCH */
2554 link_id := ts_RslLinkID_DCCH(0);
2555 dlci := '80'O;
2556 } else {
2557 /* SAPI3 on SACCH */
2558 link_id := ts_RslLinkID_SACCH(3);
2559 dlci := 'C3'O;
2560 }
2561
2562 /* Send MO message: RSL -> BSSAP */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002563 f_mo_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002564 /* Send MT message: BSSAP -> RSL */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002565 f_mt_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002566 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002567 f_perform_clear();
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002568}
2569testcase TC_tch_dlci_link_id_sapi() runs on test_CT {
2570 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2571 var MSC_ConnHdlr vc_conn;
2572
2573 f_init(1, true);
2574 f_sleep(1.0);
2575
2576 vc_conn := f_start_handler(refers(f_TC_tch_dlci_link_id_sapi), pars);
2577 vc_conn.done;
2578
2579 f_shutdown_helper();
2580}
2581
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002582private function f_exp_sapi_n_reject(template (present) GsmSapi sapi := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002583 template (present) myBSSMAP_Cause cause := ?,
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002584 template (present) BIT2 cc := ?,
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002585 float T_val := 2.0)
2586runs on test_CT {
2587 var BSSAP_N_DATA_ind rx_di;
2588 timer T;
2589
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002590 var template (present) BSSMAP_IE_Cause tr_cause := tr_BSSMAP_IE_Cause(cause);
2591 var template (present) PDU_BSSAP tr_pdu := tr_BSSMAP_SAPInReject(sapi);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002592
2593 T.start(T_val);
2594 alt {
2595 [] BSSAP.receive(tr_BSSAP_DATA_ind(?, tr_pdu)) -> value rx_di {
2596 var BSSMAP_IE_Cause rx_cause := rx_di.userData.pdu.bssmap.sAPInReject.cause;
2597 if (not match(rx_cause, tr_cause)) {
2598 setverdict(fail, "Rx unexpected Cause IE: ",
2599 rx_cause, " vs expected ", tr_cause);
2600 }
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002601
2602 /* Who ever on the earth decided to define this field as two separate bits?!? */
2603 var BIT2 rx_cc := rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c2
2604 & rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c1;
2605 if (not match(rx_cc, cc)) {
2606 setverdict(fail, "Rx unexpected Control Channel type: ",
2607 rx_cc, " vs expected ", cc);
2608 }
2609
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002610 setverdict(pass);
2611 }
2612 [] BSSAP.receive(BSSAP_N_DATA_ind:?) -> value rx_di {
2613 setverdict(fail, "Rx unexpected BSSAP PDU: ", rx_di);
2614 }
2615 [] T.timeout {
2616 setverdict(fail, "Timeout waiting for BSSMAP SAPI N Reject");
2617 }
2618 }
2619}
2620
2621/* Check if we get SAPI N Reject on receipt of unexpected RLL RELease INDication */
2622testcase TC_rll_rel_ind_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002623 var RSL_Message rx_rsl;
2624 var DchanTuple dt;
2625
2626 f_init(1);
2627
2628 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002629 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002630
2631 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002632 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 +07002633 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002634 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 +07002635
2636 /* MS sends unexpected RELease INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002637 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002638 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2639 f_exp_sapi_n_reject(3, GSM0808_CAUSE_MS_NOT_EQUIPPED);
2640
2641 /* Clean up the connection */
2642 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002643 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002644
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002645 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002646}
2647
2648/* Check if we get SAPI N Reject on receipt of unexpected RLL ERROR INDication */
2649testcase TC_rll_err_ind_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002650 var RSL_Message rx_rsl;
2651 var DchanTuple dt;
2652
2653 f_init(1);
2654
2655 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002656 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002657
2658 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002659 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 +07002660 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002661 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 +07002662
2663 /* BTS sends unexpected ERROR INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002664 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002665 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2666 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED);
2667
2668 /* Clean up the connection */
2669 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002670 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002671
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002672 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002673}
2674
2675/* Check if we get SAPI N Reject due to a SAPI=3 link establishment timeout */
2676testcase TC_rll_timeout_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002677 var RSL_Message rx_rsl;
2678 var DchanTuple dt;
2679
2680 f_init(1);
2681
2682 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002683 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002684
2685 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002686 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 +07002687 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002688 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 +07002689
2690 /* MS does not respond, so the link establishment timeout triggers SAPI N Reject */
2691 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, T_val := 8.0);
2692
2693 /* Clean up the connection */
2694 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002695 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002696
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002697 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002698}
2699
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002700/* Check DLCI CC (Control Channel type) bits in SAPI N Reject */
2701testcase TC_rll_sapi_n_reject_dlci_cc() runs on test_CT {
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002702 var RSL_Message rx_rsl;
2703 var DchanTuple dt;
2704
2705 f_init(1);
2706
2707 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002708 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002709
2710 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002711 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 +07002712 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002713 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 +07002714
2715 /* MS sends unexpected ERROR INDication on DCCH/ACCH SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002716 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Pau Espin Pedrol121f27f2022-01-12 12:02:10 +01002717 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, '10'B);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002718
2719 /* Clean up the connection */
2720 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002721 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002722
2723 f_shutdown_helper();
2724}
2725
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002726testcase TC_si_default() runs on test_CT {
2727 f_init(0);
2728 f_init_bts_and_check_sysinfo(0, expect_si := SystemInformationConfig_default);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002729 f_shutdown_helper();
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002730}
Harald Welte4003d112017-12-09 22:35:39 +01002731
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002732/* We're testing SI2quater with lists of EARFCNs. Instead of just incrementing EARFCNs, also pick some from the edges of
2733 * the entire value range. This function provides the same EARFCN numbers for the same earfcn_index */
2734private function f_test_si2quater_earfcn_by_idx(integer earfcn_index) return uint16_t
2735{
2736 select (earfcn_index) {
2737 case (0) {
2738 /* E-ARFCN 111 is already added in the osmo-bsc.cfg */
2739 return 111;
2740 }
2741 case (1) {
2742 return 1;
2743 }
2744 case (2) {
2745 return 0;
2746 }
2747 case (3) {
2748 return 65535;
2749 }
2750 case else {
2751 return 23 * (earfcn_index - 3);
2752 }
2753 }
2754}
2755
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002756function f_test_si2quater(integer total_earfcns, template SystemInformationConfig expect_si,
2757 template CellSelIndValue expect_cells := omit) runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002758
2759 f_init(0);
2760
2761 /* E-ARFCN 111 is already added in the osmo-bsc.cfg, so only add more arfcns if total_earfcns > 1 */
2762 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002763 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2764 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002765 }
2766
2767 f_init_bts_and_check_sysinfo(0, expect_si := expect_si);
2768
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002769 if (not istemplatekind(expect_cells, "omit")) {
2770 /* Also check that RR Channel Release contains these EARFCNs.
2771 * (copied code from TC_chan_rel_hard_clear_csfb) */
2772 var BSSAP_N_DATA_ind rx_di;
2773 var DchanTuple dt;
2774
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002775 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Pau Espin Pedrold0046312021-04-19 16:35:58 +02002776 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2777 * yet when generating the EUTRAN neigh list in RR CHannel Release) */
2778 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002779
2780 /* Instruct BSC to clear channel */
2781 var BssmapCause cause := 0;
2782 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2783
2784 /* expect Clear Complete from BSC on A */
2785 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2786 /* release the SCCP connection */
2787 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2788 }
2789
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002790 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false, expect_cells := expect_cells);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002791 }
2792
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002793 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002794 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 +02002795 }
2796}
2797
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002798private function f_tr_si2quater_earfcns(integer count) return template SI2quaterRestOctetsList
2799{
2800 var template SI2quaterRestOctetsList si2quater := {};
2801 var integer si2quater_count := (count + 2) / 3;
2802
2803 for (var integer i := 0; i < count; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002804 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002805 var integer index := i / 3;
2806 var integer earfcn_index := i mod 3;
2807 if (index >= lengthof(si2quater)) {
2808 si2quater[index] := tr_SI2quaterRestOctets_EUTRAN(index := index, count := si2quater_count - 1);
2809 }
2810 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);
2811 }
2812
2813 return si2quater;
2814}
2815
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002816private function f_tr_rr_chan_rel_earfcns(integer count) return template CellSelIndValue
2817{
2818 var template CellSelIndValue_EUTRAN_Descrs cells := {};
2819
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002820 /* the lte neighbors must match the config & vty to pass this test */
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002821 for (var integer i := 0; i < count; i := i + 1) {
2822 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002823 cells[i] := tr_CellSelIndValue_EUTRAN_Descr(earfcn, '1'B, 3);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002824 }
2825
2826 return tr_CellSelIndValue_EUTRAN(cells);
2827}
2828
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002829private function f_tc_si2quater_n_earfcns(integer n) runs on test_CT
2830{
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002831 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrol8ab62e42020-12-18 16:19:11 +01002832 sic.si2quater := f_tr_si2quater_earfcns(n);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002833 var template CellSelIndValue cells := f_tr_rr_chan_rel_earfcns(n);
2834 f_test_si2quater(n, sic, cells);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002835}
2836
2837testcase TC_si2quater_2_earfcns() runs on test_CT {
2838 f_tc_si2quater_n_earfcns(2);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002839 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002840}
2841
2842testcase TC_si2quater_3_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002843 f_tc_si2quater_n_earfcns(3);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002844 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002845}
2846
2847testcase TC_si2quater_4_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002848 f_tc_si2quater_n_earfcns(4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002849 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002850}
2851
2852testcase TC_si2quater_5_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002853 f_tc_si2quater_n_earfcns(5);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002854 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002855}
2856
2857testcase TC_si2quater_6_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002858 f_tc_si2quater_n_earfcns(6);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002859 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002860}
2861
2862testcase TC_si2quater_12_earfcns() runs on test_CT {
2863 f_tc_si2quater_n_earfcns(12);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002864 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002865}
2866
2867testcase TC_si2quater_23_earfcns() runs on test_CT {
2868 f_tc_si2quater_n_earfcns(23);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002869 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002870}
2871
2872testcase TC_si2quater_32_earfcns() runs on test_CT {
2873 f_tc_si2quater_n_earfcns(32);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002874 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002875}
2876
2877testcase TC_si2quater_33_earfcns() runs on test_CT {
2878 f_tc_si2quater_n_earfcns(33);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002879 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002880}
2881
2882testcase TC_si2quater_42_earfcns() runs on test_CT {
2883 f_tc_si2quater_n_earfcns(42);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002884 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002885}
2886
2887testcase TC_si2quater_48_earfcns() runs on test_CT {
2888 f_tc_si2quater_n_earfcns(48);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002889 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002890}
2891
2892/* verify the VTY error response when adding too many EARFCNs, and showing that osmo-bsc still sends 16 SI2quater with
2893 * 48 EARFCNs. */
2894testcase TC_si2quater_49_earfcns() runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002895 var template SystemInformationConfig sic := SystemInformationConfig_default;
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002896 sic.si2quater := f_tr_si2quater_earfcns(48); /* 48, not 49! */
2897 f_init(0);
2898
2899 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002900 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2901 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002902 }
2903
2904 /* The 49th EARFCN no longer fits, expect VTY error */
2905 f_vty_enter_cfg_bts(BSCVTY, 0);
2906 var charstring vty_error;
2907 vty_error := f_vty_transceive_ret(BSCVTY,
2908 "si2quater neighbor-list add earfcn 70 thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3")
2909 f_vty_transceive(BSCVTY, "end");
2910
2911 if (f_strstr(vty_error, "Unable to add ARFCN 70") >= 0) {
2912 log("Got expected VTY error: ", vty_error);
2913 setverdict(pass);
2914 } else {
2915 setverdict(fail, "Expected the 49th EUTRAN ARFCN to be rejected by vty config, got: ", vty_error);
2916 }
2917
2918 f_init_bts_and_check_sysinfo(0, expect_si := sic);
2919
2920 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002921 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 +02002922 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002923 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002924}
2925
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002926private function f_acc09_count_allowed(AccessControlClass acc) return uint8_t
2927{
2928 var uint8_t count := 0;
2929 for (var integer i := 5; i < 16; i := i + 1) {
2930 if (acc[i] == '0'B) { /* the list marks barred, we count allowed */
2931 count := count + 1;
2932 }
2933 }
2934 return count;
2935}
2936
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002937private function f_recv_next_si1(integer rsl_idx := 0) runs on test_CT return SystemInformationType1
2938{
2939 var ASP_RSL_Unitdata rx_rsl_ud;
2940 var SystemInformationType1 last_si1;
2941
2942 timer T := 30.0;
2943 T.start;
2944 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002945 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD((tr_RSL_NO_BCCH_INFO,
2946 tr_RSL_BCCH_INFO,
2947 tr_RSL_NO_SACCH_FILL,
2948 tr_RSL_SACCH_FILL))) -> value rx_rsl_ud {
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002949 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
2950 if (g_system_information[rsl_idx].si1 == omit) {
2951 repeat;
2952 }
2953 last_si1 := g_system_information[rsl_idx].si1;
2954 g_system_information[rsl_idx].si1 := omit;
2955 T.stop;
2956 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002957 [] IPA_RSL[rsl_idx][0].receive { repeat; }
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002958 [] T.timeout { setverdict(fail, "Timeout receiving next SI1"); }
2959 }
2960 return last_si1;
2961}
2962
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002963/* verify ACC rotate feature */
2964testcase TC_si_acc_rotate() runs on test_CT {
2965 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002966 var SystemInformationType1 last_si1;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002967 var AccessControlClass acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002968 var uint8_t count;
2969 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2970
2971 f_init(0, guard_timeout := 60.0);
2972
2973 f_bts_0_cfg(BSCVTY, {"rach access-control-class 5 barred",
2974 "access-control-class-rotate 3",
2975 "access-control-class-rotate-quantum 1"});
2976
2977 /* Init and get first sysinfo */
2978 f_init_bts_and_check_sysinfo(0, expect_si := ?);
2979
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002980 for (var integer i:= 0; i < 20; i := i + 1) {
2981 last_si1 := f_recv_next_si1(0);
2982 acc := last_si1.rach_control.acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002983 count := f_acc09_count_allowed(acc);
2984 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
2985
2986 if (count != 3) {
2987 log("RSL: EXPECTED SI ACC len=3");
2988 setverdict(fail, "received SI does not match expectations");
2989 break;
2990 }
2991
2992 for (var integer j := 0; j < 10; j := j + 1) {
2993 if (acc[16 - 1 - j] == '0'B) { /* the list marks barred, we count allowed */
2994 times_allowed[j] := times_allowed[j] + 1;
2995 }
2996 }
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002997 }
2998
2999 for (var integer j := 0; j < 10; j := j + 1) {
3000 log("ACC", j, " allowed ", times_allowed[j], " times" );
3001 if (j != 5 and times_allowed[j] < 3) {
3002 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " < 1 times");
3003 } else if (j == 5 and times_allowed[j] > 0) {
3004 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " > 0 times");
3005 }
3006 }
3007
3008 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
3009 "rach access-control-class 5 allowed"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003010 f_shutdown_helper();
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003011}
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02003012
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003013/* verify ACC startup ramp+rotate feature */
3014testcase TC_si_acc_ramp_rotate() runs on test_CT {
3015 var template SystemInformationConfig sic := SystemInformationConfig_default;
3016 var SystemInformationType1 last_si1;
3017 var AccessControlClass acc;
3018 var ASP_RSL_Unitdata rx_rsl_ud;
3019 var uint8_t count;
3020 var uint8_t prev_count;
3021 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
3022
3023 f_init(0, guard_timeout := 80.0);
3024
3025 f_bts_0_cfg(BSCVTY, {"rach access-control-class 4 barred",
3026 "access-control-class-rotate 0",
3027 "access-control-class-rotate-quantum 1",
3028 "access-control-class-ramping",
3029 "access-control-class-ramping-step-interval 5",
3030 "access-control-class-ramping-step-size 5"});
3031
3032 /* Init and get first sysinfo */
3033 f_init_bts_and_check_sysinfo(0, expect_si := ?);
3034 last_si1 := g_system_information[0].si1;
3035 acc := last_si1.rach_control.acc;
3036 count := f_acc09_count_allowed(acc);
3037 /* Adm subset size was set to 0 above, so wait until all ACC are barred */
3038 while (count > 0) {
3039 last_si1 := f_recv_next_si1(0);
3040 acc := last_si1.rach_control.acc;
3041 count := f_acc09_count_allowed(acc);
3042 log("RSL: wait len()=0: GOT SI1 ACC len=", count, ": ", acc);
3043 }
3044
3045 /* Increase adm subset size, we should see ramping start up */
3046 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10"});
3047 prev_count := 0;
3048 while (true) {
3049 last_si1 := f_recv_next_si1(0);
3050 acc := last_si1.rach_control.acc;
3051 count := f_acc09_count_allowed(acc);
3052 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
3053
3054 if (prev_count > count) {
3055 setverdict(fail, "ACC allowed count dropped while expecting grow: ", prev_count, " -> ", count);
3056 break;
3057 }
3058
3059 if (count == 9) {
3060 break; /* Maximum reached (10 - 1 perm barred), done here */
3061 }
3062
3063 prev_count := count;
3064 }
3065
3066 setverdict(pass);
3067
3068 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
3069 "rach access-control-class 4 allowed",
3070 "no access-control-class-ramping"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003071 f_shutdown_helper();
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003072}
3073
Harald Welte4003d112017-12-09 22:35:39 +01003074testcase TC_ctrl_msc_connection_status() runs on test_CT {
3075 var charstring ctrl_resp;
3076
Harald Welte89d42e82017-12-17 16:42:41 +01003077 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003078
3079 /* See https://osmocom.org/issues/2729 */
3080 f_ctrl_get_exp(IPA_CTRL, "msc_connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003081 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01003082}
3083
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003084testcase TC_ctrl_msc0_connection_status() runs on test_CT {
3085 var charstring ctrl_resp;
3086
3087 f_init(1);
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003088
3089 f_ctrl_get_exp(IPA_CTRL, "msc.0.connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003090 f_shutdown_helper();
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003091}
3092
Neels Hofmeyr0bc470d2021-08-21 13:37:13 +02003093/* Verify correct stats on the number of configured and connected MSCs */
3094private function f_tc_stat_num_msc_connected_msc_connhdlr(integer expect_num_msc_connected) runs on MSC_ConnHdlr {
3095 g_pars := f_gen_test_hdlr_pars();
3096 var StatsDExpects expect := {
3097 { name := "TTCN3.bsc.0.num_msc.connected", mtype := "g", min := expect_num_msc_connected, max := expect_num_msc_connected },
3098 { name := "TTCN3.bsc.0.num_msc.total", mtype := "g", min := NUM_MSC, max := NUM_MSC }
3099 };
3100 f_statsd_expect(expect);
3101}
3102
3103private function f_tc_stat_num_msc_connected_test_ct(void_fn tc_fn, integer nr_msc) runs on test_CT
3104{
3105 var MSC_ConnHdlr vc_conn;
3106
3107 f_init(nr_bts := 1, handler_mode := true, nr_msc := nr_msc);
3108 f_sleep(1.0);
3109 vc_conn := f_start_handler(tc_fn);
3110 vc_conn.done;
3111
3112 /* Also verify stat exposed on CTRL interface */
3113 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:connected", int2str(nr_msc));
3114 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:total", int2str(NUM_MSC));
3115
3116 f_shutdown_helper();
3117}
3118
3119/* Verify that when 1 MSC is active, that num_msc:connected reports 1. */
3120private function f_tc_stat_num_msc_connected_1(charstring id) runs on MSC_ConnHdlr {
3121 f_tc_stat_num_msc_connected_msc_connhdlr(1);
3122}
3123testcase TC_stat_num_msc_connected_1() runs on test_CT {
3124 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_1), 1);
3125}
3126
3127/* Verify that when 2 MSCs are active, that num_msc:connected reports 2. */
3128private function f_tc_stat_num_msc_connected_2(charstring id) runs on MSC_ConnHdlr {
3129 f_tc_stat_num_msc_connected_msc_connhdlr(2);
3130}
3131testcase TC_stat_num_msc_connected_2() runs on test_CT {
3132 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_2), 2);
3133}
3134
3135/* Verify that when 3 MSCs are active, that num_msc:connected reports 3. */
3136private function f_tc_stat_num_msc_connected_3(charstring id) runs on MSC_ConnHdlr {
3137 f_tc_stat_num_msc_connected_msc_connhdlr(3);
3138}
3139testcase TC_stat_num_msc_connected_3() runs on test_CT {
3140 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_3), 3);
3141}
3142
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003143/* Verify correct stats on the number of configured and connected MSCs */
3144private 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 +06003145 var integer num_trx_connected := 0;
3146 var integer num_trx_total := 0;
3147
3148 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3149 var integer trx_num := c_BtsParams[i].trx_num;
3150 num_trx_total := num_trx_total + trx_num;
3151 if (i < expect_num_bts_connected) {
3152 num_trx_connected := num_trx_connected + trx_num;
3153 }
3154 }
3155
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003156 var StatsDExpects expect := {
3157 { name := "TTCN3.bsc.0.num_bts.oml_connected", mtype := "g", min := expect_num_bts_connected, max := NUM_BTS_CFG },
3158 { name := "TTCN3.bsc.0.num_bts.all_trx_rsl_connected", mtype := "g", min := expect_num_bts_connected, max := expect_num_bts_connected },
3159 { name := "TTCN3.bsc.0.num_bts.total", mtype := "g", min := NUM_BTS_CFG, max := NUM_BTS_CFG },
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003160 { name := "TTCN3.bsc.0.num_trx.rsl_connected", mtype := "g", min := num_trx_connected, max := num_trx_connected },
3161 { name := "TTCN3.bsc.0.num_trx.total", mtype := "g", min := num_trx_total, max := num_trx_total }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003162 };
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003163
3164 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003165 f_statsd_expect(expect);
3166}
3167
3168private 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 +06003169 var integer num_trx_connected := 0;
3170 var integer num_trx_total := 0;
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003171 var MSC_ConnHdlr vc_conn;
3172
3173 f_init(nr_bts := nr_bts, handler_mode := true, nr_msc := 1);
3174 f_sleep(1.0);
3175 vc_conn := f_start_handler(tc_fn);
3176 vc_conn.done;
3177
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003178 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3179 var integer trx_num := c_BtsParams[i].trx_num;
3180 num_trx_total := num_trx_total + trx_num;
3181 if (i < nr_bts) {
3182 num_trx_connected := num_trx_connected + trx_num;
3183 }
3184 }
3185
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003186 /* Also verify stat exposed on CTRL interface */
3187 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_bts:all_trx_rsl_connected", int2str(nr_bts));
3188 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 +06003189 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_trx:rsl_connected", int2str(num_trx_connected));
3190 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 +02003191
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003192 /* Verify rf_states exposed on CTRL interface */
3193 var charstring expect_net_rf_states := "";
3194 for (var integer i := 0; i < NUM_BTS_CFG; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003195 var charstring expect_bts_rf_states := "";
3196
3197 for (var integer j := 0; j < c_BtsParams[i].trx_num; j := j + 1) {
3198 expect_bts_rf_states := expect_bts_rf_states &
3199 int2str(i) & "," & int2str(j) & ",";
3200 if (i < NUM_BTS) {
3201 /* In these tests, OML for the first NUM_BTS are always connected via osmo-bts-omldummy */
3202 expect_bts_rf_states := expect_bts_rf_states & "operational,unlocked,";
3203 } else {
3204 /* For remaining i < NUM_BTS_CFG, OML is not connected, i.e. inoperational */
3205 expect_bts_rf_states := expect_bts_rf_states & "inoperational,locked,";
3206 }
3207 /* The RF policy is still global in osmo-bsc, i.e. always "on" */
3208 expect_bts_rf_states := expect_bts_rf_states & "on,";
3209 if (i < nr_bts) {
3210 /* For BTS where RSL is connected, the RSL state will be "up" */
3211 expect_bts_rf_states := expect_bts_rf_states & "rsl-up;";
3212 } else {
3213 expect_bts_rf_states := expect_bts_rf_states & "rsl-down;";
3214 }
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003215 }
3216
3217 f_ctrl_get_exp(IPA_CTRL, "bts." & int2str(i) & ".rf_states", expect_bts_rf_states);
3218 expect_net_rf_states := expect_net_rf_states & expect_bts_rf_states;
3219 }
3220 f_ctrl_get_exp(IPA_CTRL, "rf_states", expect_net_rf_states);
3221
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003222 f_shutdown_helper();
3223}
3224
3225/* Verify that when 1 BTS is connected, that num_{bts,trx}:*_connected reports 1. */
3226private function f_tc_stat_num_bts_connected_1(charstring id) runs on MSC_ConnHdlr {
3227 f_tc_stat_num_bts_connected_msc_connhdlr(1);
3228}
3229testcase TC_stat_num_bts_connected_1() runs on test_CT {
3230 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_1), 1);
3231}
3232
3233/* Verify that when 2 BTS is connected, that num_{bts,trx}:*_connected reports 2. */
3234private function f_tc_stat_num_bts_connected_2(charstring id) runs on MSC_ConnHdlr {
3235 f_tc_stat_num_bts_connected_msc_connhdlr(2);
3236}
3237testcase TC_stat_num_bts_connected_2() runs on test_CT {
3238 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_2), 2);
3239}
3240
3241/* Verify that when 3 BTS is connected, that num_{bts,trx}:*_connected reports 3. */
3242private function f_tc_stat_num_bts_connected_3(charstring id) runs on MSC_ConnHdlr {
3243 f_tc_stat_num_bts_connected_msc_connhdlr(3);
3244}
3245testcase TC_stat_num_bts_connected_3() runs on test_CT {
3246 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_3), 3);
3247}
3248
Harald Welte4003d112017-12-09 22:35:39 +01003249testcase TC_ctrl() runs on test_CT {
3250 var charstring ctrl_resp;
3251
Harald Welte89d42e82017-12-17 16:42:41 +01003252 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003253
3254 /* all below values must match the osmo-bsc.cfg config file used */
3255
Harald Welte6a129692018-03-17 17:30:14 +01003256 f_ctrl_get_exp(IPA_CTRL, "mcc", "001");
3257 f_ctrl_get_exp(IPA_CTRL, "mnc", "01");
Oliver Smith75aa0202019-08-19 14:17:50 +02003258 f_ctrl_get_exp(IPA_CTRL, "number-of-bts", "4");
Harald Welte4003d112017-12-09 22:35:39 +01003259
3260 var integer bts_nr := 0;
3261 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "location-area-code", "1");
3262 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "cell-identity", "0");
3263 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "oml-connection-state", "connected");
3264 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "gprs-mode", "gprs");
3265 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "rf_state", "operational,unlocked,on");
3266 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "arfcn", "871");
3267 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "max-power-reduction", "20");
3268
3269 var integer uptime := str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime"));
3270 f_sleep(2.0);
3271 if (str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime")) < uptime+1) {
3272 setverdict(fail, "oml-uptime not incrementing as expected");
3273 }
3274 /* TODO: Disconnect RSL, imply that OML is disconnected and check for uptime zero? */
3275
3276 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", 0);
3277
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003278 f_shutdown_helper();
Harald Welte96c94412017-12-09 03:12:45 +01003279}
3280
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003281/* Verify that Upon receival of SET "location", BSC forwards a TRAP
3282 "location-state" over the SCCPlite IPA conn */
3283testcase TC_ctrl_location() runs on test_CT {
3284 var MSC_ConnHdlr vc_conn;
3285 var integer bts_nr := 0;
3286
3287 f_init(1, true);
3288 f_sleep(1.0);
3289
3290 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234567,fix3d,0.340000,0.560000,0.780000");
3291 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3292 "1234567,fix3d,0.340000,0.560000,0.780000,operational,unlocked,on,001,01");
3293
3294 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "1");
3295 f_sleep(2.0);
3296
3297 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234888,fix3d,0.350000,0.570000,0.790000");
3298 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3299 "1234888,fix3d,0.350000,0.570000,0.790000,operational,locked,off,001,01");
3300
3301 /* should match the one from config */
3302 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "0");
3303
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003304 f_shutdown_helper();
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003305}
3306
Harald Welte6f521d82017-12-11 19:52:02 +01003307
3308/***********************************************************************
3309 * Paging Testing
3310 ***********************************************************************/
3311
3312type record Cell_Identity {
3313 GsmMcc mcc,
3314 GsmMnc mnc,
3315 GsmLac lac,
3316 GsmCellId ci
3317};
Harald Welte24135bd2018-03-17 19:27:53 +01003318private const Cell_Identity cid := { '001'H, '01'H, 1, 0 };
Stefan Sperling049a86e2018-03-20 15:51:00 +01003319private const Cell_Identity unknown_cid := { '678'H, 'f90'H, 1, 0 };
Harald Welte6f521d82017-12-11 19:52:02 +01003320
Harald Welte5d1a2202017-12-13 19:51:29 +01003321type set of integer BtsIdList;
3322
3323private function f_bts_in_list(integer bts_id, BtsIdList bts_ids) return boolean {
3324 for (var integer j := 0; j < sizeof(bts_ids); j := j + 1) {
3325 if (bts_id == bts_ids[j]) {
3326 return true;
3327 }
3328 }
3329 return false;
3330}
Harald Welte6f521d82017-12-11 19:52:02 +01003331
3332/* core paging test helper function; used by most paging test cases */
3333private function f_pageing_helper(hexstring imsi,
3334 template BSSMAP_FIELD_CellIdentificationList cid_list,
Harald Welte5d1a2202017-12-13 19:51:29 +01003335 BtsIdList bts_ids := { 0 },
Harald Welte6f521d82017-12-11 19:52:02 +01003336 template RSL_ChanNeeded rsl_chneed := omit,
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003337 template (omit) OCT4 tmsi := omit) runs on test_CT
Harald Welte6f521d82017-12-11 19:52:02 +01003338{
3339 var template BSSMAP_IE_ChannelNeeded bssmap_chneed;
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003340 var template MobileIdentityV mi;
Harald Welte6f521d82017-12-11 19:52:02 +01003341 var RSL_Message rx_rsl;
3342 var integer paging_group := hex2int(imsi[lengthof(imsi)-1]);
Harald Welte5d1a2202017-12-13 19:51:29 +01003343 var integer i;
Harald Welte6f521d82017-12-11 19:52:02 +01003344
3345 f_init();
Harald Welte6f521d82017-12-11 19:52:02 +01003346
3347 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Harald Weltec3068592018-03-17 19:55:31 +01003348 for (i := 0; i < NUM_BTS; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003349 IPA_RSL[i][0].clear;
Harald Welte5d1a2202017-12-13 19:51:29 +01003350 }
Harald Welte6f521d82017-12-11 19:52:02 +01003351
3352 if (isvalue(rsl_chneed)) {
3353 /* The values of 08.08 3.2.2.36 and 08.58 9.3.40 are luckily identical */
3354 bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
3355 } else {
3356 bssmap_chneed := omit;
3357 }
3358
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003359 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own,
3360 ts_BSSMAP_Paging(imsi, cid_list, tmsi, bssmap_chneed)));
Harald Welte6f521d82017-12-11 19:52:02 +01003361
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003362 if (not istemplatekind(tmsi, "omit")) {
3363 mi := t_MI_TMSI(tmsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003364 } else {
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003365 mi := tr_MI_IMSI(imsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003366 }
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003367
Harald Welte5d1a2202017-12-13 19:51:29 +01003368 for (i := 0; i < sizeof(bts_ids); i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003369 rx_rsl := f_exp_ipa_rx(tr_RSL_PAGING_CMD(mi), idx := {bts_ids[i], 0});
Harald Welte5d1a2202017-12-13 19:51:29 +01003370 /* check channel type, paging group */
3371 if (rx_rsl.ies[1].body.paging_group != paging_group) {
3372 setverdict(fail, "Paging for wrong paging group");
3373 }
3374 if (ispresent(rsl_chneed) and
3375 rx_rsl.ies[3].body.chan_needed.chan_needed != valueof(rsl_chneed)) {
3376 setverdict(fail, "RSL Channel Needed != BSSMAP Channel Needed");
3377 }
Harald Welte6f521d82017-12-11 19:52:02 +01003378 }
Harald Welte2fccd982018-01-31 15:48:19 +01003379 f_sleep(2.0);
Harald Welte5d1a2202017-12-13 19:51:29 +01003380 /* do a quick check on all not-included BTSs if they received paging */
3381 for (i := 0; i < NUM_BTS; i := i + 1) {
3382 timer T := 0.1;
3383 if (f_bts_in_list(i, bts_ids)) {
3384 continue;
3385 }
3386 T.start;
3387 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003388 [] IPA_RSL[i][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(mi))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003389 setverdict(fail, "Paging on BTS ", i, " which is not part of ", bts_ids);
3390 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003391 [] IPA_RSL[i][0].receive { repeat; }
Harald Welte5d1a2202017-12-13 19:51:29 +01003392 [] T.timeout { }
3393 }
Harald Welte6f521d82017-12-11 19:52:02 +01003394 }
3395
3396 setverdict(pass);
3397}
3398
Harald Welte5d1a2202017-12-13 19:51:29 +01003399const BtsIdList c_BtsId_all := { 0, 1, 2 };
Harald Welte751d3eb2018-01-31 15:51:06 +01003400const BtsIdList c_BtsId_none := { };
Harald Welte5d1a2202017-12-13 19:51:29 +01003401const BtsIdList c_BtsId_LAC1 := { 0, 1 };
3402const BtsIdList c_BtsId_LAC2 := { 2 };
3403
Harald Welte6f521d82017-12-11 19:52:02 +01003404/* PAGING by IMSI + TMSI */
3405testcase TC_paging_imsi_nochan() runs on test_CT {
3406 var BSSMAP_FIELD_CellIdentificationList cid_list;
3407 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Philipp Maier8c04b0a2018-02-23 13:48:48 +01003408 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, omit);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003409 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003410}
3411
3412/* PAGING by IMSI + TMSI */
3413testcase TC_paging_tmsi_nochan() runs on test_CT {
3414 var BSSMAP_FIELD_CellIdentificationList cid_list;
3415 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003416 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, 'A1B2C301'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003417 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003418}
3419
3420/* Paging with different "channel needed' values */
3421testcase TC_paging_tmsi_any() runs on test_CT {
3422 var BSSMAP_FIELD_CellIdentificationList cid_list;
3423 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003424 f_pageing_helper('001010100000002'H, cid_list, c_BtsId_all, RSL_CHANNEED_ANY, 'A1B2C302'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003425 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003426}
3427testcase TC_paging_tmsi_sdcch() runs on test_CT {
3428 var BSSMAP_FIELD_CellIdentificationList cid_list;
3429 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003430 f_pageing_helper('001010100000003'H, cid_list, c_BtsId_all, RSL_CHANNEED_SDCCH, 'A1B2C303'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003431 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003432}
3433testcase TC_paging_tmsi_tch_f() runs on test_CT {
3434 var BSSMAP_FIELD_CellIdentificationList cid_list;
3435 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003436 f_pageing_helper('001010000000004'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_F, 'A1B2C304'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003437 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003438}
3439testcase TC_paging_tmsi_tch_hf() runs on test_CT {
3440 var BSSMAP_FIELD_CellIdentificationList cid_list;
3441 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003442 f_pageing_helper('001010000000005'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_ForH, 'A1B2C305'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003443 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003444}
3445
3446/* Paging by CGI */
3447testcase TC_paging_imsi_nochan_cgi() runs on test_CT {
3448 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3449 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(cid.mcc, cid.mnc, cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003450 f_pageing_helper('001010000000006'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003451 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003452}
3453
3454/* Paging by LAC+CI */
3455testcase TC_paging_imsi_nochan_lac_ci() runs on test_CT {
3456 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3457 cid_list := { cIl_LAC_CI := { ts_BSSMAP_CI_LAC_CI(cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003458 f_pageing_helper('001010000000007'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003459 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003460}
3461
3462/* Paging by CI */
3463testcase TC_paging_imsi_nochan_ci() runs on test_CT {
3464 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3465 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003466 f_pageing_helper('001010000000008'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003467 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003468}
3469
3470/* Paging by LAI */
3471testcase TC_paging_imsi_nochan_lai() runs on test_CT {
3472 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3473 cid_list := { cIl_LAI := { ts_BSSMAP_CI_LAI(cid.mcc, cid.mnc, cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003474 f_pageing_helper('001010000000009'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003475 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003476}
3477
3478/* Paging by LAC */
3479testcase TC_paging_imsi_nochan_lac() runs on test_CT {
3480 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3481 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003482 f_pageing_helper('001010000000010'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003483 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003484}
3485
3486/* Paging by "all in BSS" */
3487testcase TC_paging_imsi_nochan_all() runs on test_CT {
3488 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3489 cid_list := { cIl_allInBSS := ''O };
Harald Welte5d1a2202017-12-13 19:51:29 +01003490 f_pageing_helper('001010000000011'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003491 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003492}
3493
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003494/* Paging by PLMN+LAC+RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003495testcase TC_paging_imsi_nochan_plmn_lac_rnc() runs on test_CT {
3496 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3497 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 +01003498 f_pageing_helper('001010000000012'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003499 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003500}
Harald Welte6f521d82017-12-11 19:52:02 +01003501
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003502/* Paging by RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003503testcase TC_paging_imsi_nochan_rnc() runs on test_CT {
3504 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3505 cid_list := { cIl_RNC := { int2oct(13, 2) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003506 f_pageing_helper('001010000000013'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003507 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003508}
3509
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003510/* Paging by LAC+RNC; We do not implement; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003511testcase TC_paging_imsi_nochan_lac_rnc() runs on test_CT {
3512 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3513 cid_list := { cIl_LAC_RNC := { ts_BSSMAP_CI_LAC_RNC(cid.lac, 14) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003514 f_pageing_helper('001010000000014'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003515 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003516}
3517
Harald Welte6f521d82017-12-11 19:52:02 +01003518/* Paging on multiple cells (multiple entries in list): Verify all of them page */
Harald Welte751d3eb2018-01-31 15:51:06 +01003519testcase TC_paging_imsi_nochan_lacs() runs on test_CT {
3520 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3521 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(1), ts_BSSMAP_CI_LAC(2) } };
3522 f_pageing_helper('001010000000015'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003523 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003524}
3525
3526/* Paging on empty list: Verify none of them page */
3527testcase TC_paging_imsi_nochan_lacs_empty() runs on test_CT {
3528 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3529 cid_list := { cIl_LAC := { } };
3530 f_pageing_helper('001010000000016'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003531 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003532}
3533
Stefan Sperling049a86e2018-03-20 15:51:00 +01003534/* Paging by CGI with unknown MCC/MNC: Verify nothing is paged. */
3535testcase TC_paging_imsi_nochan_cgi_unknown_cid() runs on test_CT {
3536 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3537 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(unknown_cid.mcc, unknown_cid.mnc, unknown_cid.lac, unknown_cid.ci) } };
3538 f_pageing_helper('001010000000006'H, cid_list, c_BtsId_none);
3539 f_shutdown_helper();
3540}
3541
Pau Espin Pedrol07657ae2023-01-03 12:08:05 +01003542/* Send paging response containing invalid (wrongly formatted) MobileIdentity IE. */
3543testcase TC_paging_imsi_nochan_ci_resp_invalid_mi() runs on test_CT {
3544 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3545 var BSSAP_N_CONNECT_ind rx_c_ind;
3546 var DchanTuple dt;
3547 var octetstring rr_pag_resp := '06270003535992617965720000'O;
3548 /* { 06 27 } is { GSM48_PDISC_RR, GSM48_MT_RR_PAG_RESP }
3549 * see 3GPP TS 44.018, table 9.1.25.1
3550 * { 00 } or { 01 } is CKSN + Spare Half Octet, not important
3551 * { 03 53 59 92 } is Mobile Station Classmark
3552 * { 61 79 65 72 00 00 } is the invalid Mobile Identity IE (3GPP TS 24.008, 10.5.1.4),
3553 * Length is 0x61 (97 in decimal).
3554 */
3555
3556 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
3557 f_pageing_helper('001010000000008'H, cid_list, { 0 });
3558
3559 /* Send CHAN RQD and wait for allocation; acknowledge it */
3560 dt.rsl_chan_nr := f_chreq_act_ack();
3561 dt.idx := {0, 0};
3562
3563 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
3564 f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), rr_pag_resp));
3565
3566 /* Expevct a CR with a matching Paging response on the A-Interface */
3567 timer T := 5.0;
3568 T.start;
3569 alt {
3570 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
3571 setverdict(pass);
3572 dt.sccp_conn_id := rx_c_ind.connectionId;
3573 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
3574 }
3575 [] BSSAP.receive {
3576 setverdict(fail, "Received unexpected message on A-Interface!");
3577 }
3578 [] T.timeout {
3579 setverdict(fail, "Received nothing on A-Interface!");
3580 }
3581 }
3582
3583 f_perform_clear_test_ct(dt);
3584 f_shutdown_helper();
3585}
3586
Harald Welte6f521d82017-12-11 19:52:02 +01003587/* Verify paging retransmission interval + count */
3588/* Verify paging stops after channel establishment */
Harald Welte6f521d82017-12-11 19:52:02 +01003589/* Test behavior under paging overload */
Harald Welteae026692017-12-09 01:03:01 +01003590
Harald Weltee65d40e2017-12-13 00:09:06 +01003591/* Verify PCH load */
3592testcase TC_paging_imsi_load() runs on test_CT {
3593 var BSSMAP_FIELD_CellIdentificationList cid_list;
3594 timer T := 4.0;
Harald Welte2caa1062018-03-17 18:19:05 +01003595 timer T_retrans := 1.0;
Harald Weltee65d40e2017-12-13 00:09:06 +01003596 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003597 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Weltee65d40e2017-12-13 00:09:06 +01003598
3599 /* tell BSC there is no paging space anymore */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003600 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte3b57ab52018-03-17 18:01:10 +01003601 f_sleep(0.2);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003602 IPA_RSL[0][0].clear;
Harald Weltee65d40e2017-12-13 00:09:06 +01003603
3604 /* Wait for 4 seconds if any more PAGING CMD are received on RSL. Normally,
3605 * there would be 8 retransmissions during 4 seconds */
3606 T.start;
Harald Welte2caa1062018-03-17 18:19:05 +01003607 T_retrans.start;
Harald Weltee65d40e2017-12-13 00:09:06 +01003608 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003609 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Weltee65d40e2017-12-13 00:09:06 +01003610 setverdict(fail, "Received PAGING after LOAD_IND(0)");
Daniel Willmannafce8662018-07-06 23:11:32 +02003611 mtc.stop;
Harald Weltee65d40e2017-12-13 00:09:06 +01003612 }
Harald Welte2caa1062018-03-17 18:19:05 +01003613 [] T_retrans.timeout {
3614 /* re-trnsmit the zero-space LOAD IND to avoid BSC 'auto credit' */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003615 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte2caa1062018-03-17 18:19:05 +01003616 T_retrans.start;
3617 repeat;
3618 }
Harald Weltee65d40e2017-12-13 00:09:06 +01003619 [] T.timeout {
3620 setverdict(pass);
3621 }
3622 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003623
3624 f_shutdown_helper();
Harald Weltee65d40e2017-12-13 00:09:06 +01003625}
3626
Harald Welte235ebf12017-12-15 14:18:16 +01003627/* Verify Paging Counter */
Harald Welte1ff69992017-12-14 12:31:17 +01003628testcase TC_paging_counter() runs on test_CT {
3629 var BSSMAP_FIELD_CellIdentificationList cid_list;
3630 timer T := 4.0;
3631 var integer i;
3632 var integer paging_attempted_bsc;
3633 var integer paging_attempted_bts[NUM_BTS];
Oliver Smith8b343d32021-11-26 13:01:42 +01003634 var integer paging_expired_bsc;
Harald Welte1ff69992017-12-14 12:31:17 +01003635 var integer paging_expired_bts[NUM_BTS];
3636 cid_list := valueof(ts_BSSMAP_CIL_noCell);
3637
3638 f_init();
3639
3640 /* read counters before paging */
3641 paging_attempted_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted");
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01003642 paging_expired_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired");
Harald Welte1ff69992017-12-14 12:31:17 +01003643 for (i := 0; i < NUM_BTS; i := i+1) {
3644 paging_attempted_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted");
3645 paging_expired_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired");
3646 }
3647
3648 f_pageing_helper('001230000000001'H, cid_list, c_BtsId_all);
3649
3650 /* expect the attempted pages on BSC and each BTSs to have incremented by one */
3651 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", paging_attempted_bsc+1);
3652 for (i := 0; i < NUM_BTS; i := i+1) {
3653 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted",
3654 paging_attempted_bts[i]+1);
3655 }
3656
3657 /* assume that 12s later the paging on all BTSs have expired and hence incremented by 1 */
3658 f_sleep(12.0);
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01003659 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired", paging_expired_bsc+1);
Harald Welte1ff69992017-12-14 12:31:17 +01003660 for (i := 0; i < NUM_BTS; i := i+1) {
3661 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired",
3662 paging_expired_bts[i]+1);
3663 }
Harald Welte1ff69992017-12-14 12:31:17 +01003664
Philipp Maier282ca4b2018-02-27 17:17:00 +01003665 f_shutdown_helper();
Harald Welte1ff69992017-12-14 12:31:17 +01003666}
3667
3668
Harald Welte10985002017-12-12 09:29:15 +01003669/* Verify paging stops after A-RESET */
3670testcase TC_paging_imsi_a_reset() runs on test_CT {
3671 var BSSMAP_FIELD_CellIdentificationList cid_list;
3672 timer T := 3.0;
3673 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003674 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Welte10985002017-12-12 09:29:15 +01003675
3676 /* Perform a BSSMAP Reset and wait for ACK */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003677 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 +01003678 alt {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003679 [] 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 +01003680 [] BSSAP.receive { repeat; }
3681 }
3682
Daniel Willmanncbef3982018-07-30 09:22:40 +02003683 /* Wait to avoid a possible race condition if a paging message is
3684 * received right before the reset ACK. */
3685 f_sleep(0.2);
3686
Harald Welte10985002017-12-12 09:29:15 +01003687 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Philipp Maier1e6b4422018-02-23 14:02:13 +01003688 for (var integer i := 0; i < sizeof(IPA_RSL); i := i+1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003689 IPA_RSL[i][0].clear;
Philipp Maier1e6b4422018-02-23 14:02:13 +01003690 }
Harald Welte10985002017-12-12 09:29:15 +01003691
3692 /* Wait for 3 seconds if any more PAGING CMD are received on RSL */
3693 T.start;
3694 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003695 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte10985002017-12-12 09:29:15 +01003696 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003697 mtc.stop;
Harald Welte10985002017-12-12 09:29:15 +01003698 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003699 [] IPA_RSL[1][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003700 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003701 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003702 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003703 [] IPA_RSL[2][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003704 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003705 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003706 }
Harald Welte10985002017-12-12 09:29:15 +01003707 [] T.timeout {
3708 setverdict(pass);
3709 }
3710 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003711
3712 f_shutdown_helper();
Harald Welte10985002017-12-12 09:29:15 +01003713}
Harald Welteae026692017-12-09 01:03:01 +01003714
Philipp Maierf45824a2019-08-14 14:44:10 +02003715/* Verify how we handle unsolicited Paging Response. In case of an unsolicit
3716 * paging response we can not know which MSC is in charge, so we will blindly
3717 * pick the first configured MSC. This behavior is required in order to make
3718 * MT-CSFB calls working because in those cases the BSC can not know that the
3719 * MSC has already paged the subscriver via SGs. So any MT-CSFB call will look
3720 * like an unsolicited Paging Response to the MSC.
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003721 */
3722testcase TC_paging_resp_unsol() runs on test_CT {
3723
3724 f_init(1);
Philipp Maierf45824a2019-08-14 14:44:10 +02003725 timer T := 5.0;
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003726
3727 var BSSAP_N_CONNECT_ind rx_c_ind;
3728 var DchanTuple dt;
3729 var PDU_ML3_MS_NW l3 := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010008880018'H))));
Philipp Maierf45824a2019-08-14 14:44:10 +02003730 var octetstring rr_pag_resp := enc_PDU_ML3_MS_NW(l3);
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003731
3732 /* Send CHAN RQD and wait for allocation; acknowledge it */
3733 dt.rsl_chan_nr := f_chreq_act_ack();
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003734 dt.idx := {0, 0};
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003735
3736 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
Pau Espin Pedrole8a51012023-01-03 11:59:59 +01003737 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 +01003738
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003739
Philipp Maierf45824a2019-08-14 14:44:10 +02003740 /* Expevct a CR with a matching Paging response on the A-Interface */
3741 T.start;
3742 alt {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003743 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
Philipp Maierf45824a2019-08-14 14:44:10 +02003744 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003745 dt.sccp_conn_id := rx_c_ind.connectionId;
3746 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
Philipp Maierf45824a2019-08-14 14:44:10 +02003747 }
3748 [] BSSAP.receive {
3749 setverdict(fail, "Received unexpected message on A-Interface!");
3750 }
3751 [] T.timeout {
3752 setverdict(fail, "Received nothing on A-Interface!");
3753 }
3754 }
3755
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003756 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003757 f_shutdown_helper();
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003758}
3759
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003760/* Verify BSC can schedule N paging requests under one minute if BTS buffer is good enough */
3761function f_TC_paging_Nreq(integer num_subscribers, boolean send_pag_load_ind) runs on test_CT {
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003762 var ASP_RSL_Unitdata rx_rsl_ud;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003763 var Hexstrings imsis := {};
3764 var Booleans rx_paging_done := {};
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003765 var integer rx_paging_num := 0;
3766 var integer i;
3767 timer T_rx := 60.0;
3768 timer T_load_ind := 1.0;
3769
3770 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003771 imsis := imsis & {f_gen_imsi(i)};
3772 rx_paging_done := rx_paging_done & { false };
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003773 }
3774
3775 f_init(1, guard_timeout := 100.0);
3776
3777 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003778 IPA_RSL[0][0].clear;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003779 if (send_pag_load_ind) {
3780 /* Tell there's plenty of space at the BTS (UINT16_MAX): */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003781 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(65535));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003782 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003783
3784 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003785 /* Page on LAC-CI of BTS0: */
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003786 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 +02003787 ts_BSSMAP_Paging(imsis[i], valueof(ts_BSSMAP_CIL_LAC_CI({ts_BSSMAP_CI_LAC_CI(1, 0)})),
3788 omit, omit)));
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003789 }
3790
3791 T_rx.start;
3792 T_load_ind.start;
3793 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003794 [] 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 +02003795 var hexstring imsi := rx_rsl_ud.rsl.ies[2].body.ms_identity.mobileIdentityV.oddEvenInd_identity.imsi.digits;
3796 var hexstring imsi_suffix := substr(imsi, lengthof(imsi)-6, 6);
3797 var charstring imsi_str := hex2str(imsi_suffix);
3798 var integer imsi_idx := str2int(imsi_str);
3799 if (rx_paging_done[imsi_idx] == false) {
3800 rx_paging_done[imsi_idx] := true;
3801 rx_paging_num := rx_paging_num + 1;
Pau Espin Pedrolef7ef632022-04-25 13:34:57 +02003802 } else {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003803 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 +02003804 mtc.stop;
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003805 }
3806 if (rx_paging_num < num_subscribers) {
3807 repeat;
3808 }
3809 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003810 [] IPA_RSL[0][0].receive { repeat; }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003811 [] T_load_ind.timeout {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003812 log("[CCH Load Ind timer] received paging requests so far: ", rx_paging_num);
3813 if (send_pag_load_ind) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003814 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(40));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003815 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003816 T_load_ind.start;
3817 repeat;
3818 }
3819 [] T_rx.timeout {
3820 setverdict(fail, "Timeout expecting paging requests, so far ", rx_paging_num);
3821 mtc.stop;
3822 }
3823 }
3824
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003825 /* Drop OML connection to have all paging requests flushed: */
3826 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
3827
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003828 f_shutdown_helper();
3829}
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003830/* Verify BSC can schedule 500 paging requests under one minute if BTS buffer is good enough */
3831testcase TC_paging_500req() runs on test_CT {
3832 f_TC_paging_Nreq(500, true);
3833}
3834/* Same as TC_paging_500req, but without sending CCCH Load Indication, which
3835 * means BTS is always under CCH Load Threshold, aka capable of sending tons of requests.
3836 * Since No CCCH Load Ind, BSC uses a conservative estimation of BTS load, which
3837 * for current config yields ~8req/sec, so 480req/min maximum. */
3838testcase TC_paging_450req_no_paging_load_ind() runs on test_CT {
3839 f_TC_paging_Nreq(450, false);
3840}
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003841
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003842/* Test RSL link drop causes counter increment */
3843testcase TC_rsl_drop_counter() runs on test_CT {
3844 var integer rsl_fail;
3845
Harald Welte89d42e82017-12-17 16:42:41 +01003846 f_init(1);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003847
3848 rsl_fail := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail");
3849
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003850 f_ipa_rsl_stop(bts[0][0].rsl);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003851
3852 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail", rsl_fail+1);
3853
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003854 f_shutdown_helper();
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003855}
3856
3857/* TODO: Test OML link drop causes counter increment */
3858
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003859/* The body of TC_rsl_unknown_unit_id() and TC_oml_unknown_unit_id() tests. */
3860function f_ipa_unknown_unit_id(integer mp_bsc_ipa_port) runs on test_CT return boolean {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003861 var IPA_Client client;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003862 timer T := 10.0;
3863
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003864 client.id := "IPA-BTS0-TRX0-RSL";
3865 client.vc_IPA := IPA_Emulation_CT.create(client.id & "-IPA") alive;
3866 client.ccm_pars := c_IPA_default_ccm_pars;
3867 client.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
3868 client.ccm_pars.unit_id := "99/0/0"; /* value which is unknown at BTS */
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003869
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01003870 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003871
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003872 f_init_mgcp(0, "VirtMGW");
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003873
3874 /* start RSL/OML connection (XXX re-uses RSL port/protocol definitions for OML) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003875 map(client.vc_IPA:IPA_PORT, system:IPA);
3876 connect(client.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[0][0]);
3877 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 +01003878
3879 /* wait for IPA OML link to connect and then disconnect */
3880 T.start;
3881 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003882 [] IPA_RSL[0][0].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_DOWN)) {
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003883 T.stop;
3884 return true;
3885 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003886 [] IPA_RSL[0][0].receive { repeat }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003887 [] T.timeout {
Daniel Willmannafce8662018-07-06 23:11:32 +02003888 return false;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003889 }
3890 }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003891 return false;
3892}
3893
3894/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3895testcase TC_rsl_unknown_unit_id() runs on test_CT {
3896 if (f_ipa_unknown_unit_id(mp_bsc_rsl_port)) {
3897 setverdict(pass);
3898 } else {
3899 setverdict(fail, "Timeout RSL waiting for connection to close");
3900 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003901 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003902}
3903
3904
3905/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3906testcase TC_oml_unknown_unit_id() runs on test_CT {
3907 if (f_ipa_unknown_unit_id(mp_bsc_oml_port)) {
3908 setverdict(pass);
3909 } else {
3910 setverdict(fail, "Timeout OML waiting for connection to close");
3911 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003912 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003913}
3914
3915
Harald Weltec1a2fff2017-12-17 11:06:19 +01003916/***********************************************************************
Harald Welte6811d102019-04-14 22:23:14 +02003917 * "New world" test cases using RSL_Emulation + RAN_Emulation
Harald Weltec1a2fff2017-12-17 11:06:19 +01003918 ***********************************************************************/
3919
Harald Welte6811d102019-04-14 22:23:14 +02003920import from RAN_Emulation all;
Harald Welte47cd0e32020-08-21 12:39:11 +02003921import from BSSAP_LE_Emulation all;
Harald Weltec1a2fff2017-12-17 11:06:19 +01003922import from RSL_Emulation all;
3923import from MSC_ConnectionHandler all;
3924
3925type function void_fn(charstring id) runs on MSC_ConnHdlr;
3926
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003927/* helper function to create and connect a MSC_ConnHdlr component
3928 * TODO: allow connecting to TRX1..N, not only TRX0 */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003929private 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 +02003930 connect(vc_conn:RAN, g_bssap[bssap_idx].vc_RAN:PROC);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003931 connect(vc_conn:RSL, bts[0][0].rsl.vc_RSL:CLIENT_PT);
3932 connect(vc_conn:RSL_PROC, bts[0][0].rsl.vc_RSL:RSL_PROC);
3933 if (isvalue(bts[1][0])) {
3934 connect(vc_conn:RSL1, bts[1][0].rsl.vc_RSL:CLIENT_PT);
3935 connect(vc_conn:RSL1_PROC, bts[1][0].rsl.vc_RSL:RSL_PROC);
Philipp Maier956a92f2018-02-16 10:58:07 +01003936 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003937 if (isvalue(bts[2][0])) {
3938 connect(vc_conn:RSL2, bts[2][0].rsl.vc_RSL:CLIENT_PT);
3939 connect(vc_conn:RSL2_PROC, bts[2][0].rsl.vc_RSL:RSL_PROC);
Neels Hofmeyr91401012019-07-11 00:42:35 +02003940 }
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003941 connect(vc_conn:BSSAP, g_bssap[bssap_idx].vc_RAN:CLIENT);
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02003942 if (mp_enable_lcs_tests) {
3943 connect(vc_conn:BSSAP_LE, g_bssap_le.vc_BSSAP_LE:CLIENT);
3944 connect(vc_conn:BSSAP_LE_PROC, g_bssap_le.vc_BSSAP_LE:PROC);
3945 }
Daniel Willmannebdecc02020-08-12 15:30:17 +02003946 connect(vc_conn:STATSD_PROC, vc_STATSD:STATSD_PROC);
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003947 connect(vc_conn:MGCP_PROC, vc_MGCP[mgwpool_idx]:MGCP_PROC);
3948 connect(vc_conn:MGCP, vc_MGCP[mgwpool_idx]:MGCP_CLIENT);
3949 connect(vc_conn:MGCP_MULTI, vc_MGCP[mgwpool_idx]:MGCP_CLIENT_MULTI);
Harald Welte336820c2018-05-31 20:34:52 +02003950}
3951
Neels Hofmeyrda436782021-07-20 22:09:06 +02003952function f_start_handler_create(template (omit) TestHdlrParams pars := omit)
Harald Welte336820c2018-05-31 20:34:52 +02003953runs on test_CT return MSC_ConnHdlr {
3954 var charstring id := testcasename();
3955 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003956 var integer bssap_idx := 0;
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003957 var integer mgwpool_idx := 0;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003958 if (isvalue(pars)) {
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003959 var TestHdlrParams pars_val := valueof(pars);
3960 bssap_idx := pars_val.mscpool.bssap_idx;
3961 mgwpool_idx := pars_val.mgwpool_idx;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003962 }
Harald Welte336820c2018-05-31 20:34:52 +02003963 vc_conn := MSC_ConnHdlr.create(id);
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003964 f_connect_handler(vc_conn, bssap_idx, mgwpool_idx);
Neels Hofmeyrda436782021-07-20 22:09:06 +02003965 return vc_conn;
3966}
3967
3968function f_start_handler_run(MSC_ConnHdlr vc_conn, void_fn fn, template (omit) TestHdlrParams pars := omit)
3969runs on test_CT return MSC_ConnHdlr {
3970 var charstring id := testcasename();
Harald Weltea0630032018-03-20 21:09:55 +01003971 vc_conn.start(f_handler_init(fn, id, pars));
Harald Weltec1a2fff2017-12-17 11:06:19 +01003972 return vc_conn;
3973}
3974
Neels Hofmeyrda436782021-07-20 22:09:06 +02003975function f_start_handler(void_fn fn, template (omit) TestHdlrParams pars := omit)
3976runs on test_CT return MSC_ConnHdlr {
3977 return f_start_handler_run(f_start_handler_create(pars), fn, pars);
3978}
3979
Harald Weltea0630032018-03-20 21:09:55 +01003980/* first function inside ConnHdlr component; sets g_pars + starts function */
3981private function f_handler_init(void_fn fn, charstring id, template (omit) TestHdlrParams pars := omit)
3982runs on MSC_ConnHdlr {
3983 if (isvalue(pars)) {
3984 g_pars := valueof(pars);
3985 }
3986 fn.apply(id);
3987}
3988
Oliver Smith26a3db72021-07-09 13:51:29 +02003989private function f_vty_encryption_a5(charstring options) runs on test_CT {
3990 f_vty_transceive(BSCVTY, "configure terminal");
3991 f_vty_transceive(BSCVTY, "network");
3992 f_vty_transceive(BSCVTY, "encryption a5 " & options);
3993 f_vty_transceive(BSCVTY, "exit");
3994 f_vty_transceive(BSCVTY, "exit");
3995}
3996
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01003997const charstring VTY_A5_DEFAULT := "0 1 3";
3998
Oliver Smith26a3db72021-07-09 13:51:29 +02003999private function f_vty_encryption_a5_reset() runs on test_CT {
4000 /* keep in sync with docker-playground.git ttcn3-bsc-test/osmo-bsc.cfg */
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01004001 f_vty_encryption_a5(VTY_A5_DEFAULT);
Oliver Smith26a3db72021-07-09 13:51:29 +02004002}
4003
Harald Welte3c86ea02018-05-10 22:28:05 +02004004/* Establish signalling channel (non-assignment case) followed by cipher mode */
4005private function f_tc_ciph_mode_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02004006 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4007 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte3c86ea02018-05-10 22:28:05 +02004008 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Philipp Maier23000732018-05-18 11:25:37 +02004009 ass_cmd.pdu.bssmap.assignmentRequest.circuitIdentityCode := omit;
4010 ass_cmd.pdu.bssmap.assignmentRequest.aoIPTransportLayer := omit;
4011 exp_compl.pdu.bssmap.assignmentComplete.circuitIdentityCode := omit;
4012 exp_compl.pdu.bssmap.assignmentComplete.aoIPTransportLayer := omit;
Harald Welte3c86ea02018-05-10 22:28:05 +02004013
Philipp Maier23000732018-05-18 11:25:37 +02004014 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004015 f_perform_clear();
Harald Welte3c86ea02018-05-10 22:28:05 +02004016}
4017testcase TC_ciph_mode_a5_0() runs on test_CT {
4018 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004019 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004020 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
4021
4022 f_init(1, true);
4023 f_sleep(1.0);
4024 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4025 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004026 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004027}
4028testcase TC_ciph_mode_a5_1() runs on test_CT {
4029 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004030 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004031 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
4032
4033 f_init(1, true);
4034 f_sleep(1.0);
4035 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4036 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004037 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004038}
Oliver Smith50b98122021-07-09 15:00:28 +02004039/* OS#4975: verify that A5/2 is preferred over A5/0 */
4040testcase TC_ciph_mode_a5_2_0() runs on test_CT {
4041 var MSC_ConnHdlr vc_conn;
4042 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4043
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01004044 pars.encr := f_encr_params('05'O, '04'O); /* A5/0 and A5/2 (0x01|0x04)*/
Oliver Smith50b98122021-07-09 15:00:28 +02004045
4046 f_init(1, true);
4047 f_vty_encryption_a5("0 1 2 3");
4048 f_sleep(1.0);
4049 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4050 vc_conn.done;
4051 f_vty_encryption_a5_reset();
4052 f_shutdown_helper();
4053}
Oliver Smith1dff88d2021-07-09 08:45:51 +02004054/* OS#4975: verify that A5/1 is preferred over A5/2 */
4055testcase TC_ciph_mode_a5_2_1() runs on test_CT {
4056 var MSC_ConnHdlr vc_conn;
4057 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4058
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01004059 pars.encr := f_encr_params('06'O, '02'O); /* A5/1 and A5/2 (0x02|0x04)*/
Oliver Smith1dff88d2021-07-09 08:45:51 +02004060
4061 f_init(1, true);
4062 f_vty_encryption_a5("1 2");
4063 f_sleep(1.0);
4064 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4065 vc_conn.done;
4066 f_vty_encryption_a5_reset();
4067 f_shutdown_helper();
4068}
Harald Welte3c86ea02018-05-10 22:28:05 +02004069testcase TC_ciph_mode_a5_3() runs on test_CT {
4070 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004071 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004072 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
4073
4074 f_init(1, true);
4075 f_sleep(1.0);
4076 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4077 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004078 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004079}
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004080/* Establish a Signalling channel with A5/4 encryption. */
4081testcase TC_ciph_mode_a5_4() runs on test_CT {
4082 var MSC_ConnHdlr vc_conn;
4083 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4084 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Harald Welte3c86ea02018-05-10 22:28:05 +02004085
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004086 f_init(1, true);
Oliver Smith26a3db72021-07-09 13:51:29 +02004087 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004088 f_sleep(1.0);
4089 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4090 vc_conn.done;
Oliver Smith26a3db72021-07-09 13:51:29 +02004091 f_vty_encryption_a5_reset();
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004092 f_shutdown_helper();
4093}
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004094/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
4095private function f_tc_assignment_aoip_tla_v6(charstring id) runs on MSC_ConnHdlr {
4096 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4097 var PDU_BSSAP ass_cmd := f_gen_ass_req(aoip_tla := "::3");
4098 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4099 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4100
4101 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004102 f_perform_clear();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004103}
4104testcase TC_assignment_aoip_tla_v6() runs on test_CT {
4105 var MSC_ConnHdlr vc_conn;
4106 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4107
4108 f_init(1, true);
4109 f_sleep(1.0);
4110 vc_conn := f_start_handler(refers(f_tc_assignment_aoip_tla_v6), pars);
4111 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004112 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004113}
4114
Harald Welte3c86ea02018-05-10 22:28:05 +02004115
4116/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
Harald Welte651fcdc2018-05-10 20:23:16 +02004117private function f_tc_assignment_fr_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02004118 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4119 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004120
Harald Welte552620d2017-12-16 23:21:36 +01004121 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4122 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte73cd2712017-12-17 00:44:52 +01004123
Harald Weltea0630032018-03-20 21:09:55 +01004124 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004125 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004126}
Harald Welte552620d2017-12-16 23:21:36 +01004127testcase TC_assignment_fr_a5_0() runs on test_CT {
4128 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004129 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004130 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
Harald Welte552620d2017-12-16 23:21:36 +01004131
Harald Welte89d42e82017-12-17 16:42:41 +01004132 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004133 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004134 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004135 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004136 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004137}
Harald Welte552620d2017-12-16 23:21:36 +01004138testcase TC_assignment_fr_a5_1() runs on test_CT {
Harald Weltec1a2fff2017-12-17 11:06:19 +01004139 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004140 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004141 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004142
Harald Welte89d42e82017-12-17 16:42:41 +01004143 f_init(1, true);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004144 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004145 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4146 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004147 f_shutdown_helper();
Harald Welte651fcdc2018-05-10 20:23:16 +02004148}
4149testcase TC_assignment_fr_a5_3() runs on test_CT {
4150 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004151 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004152 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004153
Harald Welte651fcdc2018-05-10 20:23:16 +02004154 f_init(1, true);
4155 f_sleep(1.0);
4156 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004157 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004158 f_shutdown_helper();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004159}
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004160/* Establish a Signalling channel and re-assign to TCH/F with A5/4 encryption. */
4161testcase TC_assignment_fr_a5_4() runs on test_CT {
4162 var MSC_ConnHdlr vc_conn;
4163 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4164 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
4165
4166 f_init(1, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02004167 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004168 f_sleep(1.0);
4169 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4170 vc_conn.done;
Oliver Smith7eabd312021-07-12 14:18:56 +02004171 f_vty_encryption_a5_reset();
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004172 f_shutdown_helper();
4173}
Harald Weltec1a2fff2017-12-17 11:06:19 +01004174
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +02004175/* Allow only A5/4, but omit the Kc128 IE from MSC's msg. Expect Cipher Mode Reject. */
4176testcase TC_assignment_fr_a5_4_fail() runs on test_CT {
4177 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4178 var MSC_ConnHdlr vc_conn;
4179
4180 f_init(1, true);
4181 f_sleep(1.0);
4182
4183 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8))); // A5/4 support, but Kc128 missing!
4184 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
4185 vc_conn.done;
4186 f_shutdown_helper();
4187}
4188
Harald Welte552620d2017-12-16 23:21:36 +01004189/* Expect ASSIGNMENT FAIL if mandatory IE is missing */
4190private function f_tc_assignment_fr_a5_1_codec_missing(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004191 g_pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004192 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02004193 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004194
4195 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02004196 /* Omit: ass_cmd.pdu.bssmap.assignmentRequest.codecList */
4197
Harald Weltea0630032018-03-20 21:09:55 +01004198 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004199 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004200}
Harald Welte552620d2017-12-16 23:21:36 +01004201testcase TC_assignment_fr_a5_1_codec_missing() runs on test_CT {
4202 var MSC_ConnHdlr vc_conn;
4203
Harald Welte89d42e82017-12-17 16:42:41 +01004204 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004205 f_sleep(1.0);
4206
Harald Welte8863fa12018-05-10 20:15:27 +02004207 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5_1_codec_missing));
Harald Welte552620d2017-12-16 23:21:36 +01004208 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004209 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004210}
4211
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004212private function f_TC_assignment_a5_not_sup(charstring id) runs on MSC_ConnHdlr {
4213 var template PDU_BSSAP exp_ass_cpl := f_gen_exp_compl();
4214 var PDU_BSSAP exp_ass_req := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004215
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004216 exp_ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4217 exp_ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4218
4219 /* this is like the beginning of f_establish_fully(), but only up to ciphering reject */
4220
4221 var BSSMAP_FIELD_CodecType codecType;
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004222
4223 codecType := exp_ass_req.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType;
4224 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
4225
4226 f_create_chan_and_exp();
4227 /* we should now have a COMPL_L3 at the MSC */
4228
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004229 /* Start ciphering, expect Cipher Mode Reject */
Neels Hofmeyr6c388f22021-06-11 02:36:56 +02004230 f_cipher_mode(g_pars.encr, exp_fail := true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004231 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004232}
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004233testcase TC_assignment_fr_a5_not_sup() runs on test_CT {
4234 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004235 var MSC_ConnHdlr vc_conn;
4236
Harald Welte89d42e82017-12-17 16:42:41 +01004237 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004238 f_sleep(1.0);
4239
Neels Hofmeyr0588cad2021-06-11 01:38:18 +02004240 pars.encr := valueof(t_EncrParams('20'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004241 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004242 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004243 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004244}
4245
4246
Harald Welte4532e0a2017-12-23 02:05:44 +01004247private function f_tc_assignment_sign(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004248 g_pars := f_gen_test_hdlr_pars();
Harald Welte4532e0a2017-12-23 02:05:44 +01004249 var template PDU_BSSAP exp_compl := tr_BSSMAP_AssignmentComplete(omit, omit);
Philipp Maier48604732018-10-09 15:00:37 +02004250 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte4532e0a2017-12-23 02:05:44 +01004251 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004252
4253 f_statsd_reset();
Harald Weltea0630032018-03-20 21:09:55 +01004254 f_establish_fully(ass_cmd, exp_compl);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004255
4256 var StatsDExpects expect := {
Daniel Willmannc5398f72020-09-21 10:41:35 +02004257 { name := "TTCN3.bts.0.chreq.total", mtype := "c", min := 1, max := 1},
4258 { name := "TTCN3.bts.0.chreq.successful", mtype := "c", min := 1, max := 1},
Daniel Willmannebdecc02020-08-12 15:30:17 +02004259 { name := "TTCN3.bsc.0.assignment.attempted", mtype := "c", min := 1, max := 1},
4260 { name := "TTCN3.bsc.0.assignment.completed", mtype := "c", min := 1, max := 1}
4261 };
4262 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004263 f_perform_clear();
Harald Welte4532e0a2017-12-23 02:05:44 +01004264}
4265
4266testcase TC_assignment_sign() runs on test_CT {
4267 var MSC_ConnHdlr vc_conn;
4268
4269 f_init(1, true);
4270 f_sleep(1.0);
4271
Harald Welte8863fa12018-05-10 20:15:27 +02004272 vc_conn := f_start_handler(refers(f_tc_assignment_sign));
Harald Welte4532e0a2017-12-23 02:05:44 +01004273 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004274 f_shutdown_helper();
Harald Welte4532e0a2017-12-23 02:05:44 +01004275}
4276
Harald Welte60aa5762018-03-21 19:33:13 +01004277/***********************************************************************
4278 * Codec (list) testing
4279 ***********************************************************************/
4280
4281/* check if the given rsl_mode is compatible with the a_elem */
4282private function f_match_codec(BSSMAP_FIELD_CodecElement a_elem, RSL_IE_ChannelMode rsl_mode)
4283return boolean {
4284 select (a_elem.codecType) {
4285 case (GSM_FR) {
4286 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM1))) {
4287 return true;
4288 }
4289 }
4290 case (GSM_HR) {
4291 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM1))) {
4292 return true;
4293 }
4294 }
4295 case (GSM_EFR) {
4296 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM2))) {
4297 return true;
4298 }
4299 }
4300 case (FR_AMR) {
4301 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM3))) {
4302 return true;
4303 }
4304 }
4305 case (HR_AMR) {
4306 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM3))) {
4307 return true;
4308 }
4309 }
4310 case else { }
4311 }
4312 return false;
4313}
4314
4315/* check if the given rsl_mode is compatible with the a_list */
4316private function f_match_codecs(BSSMAP_IE_SpeechCodecList a_list, RSL_IE_ChannelMode rsl_mode)
4317return boolean {
4318 for (var integer i := 0; i < sizeof(a_list); i := i+1) {
4319 if (f_match_codec(a_list.codecElements[i], rsl_mode)) {
4320 return true;
4321 }
4322 }
4323 return false;
4324}
4325
4326/* determine BSSMAP_IE_ChannelType from *first* element of BSSMAP_FIELD_CodecElement */
Philipp Maier61f6b572018-07-06 14:03:38 +02004327function f_BSSMAP_chtype_from_codec(BSSMAP_FIELD_CodecElement a_elem)
Harald Welte60aa5762018-03-21 19:33:13 +01004328return BSSMAP_IE_ChannelType {
4329 /* FIXME: actually look at all elements of BSSMAP_IE_SpeechCodecList */
4330 var BSSMAP_IE_ChannelType ret := valueof(ts_BSSMAP_IE_ChannelType);
4331 select (a_elem.codecType) {
4332 case (GSM_FR) {
4333 ret.channelRateAndType := ChRate_TCHF;
4334 ret.speechId_DataIndicator := Spdi_TCHF_FR;
4335 }
4336 case (GSM_HR) {
4337 ret.channelRateAndType := ChRate_TCHH;
4338 ret.speechId_DataIndicator := Spdi_TCHH_HR;
4339 }
4340 case (GSM_EFR) {
4341 ret.channelRateAndType := ChRate_TCHF;
4342 ret.speechId_DataIndicator := Spdi_TCHF_EFR;
4343 }
4344 case (FR_AMR) {
4345 ret.channelRateAndType := ChRate_TCHF;
4346 ret.speechId_DataIndicator := Spdi_TCHF_AMR;
4347 }
4348 case (HR_AMR) {
4349 ret.channelRateAndType := ChRate_TCHH;
4350 ret.speechId_DataIndicator := Spdi_TCHH_AMR;
4351 }
4352 case else {
4353 setverdict(fail, "Unsupported codec ", a_elem);
Daniel Willmannafce8662018-07-06 23:11:32 +02004354 mtc.stop;
Harald Welte60aa5762018-03-21 19:33:13 +01004355 }
4356 }
4357 return ret;
4358}
4359
Harald Weltea63b9102018-03-22 20:36:16 +01004360private function f_rsl_chmod_tmpl_from_codec(BSSMAP_FIELD_CodecElement a_elem)
4361return template RSL_IE_Body {
4362 var template RSL_IE_Body mode_ie := {
4363 chan_mode := {
4364 len := ?,
4365 reserved := ?,
4366 dtx_d := ?,
4367 dtx_u := ?,
4368 spd_ind := RSL_SPDI_SPEECH,
4369 ch_rate_type := -,
Oliver Smith0033b122023-02-28 13:30:53 +01004370 u := { speech := - }
Harald Weltea63b9102018-03-22 20:36:16 +01004371 }
4372 }
4373
4374 select (a_elem.codecType) {
4375 case (GSM_FR) {
4376 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004377 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM1;
Harald Weltea63b9102018-03-22 20:36:16 +01004378 }
4379 case (GSM_HR) {
4380 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
Oliver Smith0033b122023-02-28 13:30:53 +01004381 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM1;
Harald Weltea63b9102018-03-22 20:36:16 +01004382 }
4383 case (GSM_EFR) {
4384 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004385 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM2;
Harald Weltea63b9102018-03-22 20:36:16 +01004386 }
4387 case (FR_AMR) {
4388 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004389 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM3;
Harald Weltea63b9102018-03-22 20:36:16 +01004390 }
4391 case (HR_AMR) {
4392 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
Oliver Smith0033b122023-02-28 13:30:53 +01004393 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM3;
Harald Weltea63b9102018-03-22 20:36:16 +01004394 }
4395 }
4396 return mode_ie;
4397}
4398
Harald Welte60aa5762018-03-21 19:33:13 +01004399type record CodecListTest {
4400 BSSMAP_IE_SpeechCodecList codec_list,
4401 charstring id
4402}
4403type record of CodecListTest CodecListTests
4404
4405private function f_TC_assignment_codec(charstring id) runs on MSC_ConnHdlr {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004406 f_assignment_codec(id);
4407}
4408
4409private function f_assignment_codec(charstring id, boolean do_perform_clear := true) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02004410 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02004411 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Harald Welte60aa5762018-03-21 19:33:13 +01004412
4413 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004414 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte79f3f542018-05-25 20:02:37 +02004415 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4416 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
4417 g_pars.ass_codec_list.codecElements[0];
Philipp Maierd0e64b02019-03-13 14:15:23 +01004418 if (isvalue(g_pars.expect_mr_s0_s7)) {
4419 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
4420 g_pars.expect_mr_s0_s7;
4421 }
Harald Welte79f3f542018-05-25 20:02:37 +02004422 }
Harald Welte60aa5762018-03-21 19:33:13 +01004423 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4424 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
Harald Welte60aa5762018-03-21 19:33:13 +01004425 log("expecting ASS COMPL like this: ", exp_compl);
4426
4427 f_establish_fully(ass_cmd, exp_compl);
Harald Weltea63b9102018-03-22 20:36:16 +01004428
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004429 if (not g_pars.expect_channel_mode_modify) {
4430 /* Verify that the RSL-side activation actually matches our expectations */
4431 var RSL_Message rsl := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
Harald Weltea63b9102018-03-22 20:36:16 +01004432
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004433 var RSL_IE_Body mode_ie;
4434 if (f_rsl_find_ie(rsl, RSL_IE_CHAN_MODE, mode_ie) == false) {
4435 setverdict(fail, "Couldn't find CHAN_MODE IE");
Daniel Willmannafce8662018-07-06 23:11:32 +02004436 mtc.stop;
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004437 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004438 var template RSL_IE_Body t_mode_ie := f_rsl_chmod_tmpl_from_codec(g_pars.ass_codec_list.codecElements[0]);
4439 if (not match(mode_ie, t_mode_ie)) {
4440 log("mode_ie ", mode_ie, " != t_mode_ie ", t_mode_ie);
4441 setverdict(fail, "RSL Channel Mode IE doesn't match expectation");
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004442 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004443
4444 var RSL_IE_Body mr_conf;
4445 if (g_pars.expect_mr_conf_ie != omit) {
4446 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == false) {
4447 setverdict(fail, "Missing MR CONFIG IE in RSL Chan Activ");
4448 mtc.stop;
4449 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004450 log("found RSL MR CONFIG IE: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004451
4452 if (not match(mr_conf, g_pars.expect_mr_conf_ie)) {
Vadim Yanitskiy8b189372022-09-14 17:31:17 +07004453 setverdict(fail, "RSL MR CONFIG IE does not match expectation. ",
4454 "Expected: ", g_pars.expect_mr_conf_ie, ", got: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004455 }
4456 } else {
4457 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == true) {
4458 log("found RSL MR CONFIG IE: ", mr_conf);
4459 setverdict(fail, "Found MR CONFIG IE in RSL Chan Activ, expecting omit");
4460 mtc.stop;
4461 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004462 }
4463 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004464
4465 if (do_perform_clear) {
4466 f_perform_clear();
4467 }
Harald Welte60aa5762018-03-21 19:33:13 +01004468}
4469
Philipp Maierd0e64b02019-03-13 14:15:23 +01004470private function f_TC_assignment_codec_fail(charstring id) runs on MSC_ConnHdlr {
4471
4472 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4473 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4474
4475 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004476 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maierd0e64b02019-03-13 14:15:23 +01004477 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4478 }
4479 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4480 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
4481 log("expecting ASS FAIL like this: ", exp_fail);
4482
4483 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004484 f_perform_clear();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004485}
4486
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004487const CounterNameVals counternames_bsc_bts_assignment := {
4488 { "assignment:attempted", 0 },
4489 { "assignment:completed", 0 },
4490 { "assignment:stopped", 0 },
4491 { "assignment:no_channel", 0 },
4492 { "assignment:timeout", 0 },
4493 { "assignment:failed", 0 },
4494 { "assignment:error", 0 }
4495};
4496
4497const CounterNameVals counternames_bts_assignment := {
4498 { "assignment:attempted_sign", 0 },
4499 { "assignment:attempted_speech", 0 },
4500 { "assignment:completed_sign", 0 },
4501 { "assignment:completed_speech", 0 },
4502 { "assignment:stopped_sign", 0 },
4503 { "assignment:stopped_speech", 0 },
4504 { "assignment:no_channel_sign", 0 },
4505 { "assignment:no_channel_speech", 0 },
4506 { "assignment:timeout_sign", 0 },
4507 { "assignment:timeout_speech", 0 },
4508 { "assignment:failed_sign", 0 },
4509 { "assignment:failed_speech", 0 },
4510 { "assignment:error_sign", 0 },
4511 { "assignment:error_speech", 0 }
4512};
4513
4514function f_ctrs_bsc_and_bts_assignment_init(integer bts_count := NUM_BTS) runs on test_CT {
4515 var CounterNameVals bts_names := counternames_bsc_bts_assignment & counternames_bts_assignment;
4516 f_ctrs_bts_init(bts_count, bts_names);
4517 f_ctrs_bsc_init(counternames_bsc_bts_assignment);
4518}
4519
Harald Welte60aa5762018-03-21 19:33:13 +01004520testcase TC_assignment_codec_fr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004521 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004522 var MSC_ConnHdlr vc_conn;
4523
4524 f_init(1, true);
4525 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004526 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004527
4528 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004529 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004530 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004531
4532 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4533 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4534 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4535 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4536 f_ctrs_bts_verify();
4537
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004538 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004539}
4540
4541testcase TC_assignment_codec_hr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004542 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004543 var MSC_ConnHdlr vc_conn;
4544
4545 f_init(1, true);
4546 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004547 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004548
4549 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004550 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004551 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004552
4553 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4554 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4555 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4556 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4557 f_ctrs_bts_verify();
4558
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004559 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004560}
4561
4562testcase TC_assignment_codec_efr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004563 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004564 var MSC_ConnHdlr vc_conn;
4565
4566 f_init(1, true);
4567 f_sleep(1.0);
4568
4569 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecEFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004570 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004571 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004572 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004573}
4574
Philipp Maierd0e64b02019-03-13 14:15:23 +01004575/* Allow 5,90k only (current default config) */
4576private function f_allow_amr_rate_5_90k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004577 f_vty_cfg_msc(BSCVTY, 0, {
4578 "amr-config 12_2k forbidden",
4579 "amr-config 10_2k forbidden",
4580 "amr-config 7_95k forbidden",
4581 "amr-config 7_40k forbidden",
4582 "amr-config 6_70k forbidden",
4583 "amr-config 5_90k allowed",
4584 "amr-config 5_15k forbidden",
4585 "amr-config 4_75k forbidden"
4586 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004587}
4588
4589/* Allow 4,75k, 5,90k, 4,70k and 12,2k, which are the most common rates
4590 * ("Config-NB-Code = 1") */
4591private function f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004592 f_vty_cfg_msc(BSCVTY, 0, {
4593 "amr-config 12_2k allowed",
4594 "amr-config 10_2k forbidden",
4595 "amr-config 7_95k forbidden",
4596 "amr-config 7_40k allowed",
4597 "amr-config 6_70k forbidden",
4598 "amr-config 5_90k allowed",
4599 "amr-config 5_15k forbidden",
4600 "amr-config 4_75k allowed"
4601 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004602}
4603
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004604private function f_vty_amr_start_mode_set(boolean fr, charstring startmode) runs on test_CT {
4605 var charstring tch;
4606 if (fr) {
4607 tch := "tch-f";
4608 } else {
4609 tch := "tch-h";
4610 }
4611 f_vty_cfg_bts(BSCVTY, 0, { "amr " & tch & " start-mode " & startmode });
4612}
4613
4614/* Set the AMR start-mode for this TCH back to the default configuration. */
4615private function f_vty_amr_start_mode_restore(boolean fr) runs on test_CT {
4616 f_vty_amr_start_mode_set(fr, "auto");
4617}
4618
Harald Welte60aa5762018-03-21 19:33:13 +01004619testcase TC_assignment_codec_amr_f() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004620 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004621 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004622
4623 /* Note: This setups the codec configuration. The parameter payload in
4624 * mr_conf must be consistant with the parameter codecElements in pars
4625 * and also must match the amr-config in osmo-bsc.cfg! */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004626 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004627 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004628 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004629 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004630
Harald Welte60aa5762018-03-21 19:33:13 +01004631 f_init(1, true);
4632 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004633 f_vty_amr_start_mode_set(true, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004634 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004635
Harald Welte8863fa12018-05-10 20:15:27 +02004636 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004637 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004638
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004639 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4640 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4641 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4642 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4643 f_ctrs_bts_verify();
4644
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004645 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004646 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004647}
4648
4649testcase TC_assignment_codec_amr_h() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004650 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004651 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004652
4653 /* See note above */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004654 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004655 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004656 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004657 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004658
Harald Welte60aa5762018-03-21 19:33:13 +01004659 f_init(1, true);
4660 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004661 f_vty_amr_start_mode_set(false, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004662 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004663
Harald Welte8863fa12018-05-10 20:15:27 +02004664 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004665 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004666
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004667 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4668 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4669 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4670 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4671 f_ctrs_bts_verify();
4672
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004673 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004674 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004675}
4676
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004677/* Establish signalling on a TCH/F lchan, and then switch to speech mode without a new Assignment. */
4678testcase TC_assignment_codec_fr_by_mode_modify() runs on test_CT {
4679 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4680 var MSC_ConnHdlr vc_conn;
4681
4682 f_init(1, true);
4683 f_sleep(1.0);
4684
4685 /* By disabling all SDCCH, the MS should be given a TCH/F for signalling. Then activating an FR codec should
4686 * merely do a Channel Mode Modify, and not assign to a new lchan. f_establish_fully() already accounts for
4687 * expecting a Channel Mode Modify if the channel type is compatible. */
4688 f_disable_all_sdcch();
4689 f_disable_all_tch_h();
4690
4691 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4692 pars.expect_channel_mode_modify := true;
4693 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4694 vc_conn.done;
4695
4696 f_enable_all_sdcch();
4697 f_enable_all_tch();
4698 f_shutdown_helper();
4699}
4700
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004701/* 'amr start-mode auto' should not keep the (unused) 'smod' bits from previous configuration */
4702testcase TC_assignment_codec_amr_startmode_cruft() runs on test_CT {
4703 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4704 var MSC_ConnHdlr vc_conn;
4705
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004706 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4707 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
4708 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy36fe9582022-09-14 15:25:04 +07004709 pars.expect_mr_conf_ie := c_mr_conf_5_90;
4710 pars.expect_mr_conf_ie.multirate_cfg.icmi := false; /* expect ICMI=0, smod=00: */
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004711
4712 f_init(1, true);
4713 f_sleep(1.0);
4714
4715 /* First set nonzero start mode bits */
4716 f_vty_amr_start_mode_set(true, "4");
4717 /* Now set to auto, and expect the startmode bits to be zero in the message, i.e. ensure that osmo-bsc does not
4718 * let the startmode bits stick around and has deterministic MultiRate config for 'start-mode auto'; that is
4719 * ensured by above '2004'O, where 'x0xx'O indicates ICMI = 0, spare = 0, smod = 00. */
4720 f_vty_amr_start_mode_set(true, "auto");
4721
4722 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4723 vc_conn.done;
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004724
4725 /* Clear the startmode bits to not affect subsequent tests, in case the bits should indeed stick around. */
4726 f_vty_amr_start_mode_set(true, "1");
4727 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004728 f_shutdown_helper();
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004729}
4730
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004731function f_TC_assignment_codec_amr(boolean fr, RSL_IE_MultirateCfg mr_cfg,
4732 bitstring s8_s0, bitstring exp_s8_s0,
4733 charstring start_mode := "1")
Philipp Maierd0e64b02019-03-13 14:15:23 +01004734runs on test_CT {
4735
4736 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4737 var MSC_ConnHdlr vc_conn;
4738
Philipp Maierd0e64b02019-03-13 14:15:23 +01004739 if (fr) {
4740 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4741 } else {
4742 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4743 }
4744 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4745 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004746 pars.expect_mr_conf_ie := { multirate_cfg := mr_cfg };
Philipp Maierd0e64b02019-03-13 14:15:23 +01004747 pars.expect_mr_s0_s7 := exp_s8_s0;
4748
4749 f_init(1, true);
4750 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004751 f_vty_amr_start_mode_set(fr, start_mode);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004752 f_sleep(1.0);
4753
4754 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4755 vc_conn.done;
4756 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004757 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004758}
4759
4760function f_TC_assignment_codec_amr_fail(boolean fr, bitstring s8_s0)
4761runs on test_CT {
4762
4763 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4764 var MSC_ConnHdlr vc_conn;
4765
4766 if (fr) {
4767 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4768 } else {
4769 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4770 }
4771 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4772 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
4773
4774 f_init(1, true);
4775 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004776 f_vty_amr_start_mode_set(fr, "1");
Philipp Maierd0e64b02019-03-13 14:15:23 +01004777 f_sleep(1.0);
4778
4779 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fail), pars);
4780 vc_conn.done;
4781 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004782 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004783}
4784
Philipp Maierd0e64b02019-03-13 14:15:23 +01004785/* Set S1, we expect an AMR multirate configuration IE with all four rates
4786 * set. */
4787testcase TC_assignment_codec_amr_f_S1() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004788 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4789 params := '20882208'O));
4790 f_TC_assignment_codec_amr(true, mr_cfg, '00000011'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004791 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004792}
4793
4794/* Set S1, we expect an AMR multirate configuration IE with the lower three
4795 * rates set. */
4796testcase TC_assignment_codec_amr_h_S1() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004797 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4798 params := '208820'O));
4799 f_TC_assignment_codec_amr(false, mr_cfg, '00000010'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004800 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004801}
4802
4803/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4804 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4805testcase TC_assignment_codec_amr_f_S124() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004806 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4807 params := '20882208'O));
4808 f_TC_assignment_codec_amr(true, mr_cfg, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004809 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004810}
4811
4812/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4813 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4814testcase TC_assignment_codec_amr_h_S124() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004815 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4816 params := '208820'O));
4817 f_TC_assignment_codec_amr(false, mr_cfg, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004818 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004819}
4820
4821/* The following block of tests selects more and more rates until all four
4822 * possible rates are in the active set (full rate) */
4823testcase TC_assignment_codec_amr_f_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004824 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4825 f_TC_assignment_codec_amr(true, mr_cfg, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004826 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004827}
4828
4829testcase TC_assignment_codec_amr_f_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004830 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4831 params := '2080'O));
4832 f_TC_assignment_codec_amr(true, mr_cfg, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004833 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004834}
4835
4836testcase TC_assignment_codec_amr_f_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004837 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4838 params := '208820'O));
4839 f_TC_assignment_codec_amr(true, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004840 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004841}
4842
4843testcase TC_assignment_codec_amr_f_S0247() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004844 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4845 params := '20882208'O));
4846 f_TC_assignment_codec_amr(true, mr_cfg, '10010101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004847 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004848}
4849
4850/* The following block of tests selects more and more rates until all three
4851 * possible rates are in the active set (half rate) */
4852testcase TC_assignment_codec_amr_h_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004853 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4854 f_TC_assignment_codec_amr(false, mr_cfg, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004855 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004856}
4857
4858testcase TC_assignment_codec_amr_h_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004859 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4860 params := '2080'O));
4861 f_TC_assignment_codec_amr(false, mr_cfg, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004862 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004863}
4864
4865testcase TC_assignment_codec_amr_h_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004866 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4867 params := '208820'O));
4868 f_TC_assignment_codec_amr(false, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004869 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004870}
4871
4872/* The following block tests what happens when the MSC does offer rate
4873 * configurations that are not supported by the BSC. Normally such situations
4874 * should not happen because the MSC gets informed by the BSC in advance via
4875 * the L3 COMPLETE message which rates are applicable. The MSC should not try
4876 * to offer rates that are not applicable anyway. */
4877
4878testcase TC_assignment_codec_amr_h_S0247() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004879 /* Try to include 12,2k in into the active set even though the channel
4880 * is half rate only. The BSC is expected to remove the 12,0k */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004881 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4882 params := '208820'O));
4883 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004884 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004885}
4886
4887testcase TC_assignment_codec_amr_f_S01234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004888 /* See what happens when all rates are selected at once. Since then
4889 * Also S1 is selected, this setting will be prefered and we should
4890 * get 12.2k, 7,40k, 5,90k, and 4,75k in the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004891 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4892 params := '20882208'O));
4893 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004894 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004895}
4896
4897testcase TC_assignment_codec_amr_f_S0234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004898 /* Same as above, but with S1 missing, the MSC is then expected to
4899 * select the currently supported rates, which are also 12.2k, 7,40k,
4900 * 5,90k, and 4,75k, into the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004901 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4902 params := '20882208'O));
4903 f_TC_assignment_codec_amr(true, mr_cfg, '11111101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004904 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004905}
4906
4907testcase TC_assignment_codec_amr_f_zero() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004908 /* Try to select no rates at all */
4909 f_TC_assignment_codec_amr_fail(true, '00000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004910 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004911}
4912
4913testcase TC_assignment_codec_amr_f_unsupp() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004914 /* Try to select only unsupported rates */
4915 f_TC_assignment_codec_amr_fail(true, '01101000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004916 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004917}
4918
4919testcase TC_assignment_codec_amr_h_S7() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004920 /* Try to select 12,2k for half rate */
4921 f_TC_assignment_codec_amr_fail(false, '10000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004922 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004923}
4924
Neels Hofmeyr21863562020-11-26 00:34:33 +00004925testcase TC_assignment_codec_amr_f_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004926 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
4927 codec_modes := '10010101'B,
4928 params := '20882208'O));
4929 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004930 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004931}
4932
4933testcase TC_assignment_codec_amr_h_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004934 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
4935 codec_modes := '00010101'B,
4936 params := '208820'O));
4937 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B,
Neels Hofmeyr21863562020-11-26 00:34:33 +00004938 start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004939 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004940}
4941
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004942testcase TC_assignment_codec_amr_f_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004943 /* "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 +07004944 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 3,
4945 codec_modes := '10010101'B,
4946 params := '20882208'O));
4947 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004948 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004949}
4950
4951testcase TC_assignment_codec_amr_h_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004952 /* "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 +07004953 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 2,
4954 codec_modes := '00010101'B,
4955 params := '208820'O));
4956 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004957 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004958}
4959
Philipp Maierac09bfc2019-01-08 13:41:39 +01004960private function f_disable_all_tch_f() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004961 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 borken");
4962 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 borken");
4963 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 borken");
4964 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004965}
4966
4967private function f_disable_all_tch_h() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004968 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 borken");
4969 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004970}
4971
4972private function f_enable_all_tch() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004973 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 unused");
4974 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 unused");
4975 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 unused");
4976 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 unused");
4977 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 unused");
4978 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 unused");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004979}
4980
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004981private function f_disable_all_sdcch() runs on test_CT {
4982 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 borken");
4983 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 borken");
4984 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 borken");
4985 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 borken");
4986}
4987
4988private function f_enable_all_sdcch() runs on test_CT {
4989 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 unused");
4990 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 unused");
4991 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 unused");
4992 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 unused");
4993}
4994
Philipp Maierac09bfc2019-01-08 13:41:39 +01004995/* Allow HR only */
4996private function f_TC_assignment_codec_xr_exhausted_req_hr(charstring id) runs on MSC_ConnHdlr {
4997 g_pars := f_gen_test_hdlr_pars();
4998 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4999 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5000 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5001 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
5002 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
5003 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5004 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005005 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005006}
5007
5008/* Allow FR only */
5009private function f_TC_assignment_codec_xr_exhausted_req_fr(charstring id) runs on MSC_ConnHdlr {
5010 g_pars := f_gen_test_hdlr_pars();
5011 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5012 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5013 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5014 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
5015 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
5016 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5017 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005018 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005019}
5020
5021/* Allow HR only (expect assignment failure) */
5022private function f_TC_assignment_codec_xr_exhausted_req_hr_fail(charstring id) runs on MSC_ConnHdlr {
5023 g_pars := f_gen_test_hdlr_pars();
5024 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5025 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
5026 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5027 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
5028 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
5029 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5030 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005031 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005032}
5033
5034/* Allow FR only (expect assignment failure) */
5035private function f_TC_assignment_codec_xr_exhausted_req_fr_fail(charstring id) runs on MSC_ConnHdlr {
5036 g_pars := f_gen_test_hdlr_pars();
5037 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5038 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
5039 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5040 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
5041 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
5042 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5043 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005044 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005045}
5046
5047/* Allow FR and HR, but prefer FR */
5048private function f_TC_assignment_codec_fr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5049 g_pars := f_gen_test_hdlr_pars();
5050 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5051 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5052 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5053 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5054 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5055 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5056 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5057 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005058 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005059}
5060
5061/* Allow FR and HR, but prefer HR */
5062private function f_TC_assignment_codec_fr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5063 g_pars := f_gen_test_hdlr_pars();
5064 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5065 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5066 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5067 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5068 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5069 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5070 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5071 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005072 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005073}
5074
5075/* Allow FR and HR, but prefer FR */
5076private function f_TC_assignment_codec_hr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5077 g_pars := f_gen_test_hdlr_pars();
5078 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5079 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5080 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5081 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5082 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5083 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5084 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5085 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005086 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005087}
5088
5089/* Allow FR and HR, but prefer HR */
5090private function f_TC_assignment_codec_hr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5091 g_pars := f_gen_test_hdlr_pars();
5092 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5093 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5094 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5095 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5096 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5097 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5098 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5099 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005100 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005101}
5102
5103/* Request a HR channel while all FR channels are exhausted, this is expected
5104 * to work without conflicts */
5105testcase TC_assignment_codec_fr_exhausted_req_hr() runs on test_CT {
5106 var MSC_ConnHdlr vc_conn;
5107 f_init(1, true);
5108 f_sleep(1.0);
5109 f_enable_all_tch();
5110 f_disable_all_tch_f();
5111 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr));
5112 vc_conn.done;
5113 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005114 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005115}
5116
5117/* Request a FR channel while all FR channels are exhausted, this is expected
5118 * to fail. */
5119testcase TC_assignment_codec_fr_exhausted_req_fr() runs on test_CT {
5120 var MSC_ConnHdlr vc_conn;
5121 f_init(1, true);
5122 f_sleep(1.0);
5123 f_enable_all_tch();
5124 f_disable_all_tch_f();
5125 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr_fail));
5126 vc_conn.done;
5127 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005128 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005129}
5130
5131/* Request a FR (prefered) or alternatively a HR channel while all FR channels
5132 * are exhausted, this is expected to be resolved by selecting a HR channel. */
5133testcase TC_assignment_codec_fr_exhausted_req_fr_hr() runs on test_CT {
5134 var MSC_ConnHdlr vc_conn;
5135 f_init(1, true);
5136 f_sleep(1.0);
5137 f_enable_all_tch();
5138 f_disable_all_tch_f();
5139 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_fr_hr));
5140 vc_conn.done;
5141 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005142 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005143}
5144
5145/* Request a HR (prefered) or alternatively a FR channel while all FR channels
5146 * are exhausted, this is expected to work without conflicts. */
5147testcase TC_assignment_codec_fr_exhausted_req_hr_fr() runs on test_CT {
5148 var MSC_ConnHdlr vc_conn;
5149 f_init(1, true);
5150 f_sleep(1.0);
5151 f_enable_all_tch();
5152 f_disable_all_tch_f();
5153 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_hr_fr));
5154 vc_conn.done;
5155 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005156 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005157}
5158
5159/* Request a FR channel while all HR channels are exhausted, this is expected
5160 * to work without conflicts */
5161testcase TC_assignment_codec_hr_exhausted_req_fr() runs on test_CT {
5162 var MSC_ConnHdlr vc_conn;
5163 f_init(1, true);
5164 f_sleep(1.0);
5165 f_enable_all_tch();
5166 f_disable_all_tch_h();
5167 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr));
5168 vc_conn.done;
5169 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005170 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005171}
5172
5173/* Request a HR channel while all HR channels are exhausted, this is expected
5174 * to fail. */
5175testcase TC_assignment_codec_hr_exhausted_req_hr() runs on test_CT {
5176 var MSC_ConnHdlr vc_conn;
5177 f_init(1, true);
5178 f_sleep(1.0);
5179 f_enable_all_tch();
5180 f_disable_all_tch_h();
5181 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr_fail));
5182 vc_conn.done;
5183 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005184 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005185}
5186
5187/* Request a HR (prefered) or alternatively a FR channel while all HR channels
5188 * are exhausted, this is expected to be resolved by selecting a FR channel. */
5189testcase TC_assignment_codec_hr_exhausted_req_hr_fr() runs on test_CT {
5190 var MSC_ConnHdlr vc_conn;
5191 f_init(1, true);
5192 f_sleep(1.0);
5193 f_enable_all_tch();
5194 f_disable_all_tch_h();
5195 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_hr_fr));
5196 vc_conn.done;
5197 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005198 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005199}
5200
5201/* Request a FR (prefered) or alternatively a HR channel while all HR channels
5202 * are exhausted, this is expected to work without conflicts. */
5203testcase TC_assignment_codec_hr_exhausted_req_fr_hr() runs on test_CT {
5204 var MSC_ConnHdlr vc_conn;
5205 f_init(1, true);
5206 f_sleep(1.0);
5207 f_enable_all_tch();
5208 f_disable_all_tch_h();
5209 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_fr_hr));
5210 vc_conn.done;
5211 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005212 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005213}
5214
5215/* Allow FR and HR, but prefer HR */
5216private function f_TC_assignment_codec_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5217 g_pars := f_gen_test_hdlr_pars();
5218 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5219 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5220 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5221 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5222 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5223 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5224 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5225 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005226 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005227}
5228
5229/* Allow FR and HR, but prefer FR */
5230private function f_TC_assignment_codec_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5231 g_pars := f_gen_test_hdlr_pars();
5232 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5233 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5234 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5235 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5236 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5237 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5238 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5239 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005240 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005241}
5242
5243/* Request a HR (prefered) or alternatively a FR channel, it is expected that
5244 * HR, which is the prefered type, is selected. */
5245testcase TC_assignment_codec_req_hr_fr() runs on test_CT {
5246 var MSC_ConnHdlr vc_conn;
5247 f_init(1, true);
5248 f_sleep(1.0);
5249 f_enable_all_tch();
5250 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_hr_fr));
5251 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005252 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005253}
5254
5255/* Request a FR (prefered) or alternatively a HR channel, it is expected that
5256 * FR, which is the prefered type, is selected. */
5257testcase TC_assignment_codec_req_fr_hr() runs on test_CT {
5258 var MSC_ConnHdlr vc_conn;
5259 f_init(1, true);
5260 f_sleep(1.0);
5261 f_enable_all_tch();
5262 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_fr_hr));
5263 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005264 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005265}
5266
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005267/* request a signalling channel with all SDCCH exhausted, it is expected that a TCH will be selected */
5268private function f_TC_assignment_sdcch_exhausted_req_signalling(charstring id) runs on MSC_ConnHdlr {
5269 g_pars := f_gen_test_hdlr_pars();
5270 g_pars.ra := '02'O; /* RA containing reason=LU */
5271
5272 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5273 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5274 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5275 var template uint3_t tsc := ?;
5276
5277 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5278 f_create_bssmap_exp(l3_enc);
5279 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5280 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5281
5282 /* we should now have a COMPL_L3 at the MSC */
5283 timer T := 10.0;
5284 T.start;
5285 alt {
5286 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5287 [] T.timeout {
5288 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5289 }
5290 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005291
5292 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005293}
5294testcase TC_assignment_sdcch_exhausted_req_signalling() runs on test_CT {
5295 var MSC_ConnHdlr vc_conn;
5296 f_init(1, true);
5297 f_sleep(1.0);
5298 f_disable_all_sdcch();
5299 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_signalling));
5300 vc_conn.done;
5301 f_enable_all_sdcch();
5302 f_shutdown_helper();
5303}
5304
5305/* Request a signalling channel with all SDCCH exhausted, it is
5306 expected that no TCH will be selected for signalling and assigment will fail
5307 because it's dictated by VTY config */
5308testcase TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() runs on test_CT {
5309 var RSL_Message rsl_unused, rsl_msg;
5310 var GsmRrMessage rr;
5311 f_init(1, false);
5312 f_sleep(1.0);
5313 f_vty_allow_tch_for_signalling(false, 0);
5314 f_disable_all_sdcch();
5315
5316 /* RA containing reason=LU */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005317 f_ipa_tx(ts_RSL_CHAN_RQD('02'O, 2342));
5318 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005319 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
5320 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
5321 setverdict(fail, "Expected reject");
5322 }
5323
5324 f_vty_allow_tch_for_signalling(true, 0);
5325 f_enable_all_sdcch();
5326 f_shutdown_helper();
5327}
5328
5329/* Request a voice channel with all SDCCH exhausted, it is
5330 * expected that TCH channel will be allocated since the VTY option is only
5331 * aimed at signalling requests */
5332private function f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden(charstring id) runs on MSC_ConnHdlr {
5333 g_pars := f_gen_test_hdlr_pars();
5334 g_pars.ra := '43'O; /* RA containing reason=originating speech call*/
5335
5336 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5337 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5338 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5339 var template uint3_t tsc := ?;
5340
5341 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5342 f_create_bssmap_exp(l3_enc);
5343 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5344 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5345
5346 /* we should now have a COMPL_L3 at the MSC */
5347 timer T := 10.0;
5348 T.start;
5349 alt {
5350 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5351 [] T.timeout {
5352 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5353 }
5354 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005355 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005356}
5357testcase TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() runs on test_CT {
5358 var MSC_ConnHdlr vc_conn;
5359 f_init(1, true);
5360 f_sleep(1.0);
5361 f_vty_allow_tch_for_signalling(false, 0);
5362 f_disable_all_sdcch();
5363
5364 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden));
5365 vc_conn.done;
5366
5367 f_vty_allow_tch_for_signalling(true, 0);
5368 f_enable_all_sdcch();
5369 f_shutdown_helper();
5370}
5371
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005372/* Test Osmux setup BSC<->MSC */
5373testcase TC_assignment_osmux_cn() runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005374 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5375 var MSC_ConnHdlr vc_conn;
5376
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005377 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5378 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5379 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiyb9bf00f2022-09-14 15:35:37 +07005380 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02005381 pars.use_osmux_cn := true;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005382
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02005383 g_osmux_enabled_cn := true;
5384 f_init(1, true);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005385 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005386 f_vty_amr_start_mode_set(false, "1");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005387
5388 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5389 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005390
5391 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01005392 f_shutdown_helper();
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005393}
5394
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005395/* Test Osmux setup BTS<->BSC */
5396testcase TC_assignment_osmux_bts() runs on test_CT {
5397 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5398 var MSC_ConnHdlr vc_conn;
5399
5400 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5401 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5402 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005403 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005404 pars.use_osmux_bts := true;
5405
5406 g_osmux_enabled_bts := true;
5407 f_init(1, true);
5408 f_sleep(1.0);
5409 f_vty_amr_start_mode_set(false, "1");
5410
5411 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5412 vc_conn.done;
5413
5414 f_vty_amr_start_mode_restore(false);
5415 f_shutdown_helper();
5416}
5417
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +02005418/* Test non-AMR codecs still work fine as RTP when Osmux is enabled BTS<->BSC<->MSC */
5419testcase TC_assignment_codec_hr_osmux_on() runs on test_CT {
5420 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5421 var MSC_ConnHdlr vc_conn;
5422
5423 g_osmux_enabled_cn := true;
5424 g_osmux_enabled_bts := true;
5425 f_init(1, true);
5426 f_sleep(1.0);
5427 f_ctrs_bsc_and_bts_assignment_init(1);
5428
5429 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5430 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5431 vc_conn.done;
5432
5433 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
5434 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
5435 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
5436 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
5437 f_ctrs_bts_verify();
5438
5439 f_shutdown_helper();
5440}
5441
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005442/* Test Osmux setup BTS<->BSC<->MSC */
5443testcase TC_assignment_osmux() runs on test_CT {
5444 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5445 var MSC_ConnHdlr vc_conn;
5446
5447 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5448 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5449 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005450 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005451 pars.use_osmux_cn := true;
5452 pars.use_osmux_bts := true;
5453
5454 g_osmux_enabled_cn := true;
5455 g_osmux_enabled_bts := true;
5456 f_init(1, true);
5457 f_sleep(1.0);
5458 f_vty_amr_start_mode_set(false, "1");
5459
5460 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5461 vc_conn.done;
5462
5463 f_vty_amr_start_mode_restore(false);
5464 f_shutdown_helper();
5465}
5466
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005467/* test the procedure of the MSC requesting a Classmark Update:
5468 * a) BSSMAP Classmark Request should result in RR CLASSMARK ENQUIRY,
5469 * b) L3 RR CLASSMARK CHANGE should result in BSSMAP CLASSMARK UPDATE */
Harald Welte898113b2018-01-31 18:32:21 +01005470private function f_tc_classmark(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005471 g_pars := f_gen_test_hdlr_pars();
5472
Harald Weltea0630032018-03-20 21:09:55 +01005473 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005474 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005475
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005476 BSSAP.send(ts_BSSMAP_ClassmarkRequest);
5477 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_CM_ENQUIRY));
5478
Harald Welte898113b2018-01-31 18:32:21 +01005479 f_rsl_send_l3(ts_RRM_CM_CHG(valueof(ts_CM2)));
5480 BSSAP.receive(tr_BSSMAP_ClassmarkUpd(?, omit));
5481 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005482
5483 f_perform_clear();
Harald Welte898113b2018-01-31 18:32:21 +01005484}
5485testcase TC_classmark() runs on test_CT {
5486 var MSC_ConnHdlr vc_conn;
5487 f_init(1, true);
5488 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005489 vc_conn := f_start_handler(refers(f_tc_classmark));
Harald Welte898113b2018-01-31 18:32:21 +01005490 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005491 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005492}
5493
Harald Welteeddf0e92020-06-21 19:42:15 +02005494/* Send a CommonID from the simulated MSC and verify that the information is used to
5495 * fill BSC-internal data structures (specifically, bsc_subscr associated with subscr_conn) */
5496private function f_tc_common_id(charstring id) runs on MSC_ConnHdlr {
5497 g_pars := f_gen_test_hdlr_pars();
5498 f_MscConnHdlr_init_vty();
5499
5500 f_create_chan_and_exp();
5501 /* we should now have a COMPL_L3 at the MSC */
Harald Welteeddf0e92020-06-21 19:42:15 +02005502
5503 /* Send CommonID */
5504 BSSAP.send(ts_BSSMAP_CommonId(g_pars.imsi));
5505
5506 /* Use VTY to verify that the IMSI of the subscr_conn is set */
5507 var charstring regex := "*(IMSI: " & hex2str(g_pars.imsi) & ")*";
5508 f_vty_transceive_match_regexp_retry(BSCVTY, "show conns", regex, 0, 4, 1.0);
5509
5510 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005511
5512 f_perform_clear();
Harald Welteeddf0e92020-06-21 19:42:15 +02005513}
5514testcase TC_common_id() runs on test_CT {
5515 var MSC_ConnHdlr vc_conn;
5516 f_init(1, true);
5517 f_sleep(1.0);
5518 vc_conn := f_start_handler(refers(f_tc_common_id));
5519 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005520 f_shutdown_helper();
Harald Welteeddf0e92020-06-21 19:42:15 +02005521}
5522
Harald Weltee3bd6582018-01-31 22:51:25 +01005523private function f_est_single_l3(template PDU_ML3_MS_NW l3) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005524 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005525 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005526 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005527
Harald Weltee3bd6582018-01-31 22:51:25 +01005528 /* send the single message we want to send */
5529 f_rsl_send_l3(l3);
5530}
5531
5532private function f_bssap_expect_nothing(float sec := 5.00) runs on MSC_ConnHdlr {
5533 timer T := sec;
5534 var PDU_BSSAP bssap;
Harald Welte898113b2018-01-31 18:32:21 +01005535 T.start;
5536 alt {
Harald Weltee3bd6582018-01-31 22:51:25 +01005537 [] BSSAP.receive(PDU_BSSAP:?) -> value bssap {
5538 setverdict(fail, "Unexpected BSSMAP ", bssap);
Daniel Willmannafce8662018-07-06 23:11:32 +02005539 mtc.stop;
Harald Welte898113b2018-01-31 18:32:21 +01005540 }
5541 [] T.timeout {
5542 setverdict(pass);
5543 }
5544 }
5545}
5546
Harald Weltee3bd6582018-01-31 22:51:25 +01005547/* unsolicited ASSIGNMENT FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5548private function f_tc_unsol_ass_fail(charstring id) runs on MSC_ConnHdlr {
5549 f_est_single_l3(ts_RRM_AssignmentFailure('00'O));
5550 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005551 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005552}
Harald Welte898113b2018-01-31 18:32:21 +01005553testcase TC_unsol_ass_fail() runs on test_CT {
5554 var MSC_ConnHdlr vc_conn;
5555 f_init(1, true);
5556 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005557 vc_conn := f_start_handler(refers(f_tc_unsol_ass_fail));
Harald Welte898113b2018-01-31 18:32:21 +01005558 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005559 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005560}
Harald Welte552620d2017-12-16 23:21:36 +01005561
Harald Welteea99a002018-01-31 20:46:43 +01005562
5563/* unsolicited ASSIGNMENT COMPLETE (without ASSIGN) from MS shouldn't bring BSC down */
5564private function f_tc_unsol_ass_compl(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005565 f_est_single_l3(ts_RRM_AssignmentComplete('00'O));
5566 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005567 f_perform_clear();
Harald Welteea99a002018-01-31 20:46:43 +01005568}
5569testcase TC_unsol_ass_compl() runs on test_CT {
5570 var MSC_ConnHdlr vc_conn;
5571 f_init(1, true);
5572 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005573 vc_conn := f_start_handler(refers(f_tc_unsol_ass_compl));
Harald Welteea99a002018-01-31 20:46:43 +01005574 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005575 f_shutdown_helper();
Harald Welteea99a002018-01-31 20:46:43 +01005576}
5577
5578
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005579/* unsolicited HANDOVER FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5580private function f_tc_unsol_ho_fail(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005581 f_est_single_l3(ts_RRM_HandoverFailure('00'O));
5582 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005583 f_perform_clear();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005584}
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005585testcase TC_unsol_ho_fail() runs on test_CT {
5586 var MSC_ConnHdlr vc_conn;
5587 f_init(1, true);
5588 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005589 vc_conn := f_start_handler(refers(f_tc_unsol_ho_fail));
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005590 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005591 f_shutdown_helper();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005592}
5593
5594
Harald Weltee3bd6582018-01-31 22:51:25 +01005595/* short message from MS should be ignored */
5596private function f_tc_err_82_short_msg(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005597 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005598 f_create_chan_and_exp();
Harald Weltee3bd6582018-01-31 22:51:25 +01005599 /* we should now have a COMPL_L3 at the MSC */
Harald Weltee3bd6582018-01-31 22:51:25 +01005600
5601 /* send short message */
5602 RSL.send(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), ''O));
5603 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005604 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005605}
5606testcase TC_err_82_short_msg() runs on test_CT {
5607 var MSC_ConnHdlr vc_conn;
5608 f_init(1, true);
5609 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005610 vc_conn := f_start_handler(refers(f_tc_err_82_short_msg));
Harald Weltee3bd6582018-01-31 22:51:25 +01005611 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005612 f_shutdown_helper();
Harald Weltee3bd6582018-01-31 22:51:25 +01005613}
5614
5615
Harald Weltee9e02e42018-01-31 23:36:25 +01005616/* 24.008 8.4 Unknown message must trigger RR STATUS */
5617private function f_tc_err_84_unknown_msg(charstring id) runs on MSC_ConnHdlr {
5618 f_est_single_l3(ts_RRM_UL_REL('00'O));
5619 timer T := 3.0
5620 alt {
5621 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_STATUS)) {
5622 setverdict(pass);
5623 }
5624 [] BSSAP.receive { setverdict(fail, "unexpected BSSAP"); }
Harald Welte458fd372018-03-21 11:26:23 +01005625 [] T.timeout { setverdict(fail, "Timeout waiting for RR STATUS"); }
Harald Weltee9e02e42018-01-31 23:36:25 +01005626 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005627 f_perform_clear();
Harald Weltee9e02e42018-01-31 23:36:25 +01005628}
5629testcase TC_err_84_unknown_msg() runs on test_CT {
5630 var MSC_ConnHdlr vc_conn;
5631 f_init(1, true);
5632 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005633 vc_conn := f_start_handler(refers(f_tc_err_84_unknown_msg));
Harald Weltee9e02e42018-01-31 23:36:25 +01005634 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005635 f_shutdown_helper();
Harald Weltee9e02e42018-01-31 23:36:25 +01005636}
5637
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005638/***********************************************************************
5639 * Handover
5640 ***********************************************************************/
5641
Harald Welte94e0c342018-04-07 11:33:23 +02005642/* execute a "bts <0-255> trx <0-255> timeslot <0-7> " command on given Dchan */
5643private function f_vty_ts_action(charstring suffix, integer bts_nr, integer trx_nr, integer ts_nr)
5644runs on test_CT {
5645 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5646 " timeslot "&int2str(ts_nr)&" ";
5647 f_vty_transceive(BSCVTY, cmd & suffix);
5648}
5649
Harald Welte261af4b2018-02-12 21:20:39 +01005650/* 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 +07005651private function f_vty_ss_action(TELNETasp_PT pt, charstring suffix,
5652 uint8_t bts_nr, uint8_t trx_nr,
5653 in RslChannelNr chan_nr)
5654{
Harald Welte261af4b2018-02-12 21:20:39 +01005655 /* FIXME: resolve those from component-global state */
5656 var integer ts_nr := chan_nr.tn;
5657 var integer ss_nr;
5658 if (ischosen(chan_nr.u.ch0)) {
5659 ss_nr := 0;
5660 } else if (ischosen(chan_nr.u.lm)) {
5661 ss_nr := chan_nr.u.lm.sub_chan;
5662 } else if (ischosen(chan_nr.u.sdcch4)) {
5663 ss_nr := chan_nr.u.sdcch4.sub_chan;
5664 } else if (ischosen(chan_nr.u.sdcch8)) {
5665 ss_nr := chan_nr.u.sdcch8.sub_chan;
5666 } else {
5667 setverdict(fail, "Invalid ChanNr ", chan_nr);
Daniel Willmannafce8662018-07-06 23:11:32 +02005668 mtc.stop;
Harald Welte261af4b2018-02-12 21:20:39 +01005669 }
5670
5671 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5672 " timeslot "&int2str(ts_nr)&" sub-slot "&int2str(ss_nr)&" ";
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005673 f_vty_transceive(pt, cmd & suffix);
Harald Welte261af4b2018-02-12 21:20:39 +01005674}
5675
Neels Hofmeyr91401012019-07-11 00:42:35 +02005676/* Even though the VTY command to trigger handover takes a new BTS number as argument, behind the scenes osmo-bsc always
5677 * translates that to a target ARFCN+BSIC first. See bsc_vty.c trigger_ho_or_as(), which puts the selected BTS' neighbor
5678 * ident key (ARFCN + BSIC) in the struct passed on to handover_request(). handover_start() then resolves that to a
5679 * viable actual neighbor cell. So from the internal osmo-bsc perspective, we always request handover to an ARFCN + BSIC
5680 * pair, not really to a specific BTS number. */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005681private function f_vty_handover(TELNETasp_PT pt, uint8_t bts_nr, uint8_t trx_nr,
5682 in RslChannelNr chan_nr, uint8_t new_bts_nr)
5683{
5684 f_vty_ss_action(pt, "handover " & int2str(new_bts_nr), bts_nr, trx_nr, chan_nr);
Harald Welte261af4b2018-02-12 21:20:39 +01005685}
5686
5687/* intra-BSC hand-over between BTS0 and BTS1 */
5688private function f_tc_ho_int(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02005689 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5690 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte261af4b2018-02-12 21:20:39 +01005691
5692 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5693 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5694
Harald Weltea0630032018-03-20 21:09:55 +01005695 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr666f0432020-07-04 00:53:07 +02005696 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Harald Welte261af4b2018-02-12 21:20:39 +01005697
5698 var HandoverState hs := {
5699 rr_ho_cmpl_seen := false,
5700 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005701 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005702 expect_target_tsc := c_BtsParams[1].tsc
Harald Welte261af4b2018-02-12 21:20:39 +01005703 };
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005704 /* issue hand-over command on VTY, from BTS 0 to BTS 1 */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005705 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
Harald Welte261af4b2018-02-12 21:20:39 +01005706 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5707 f_rslem_suspend(RSL1_PROC);
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005708
5709 /* From the MGW perspective, a handover is is characterized by
5710 * performing one MDCX operation with the MGW. So we expect to see
5711 * one more MDCX during handover. */
5712 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5713
Harald Welte261af4b2018-02-12 21:20:39 +01005714 alt {
5715 [] as_handover(hs);
Harald Welte261af4b2018-02-12 21:20:39 +01005716 }
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005717
Philipp Maier4dae0652018-11-12 12:03:26 +01005718 /* Since this is an internal handover we expect the BSC to inform the
5719 * MSC about the event */
5720 BSSAP.receive(tr_BSSMAP_HandoverPerformed);
5721
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005722 /* Check the amount of MGCP transactions is still consistant with the
5723 * test expectation */
5724 f_check_mgcp_expectations()
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005725
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005726 var RSL_Message chan_act := f_rslem_get_last_act(RSL1_PROC, 0, g_chan_nr);
5727
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005728 /* Ensure the Channel Activation for the new channel contained the right encryption params. as_handover() set
5729 * 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 +02005730 f_verify_encr_info(chan_act);
5731
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005732 f_chan_act_verify_tsc(chan_act, c_BtsParams[1].tsc);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005733
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005734 f_perform_clear(RSL1, RSL1_PROC);
5735
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01005736 f_sleep(0.5);
Harald Welte261af4b2018-02-12 21:20:39 +01005737}
5738
5739testcase TC_ho_int() runs on test_CT {
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005740 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte261af4b2018-02-12 21:20:39 +01005741 var MSC_ConnHdlr vc_conn;
5742 f_init(2, true);
5743 f_sleep(1.0);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005744
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005745 pars.expect_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005746
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005747 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005748
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005749 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
Harald Welte261af4b2018-02-12 21:20:39 +01005750 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005751
5752 /* from f_establish_fully() */
5753 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5754 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5755 /* from handover */
5756 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5757 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5758 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5759 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005760 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5761 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005762 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02005763 f_shutdown_helper(ho := true);
Harald Welte261af4b2018-02-12 21:20:39 +01005764}
Harald Weltee9e02e42018-01-31 23:36:25 +01005765
Oliver Smith7eabd312021-07-12 14:18:56 +02005766function 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 +02005767 var MSC_ConnHdlr vc_conn;
5768 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5769 pars.encr := valueof(t_EncrParams(encr_alg, f_rnd_octstring(8), f_rnd_octstring(16)));
5770
5771 f_init(2, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02005772 f_vty_encryption_a5(enc_a5);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005773 f_sleep(1.0);
5774
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005775 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005776
5777 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
5778 vc_conn.done;
5779
5780 /* from f_establish_fully() */
5781 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5782 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5783 /* from handover */
5784 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5785 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5786 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5787 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005788 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5789 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005790 f_ctrs_bsc_and_bts_verify();
Oliver Smith7eabd312021-07-12 14:18:56 +02005791 f_vty_encryption_a5_reset();
Oliver Smith39f53072022-10-27 14:44:04 +02005792 f_shutdown_helper(ho := true);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005793}
5794
5795testcase TC_ho_int_a5_0() runs on test_CT {
5796 f_tc_ho_int_a5('01'O);
5797}
5798
5799testcase TC_ho_int_a5_1() runs on test_CT {
5800 f_tc_ho_int_a5('02'O);
5801}
5802
5803testcase TC_ho_int_a5_3() runs on test_CT {
5804 f_tc_ho_int_a5('08'O);
5805}
5806
5807testcase TC_ho_int_a5_4() runs on test_CT {
Oliver Smith7eabd312021-07-12 14:18:56 +02005808 f_tc_ho_int_a5('10'O, "0 1 3 4");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005809}
5810
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005811/* intra-BSC hand-over with CONNection FAILure and cause Radio Link Failure: check RR release cause */
5812private function f_tc_ho_int_radio_link_failure(charstring id) runs on MSC_ConnHdlr {
5813 g_pars := f_gen_test_hdlr_pars();
5814 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5815 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005816
5817 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5818 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5819
5820 f_establish_fully(ass_cmd, exp_compl);
5821 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
5822
5823 var HandoverState hs := {
5824 rr_ho_cmpl_seen := false,
5825 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005826 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005827 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005828 };
5829 /* issue hand-over command on VTY */
5830 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
5831 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5832 f_rslem_suspend(RSL1_PROC);
5833
5834 /* From the MGW perspective, a handover is is characterized by
5835 * performing one MDCX operation with the MGW. So we expect to see
5836 * one more MDCX during handover. */
5837 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5838
5839 var RSL_Message rsl;
5840 var PDU_ML3_NW_MS l3;
5841 var RslChannelNr new_chan_nr;
5842 var GsmArfcn arfcn;
5843 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
5844 l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
5845 if (not ischosen(l3.msgs.rrm.handoverCommand)) {
5846 setverdict(fail, "Expected handoverCommand");
5847 mtc.stop;
5848 }
5849 }
5850 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
5851 new_chan_nr, arfcn);
5852
5853 f_rslem_register(0, new_chan_nr, RSL1_PROC);
5854
5855 /* resume processing of RSL DChan messages, which was temporarily suspended
5856 * before performing a hand-over */
5857 f_rslem_resume(RSL1_PROC);
5858 RSL1.receive(tr_RSL_IPA_CRCX(new_chan_nr));
5859
5860 f_sleep(1.0);
5861
5862 /* Handover fails because no HANDO DET appears on the new lchan,
5863 * and the old lchan reports a Radio Link Failure. */
5864 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
5865
5866 var PDU_BSSAP rx_clear_request;
5867 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
5868 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
5869 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5870
5871 var RR_Cause rr_cause := GSM48_RR_CAUSE_ABNORMAL_UNSPEC;
5872
5873 var MgcpCommand mgcp;
5874 interleave {
5875 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE(int2oct(enum2int(rr_cause), 1)))) {}
5876 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005877 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005878 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005879 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005880 }
5881 [] RSL1.receive(tr_RSL_DEACT_SACCH(new_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005882 [] RSL1.receive(tr_RSL_RF_CHAN_REL(new_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005883 RSL1.send(ts_RSL_RF_CHAN_REL_ACK(new_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005884 f_rslem_unregister(0, g_chan_nr, PT := RSL1_PROC);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005885 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005886 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
5887 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
5888 }
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005889 }
5890
5891 f_sleep(0.5);
5892 setverdict(pass);
5893}
5894testcase TC_ho_int_radio_link_failure() runs on test_CT {
5895 var MSC_ConnHdlr vc_conn;
5896 f_init(2, true);
5897 f_sleep(1.0);
5898
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005899 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005900
5901 vc_conn := f_start_handler(refers(f_tc_ho_int_radio_link_failure));
5902 vc_conn.done;
5903
5904 /* from f_establish_fully() */
5905 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5906 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5907 /* from handover */
5908 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5909 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
5910 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5911 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:stopped");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005912 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5913 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:stopped");
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005914 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02005915 f_shutdown_helper(ho := true);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005916}
5917
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005918/* Expecting MGCP to DLCX the endpoint's two connections: towards BTS and towards MSC */
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005919private function f_expect_dlcx_conns() runs on MSC_ConnHdlr {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005920 var MgcpCommand mgcp;
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005921 var template MgcpResponse mgcp_resp;
5922 var MGCP_RecvFrom mrf;
5923 var template MgcpMessage msg_resp;
5924 var template MgcpMessage msg_dlcx := {
5925 command := tr_DLCX()
5926 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005927
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005928 if (g_pars.aoip) {
5929 MGCP.receive(tr_DLCX()) -> value mgcp {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005930 log("Got first DLCX: ", mgcp);
5931 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005932 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005933
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005934 MGCP.receive(tr_DLCX()) -> value mgcp {
5935 log("Got second DLCX: ", mgcp);
5936 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
5937 };
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005938 } else {
5939 /* For SCCPLite, BSC doesn't handle the MSC-side */
5940 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
5941 log("Got first DLCX: ", mrf.msg.command);
5942 msg_resp := {
5943 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
5944 }
5945 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, msg_resp));
5946 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005947 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005948}
5949
Oliver Smithc9a5f532022-10-21 11:32:23 +02005950private function f_ho_out_of_this_bsc(template (omit) BSSMAP_oldToNewBSSIEs exp_oldToNewBSSIEs := omit,
5951 boolean skip_meas_rep := false) runs on MSC_ConnHdlr {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005952
Oliver Smithc9a5f532022-10-21 11:32:23 +02005953 if (not skip_meas_rep) {
5954 var NcellReports neighbor_rep := {
5955 { rxlev := 20, bcch_freq := 0, bsic := 11 }
5956 };
5957 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
5958 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
5959 l3_mr, 0));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005960
Oliver Smithc9a5f532022-10-21 11:32:23 +02005961 BSSAP.receive(tr_BSSMAP_HandoverRequired(exp_oldToNewBSSIEs));
5962 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005963
5964 f_sleep(0.5);
5965 /* The MSC negotiates Handover Request and Handover Request Ack with
5966 * the other BSS and comes back with a BSSMAP Handover Command
5967 * containing an RR Handover Command coming from the target BSS... */
5968
5969 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
5970 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
5971 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
5972 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
5973 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
5974
5975 /* expect the Handover Command to go out on RR */
5976 var RSL_Message rsl_ho_cmd
5977 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
5978 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
5979 var RSL_IE_Body rsl_ho_cmd_l3;
5980 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
5981 log("RSL message contains no L3 Info IE, expected RR Handover Command");
5982 setverdict(fail);
5983 } else {
5984 log("Found L3 Info: ", rsl_ho_cmd_l3);
5985 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
5986 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
5987 setverdict(fail);
5988 } else {
5989 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
5990 setverdict(pass);
5991 }
5992 }
5993
5994 /* When the other BSS has reported a completed handover, this side is
5995 * torn down. */
5996
5997 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_HANDOVER_SUCCESSFUL;
5998 var BssmapCause cause := enum2int(cause_val);
5999 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6000
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006001 f_expect_dlcx_conns();
Pau Espin Pedrol06199952021-06-15 11:30:00 +02006002
6003 interleave {
6004 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE));
6005 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr));
6006 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006007 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
6008 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
6009 }
Pau Espin Pedrol06199952021-06-15 11:30:00 +02006010 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006011 setverdict(pass);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006012}
6013
6014private function f_tc_ho_out_of_this_bsc(charstring id) runs on MSC_ConnHdlr {
6015 g_pars := f_gen_test_hdlr_pars();
6016 var PDU_BSSAP ass_req := f_gen_ass_req();
6017 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6018 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6019 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6020 f_establish_fully(ass_req, exp_compl);
6021
6022 f_ho_out_of_this_bsc();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006023}
6024testcase TC_ho_out_of_this_bsc() runs on test_CT {
6025 var MSC_ConnHdlr vc_conn;
6026
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01006027 f_init_vty();
6028 f_bts_0_cfg(BSCVTY,
6029 {"neighbor-list mode automatic",
6030 "handover 1",
6031 "handover algorithm 2",
6032 "handover2 window rxlev averaging 1",
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006033 "no neighbors",
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01006034 "neighbor lac 99 arfcn 123 bsic any"});
6035 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6036
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006037 f_init(1, true);
6038 f_sleep(1.0);
6039
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006040 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006041
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006042 vc_conn := f_start_handler(refers(f_tc_ho_out_of_this_bsc));
6043 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006044
6045 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6046 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6047 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6048 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6049 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6050 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
6051 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006052 f_shutdown_helper(ho := true);
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006053}
6054
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006055private function f_mo_l3_transceive(RSL_DCHAN_PT rsl := RSL,
6056 template (value) RslLinkId link_id := ts_RslLinkID_DCCH(0),
Vadim Yanitskiy2ef6a2f2020-10-08 23:17:32 +07006057 template (present) OCT1 dlci := ?,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07006058 octetstring l3 := '0123456789'O)
6059runs on MSC_ConnHdlr {
Neels Hofmeyr43654812020-09-25 01:35:35 +02006060 /* The old lchan and conn should still be active. See that arbitrary L3
6061 * is still going through. */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006062 rsl.send(ts_RSL_DATA_IND(g_chan_nr, link_id, l3));
Neels Hofmeyr43654812020-09-25 01:35:35 +02006063 var template PDU_BSSAP exp_data := {
6064 discriminator := '1'B,
6065 spare := '0000000'B,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07006066 dlci := dlci,
6067 lengthIndicator := lengthof(l3),
Neels Hofmeyr43654812020-09-25 01:35:35 +02006068 pdu := {
6069 dtap := l3
6070 }
6071 };
6072 BSSAP.receive(exp_data);
6073 setverdict(pass);
6074}
6075
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006076private function f_mt_l3_transceive(RSL_DCHAN_PT rsl := RSL,
6077 template (present) RslLinkId link_id := tr_RslLinkID_DCCH(0),
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07006078 template (value) OCT1 dlci := '00'O,
6079 octetstring l3 := '0123456789'O)
6080runs on MSC_ConnHdlr {
6081 BSSAP.send(PDU_BSSAP:{
6082 discriminator := '1'B,
6083 spare := '0000000'B,
6084 dlci := dlci,
6085 lengthIndicator := lengthof(l3),
6086 pdu := {
6087 dtap := l3
6088 }
6089 });
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006090 rsl.receive(tr_RSL_DATA_REQ(g_chan_nr, link_id, l3));
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07006091 setverdict(pass);
6092}
6093
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006094/* BSC asks for inter-BSC HO, but the MSC decides that it won't happen and
6095 * simply never sends a BSSMAP Handover Command. */
6096private function f_tc_ho_out_fail_no_msc_response(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006097 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006098
6099 var PDU_BSSAP ass_req := f_gen_ass_req();
6100 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6101 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6102 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6103 f_establish_fully(ass_req, exp_compl);
6104
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006105 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006106 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6107
6108 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6109
6110 /* osmo-bsc should time out 10 seconds after the handover started.
6111 * Let's give it a bit extra. */
6112 f_sleep(15.0);
6113
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006114 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006115 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006116 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006117}
6118testcase TC_ho_out_fail_no_msc_response() runs on test_CT {
6119 var MSC_ConnHdlr vc_conn;
6120
6121 f_init(1, true);
6122 f_sleep(1.0);
6123
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006124 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006125
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006126 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_msc_response));
6127 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006128
6129 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6130 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6131 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6132 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6133 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6134 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6135 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006136 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006137}
6138
6139/* BSC asks for inter-BSC HO, receives BSSMAP Handover Command, but MS reports
6140 * RR Handover Failure. */
6141private function f_tc_ho_out_fail_rr_ho_failure(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006142 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006143
6144 var PDU_BSSAP ass_req := f_gen_ass_req();
6145 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6146 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6147 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6148 f_establish_fully(ass_req, exp_compl);
6149
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006150 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006151 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6152
6153 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6154
6155 f_sleep(0.5);
6156 /* The MSC negotiates Handover Request and Handover Request Ack with
6157 * the other BSS and comes back with a BSSMAP Handover Command
6158 * containing an RR Handover Command coming from the target BSS... */
6159
6160 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6161 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6162 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6163 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6164 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6165
6166 /* expect the Handover Command to go out on RR */
6167 var RSL_Message rsl_ho_cmd
6168 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6169 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6170 var RSL_IE_Body rsl_ho_cmd_l3;
6171 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6172 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6173 setverdict(fail);
6174 } else {
6175 log("Found L3 Info: ", rsl_ho_cmd_l3);
6176 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6177 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6178 setverdict(fail);
6179 } else {
6180 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6181 setverdict(pass);
6182 }
6183 }
6184
6185 f_sleep(0.2);
6186 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
6187
6188 /* Should tell the MSC about the failure */
6189 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6190
6191 f_sleep(1.0);
6192
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006193 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006194 f_sleep(1.0);
6195
6196 setverdict(pass);
6197 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006198 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006199}
6200testcase TC_ho_out_fail_rr_ho_failure() runs on test_CT {
6201 var MSC_ConnHdlr vc_conn;
6202
6203 f_init(1, true);
6204 f_sleep(1.0);
6205
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006206 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006207
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006208 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_rr_ho_failure));
6209 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006210
6211 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6212 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6213 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6214 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6215 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6216 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:failed");
6217 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006218 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006219}
6220
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006221/* BSC asks for inter-BSC-out HO, receives BSSMAP Handover Command, but then no reply is received about HO outcome
6222 * (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 +02006223 * and the lchan is released. */
6224private function f_tc_ho_out_fail_no_result_after_ho_cmd(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006225 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006226
6227 var PDU_BSSAP ass_req := f_gen_ass_req();
6228 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6229 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6230 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6231 f_establish_fully(ass_req, exp_compl);
6232
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006233 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006234 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6235
6236 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6237
6238 f_sleep(0.5);
6239 /* The MSC negotiates Handover Request and Handover Request Ack with
6240 * the other BSS and comes back with a BSSMAP Handover Command
6241 * containing an RR Handover Command coming from the target BSS... */
6242
6243 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6244 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6245 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6246 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6247 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6248
6249 /* expect the Handover Command to go out on RR */
6250 var RSL_Message rsl_ho_cmd
6251 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6252 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6253 var RSL_IE_Body rsl_ho_cmd_l3;
6254 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6255 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6256 setverdict(fail);
6257 } else {
6258 log("Found L3 Info: ", rsl_ho_cmd_l3);
6259 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6260 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6261 setverdict(fail);
6262 } else {
6263 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6264 setverdict(pass);
6265 }
6266 }
6267
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006268 /* We get neither success nor failure report from the remote BSS. Eventually T8 times out and we run into 3GPP
6269 * TS 48.008 3.1.5.3.3 "Abnormal Conditions": Clear Request should go to the MSC, and RR should be released
6270 * after Clear Command */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006271
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006272 var PDU_BSSAP rx_clear_request;
Neels Hofmeyre1797aa2019-07-09 19:34:04 +02006273 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
6274 log("Got BSSMAP Clear Request");
6275 /* Instruct BSC to clear channel */
6276 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
6277 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6278
6279 var MgcpCommand mgcp;
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006280 interleave {
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01006281 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
6282 log("Got Deact SACCH");
6283 }
Harald Welte924b6ea2019-02-04 01:05:34 +01006284 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
Neels Hofmeyr211169d2018-11-07 00:37:29 +01006285 log("Got RR Release");
6286 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02006287 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006288 log("Got RF Chan Rel");
6289 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02006290 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006291 }
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006292 }
6293
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006294 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006295 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006296 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006297
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006298 setverdict(pass);
6299 f_sleep(1.0);
6300}
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006301testcase TC_ho_out_fail_no_result_after_ho_cmd() runs on test_CT {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006302 var MSC_ConnHdlr vc_conn;
6303
6304 f_init(1, true);
6305 f_sleep(1.0);
6306
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006307 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006308
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006309 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_result_after_ho_cmd));
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006310 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006311
6312 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6313 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6314 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6315 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6316 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6317 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6318 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006319 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006320}
6321
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006322private 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 +01006323 var PDU_BSSAP rx_bssap;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006324 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6325 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6326 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6327 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6328 * before we get started. */
6329 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6330 f_rslem_register(0, new_chan_nr);
6331 g_chan_nr := new_chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06006332 var uint3_t expect_target_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006333 f_sleep(1.0);
6334
6335 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6336 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006337 var default as_media := activate(as_Media());
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006338
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01006339 var PDU_BSSAP ho_req := f_gen_handover_req(aoip_tla := g_pars.host_aoip_tla,
6340 cell_id_source := g_pars.cell_id_source,
6341 oldToNewBSSIEs := oldToNewBSSIEs,
6342 enc := g_pars.encr);
6343 if (g_pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr) {
6344 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, ho_req));
6345 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6346 } else {
6347 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, omit));
6348 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6349 BSSAP.send(ho_req);
6350 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006351
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006352 alt {
6353 [] BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap {
6354 if (g_pars.expect_ho_fail) {
6355 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6356 "Expected Handover Request to fail, but got Handover Request Ack")
6357 }
6358 }
6359 [] BSSAP.receive(tr_BSSMAP_HandoverFailure) -> value rx_bssap {
6360 if (not g_pars.expect_ho_fail) {
6361 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6362 "Expected Handover Request to succeed, but got Handover Failure")
6363 }
6364 // TODO: evaluate correct cause value. But osmo-bsc doesn't seem to send meaningful causes yet!
6365 // For now just accept any cause.
6366 BSSAP.receive(tr_BSSMAP_ClearRequest);
6367 setverdict(pass);
6368 return;
6369 }
6370 }
6371
Oliver Smith7a8594a2023-02-13 14:30:49 +01006372 if (g_pars.expect_ho_fail_lchan_est) {
6373 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6374 setverdict(pass);
Oliver Smitha1cbec52023-02-21 12:44:12 +01006375
6376 /* When we let MGCP MDCX run into a timeout, it's still in the
6377 * queue and additionally after BSSAP HandoverFailure, two DLCX
Oliver Smith30eb8822023-03-06 12:31:53 +01006378 * get sent (for AoIP, for SCCPlite one DLCX). */
Oliver Smitha1cbec52023-02-21 12:44:12 +01006379 if (g_pars.ignore_mgw_mdcx) {
Oliver Smith30eb8822023-03-06 12:31:53 +01006380 if (g_pars.aoip) {
6381 MGCP.receive(tr_MDCX);
6382 MGCP.receive(tr_DLCX);
6383 MGCP.receive(tr_DLCX);
6384 } else {
6385 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any({command := tr_MDCX}));
6386 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any({command := tr_DLCX}));
6387 }
Oliver Smitha1cbec52023-02-21 12:44:12 +01006388 }
Oliver Smith7a8594a2023-02-13 14:30:49 +01006389 return;
6390 }
6391
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006392 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6393
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006394 /* we're sure that the channel activation is done now, verify the parameters in it */
6395 var RSL_Message chan_act := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
6396 f_verify_encr_info(chan_act);
6397 f_chan_act_verify_tsc(chan_act, expect_target_tsc);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006398
Neels Hofmeyr46e16e52022-02-23 17:04:00 +01006399 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.codecList)) {
6400 if (not g_pars.aoip) {
6401 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6402 "handoverRequestAck: Expected no Speech Codec List (BSS Supported), because this is not AoIP");
6403 }
6404 /* TODO: check actual codecs? */
6405 } else {
6406 if (g_pars.aoip) {
6407 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6408 "handoverRequestAck: Expected Speech Codec List (BSS Supported), but none found");
6409 }
6410 }
6411
6412 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.speechCodec)) {
6413 if (not g_pars.aoip) {
6414 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6415 "handoverRequestAck: Expected no Speech Codec (Chosen), because this is not AoIP");
6416 }
6417 /* TODO: check actual codec? */
6418 } else {
6419 if (g_pars.aoip) {
6420 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6421 "handoverRequestAck: Expected Speech Codec (Chosen), but none found");
6422 }
6423 }
6424
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006425 var octetstring ho_command_str;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006426 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6427 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6428 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6429 log("L3 Info in HO Request Ack is ", ho_command);
6430
6431 var GsmArfcn arfcn;
6432 var RslChannelNr actual_new_chan_nr;
6433 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6434 actual_new_chan_nr, arfcn);
6435
6436 if (actual_new_chan_nr != new_chan_nr) {
6437 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6438 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6439 setverdict(fail);
6440 return;
6441 }
6442 log("Handover Command chan_nr is", actual_new_chan_nr);
6443
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006444 var uint3_t got_tsc := rr_chan_desc_tsc(ho_command.msgs.rrm.handoverCommand.channelDescription2);
6445 if (not match(got_tsc, expect_target_tsc)) {
6446 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
6447 expect_target_tsc, " got ", got_tsc);
6448 mtc.stop;
6449 } else {
6450 log("handoverCommand: verified TSC = ", got_tsc);
6451 }
6452
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006453 /* Check the Cipher Mode Setting IE (shall be present during inter-RAT handover) */
6454 if (ispresent(ho_command.msgs.rrm.handoverCommand.cipherModeSetting)) {
6455 var CipherModeSetting_TV cms := ho_command.msgs.rrm.handoverCommand.cipherModeSetting;
6456 var template (present) CipherModeSetting_TV tr_cms := {
6457 sC := '0'B, /* no ciphering by default */
6458 algorithmIdentifier := '000'B,
6459 elementIdentifier := ?
6460 };
6461 if (ispresent(g_pars.encr) and g_pars.encr.enc_alg_expect != '01'O) { /* A5/N */
6462 tr_cms.algorithmIdentifier := f_cipher_mode_bssmap_to_rr(g_pars.encr.enc_alg_expect);
6463 tr_cms.sC := '1'B;
6464 }
6465 if (not match(cms, tr_cms)) {
6466 setverdict(fail, "RR Handover Command: unexpected Cipher Mode Setting IE: ",
6467 cms, ", expected: ", tr_cms);
6468 }
6469 } else {
6470 setverdict(fail, "RR Handover Command: Cipher Mode Setting IE is not present");
6471 }
6472
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006473 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6474 * tells the MS to handover to the new lchan. Here comes the new MS on
6475 * the new lchan with a Handover RACH: */
6476
6477 /* send handover detect */
6478
6479 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6480
6481 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6482
6483 /* send handover complete over the new channel */
6484
6485 var PDU_ML3_MS_NW l3_tx := valueof(ts_RRM_HandoverComplete('00'O));
6486 RSL.send(ts_RSL_EST_IND(new_chan_nr, valueof(ts_RslLinkID_DCCH(0)),
6487 enc_PDU_ML3_MS_NW(l3_tx)));
6488
6489 BSSAP.receive(tr_BSSMAP_HandoverComplete);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006490 deactivate(as_media);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006491 setverdict(pass);
6492}
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006493
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006494private function f_tc_ho_into_this_bsc(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006495 var template PDU_ML3_NW_MS exp_rr_rel_tmpl;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006496 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit;
6497 if (not istemplatekind(g_pars.last_used_eutran_plmn, "omit")) {
6498 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006499 }
6500 if (g_pars.exp_fast_return) {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006501 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE_CellSelectInd;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006502 } else {
6503 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006504 }
6505 f_ho_into_this_bsc(id, oldToNewBSSIEs);
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006506 if (g_pars.expect_ho_fail) {
6507 f_perform_clear_no_lchan();
Oliver Smith7a8594a2023-02-13 14:30:49 +01006508 } else if (g_pars.expect_ho_fail_lchan_est) {
6509 BSSAP.receive(tr_BSSMAP_ClearRequest);
6510 f_perform_clear_no_lchan();
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006511 } else {
6512 f_perform_clear(exp_rr_rel_tmpl := exp_rr_rel_tmpl);
6513 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006514 setverdict(pass);
6515}
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006516function 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 +01006517 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006518
6519 f_init(1, true);
6520 f_sleep(1.0);
6521
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006522 f_vty_encryption_a5(vty_a5_cfg);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006523 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006524
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006525 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6526 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006527
6528 vc_conn := f_start_handler(refers(f_tc_ho_into_this_bsc), pars);
6529 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006530
6531 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006532 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006533 if (pars.expect_ho_fail) {
6534 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6535 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:failed");
Oliver Smith7a8594a2023-02-13 14:30:49 +01006536 } else if (pars.expect_ho_fail_lchan_est) {
6537 f_ctrs_bsc_and_bts_add(0, "handover:error");
6538 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006539 } else {
6540 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6541 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed");
6542 }
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006543 f_ctrs_bsc_and_bts_verify();
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006544
6545 f_vty_encryption_a5_reset();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006546}
6547
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006548testcase TC_ho_into_this_bsc() runs on test_CT {
6549 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6550 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02006551 f_shutdown_helper(ho := true);
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006552}
6553
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006554function f_tc_ho_into_this_bsc_a5(TestHdlrEncrParams encr, charstring vty_a5_cfg := VTY_A5_DEFAULT,
6555 boolean expect_fail := false) runs on test_CT {
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006556 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006557 pars.encr := encr;
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006558 pars.expect_ho_fail := expect_fail;
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006559 f_tc_ho_into_this_bsc_main(pars, vty_a5_cfg);
Oliver Smith39f53072022-10-27 14:44:04 +02006560 f_shutdown_helper(ho := true);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006561}
6562
6563testcase TC_ho_into_this_bsc_a5_0() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006564 f_tc_ho_into_this_bsc_a5(f_encr_params('01'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006565}
6566
6567testcase TC_ho_into_this_bsc_a5_1() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006568 f_tc_ho_into_this_bsc_a5(f_encr_params('02'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006569}
6570
6571testcase TC_ho_into_this_bsc_a5_3() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006572 f_tc_ho_into_this_bsc_a5(f_encr_params('08'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006573}
6574
6575testcase TC_ho_into_this_bsc_a5_4() runs on test_CT {
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006576 f_tc_ho_into_this_bsc_a5(f_encr_params('10'O, kc128 := true), "3 4");
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006577}
6578
Neels Hofmeyr1951be22022-02-16 16:21:07 +01006579/* Report: in inter-BSC incoming handover, when the MSC omits the Chosen Encryption Algorithm IE in the Handover Request
6580 * message, then osmo-bsc starts an unencrypted lchan even if A5/0 is not permitted.
6581 *
6582 * This test verifies that the Encryption Information is present in the Channel Activation when the Chosen Enc Alg is
6583 * omitted.
6584 *
6585 * Related: SYS#5839
6586 */
6587testcase TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() runs on test_CT {
6588 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O, alg_chosen := omit));
6589}
6590
6591testcase TC_ho_into_this_bsc_a5_1_3() runs on test_CT {
6592 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O));
6593}
6594
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006595/* Send a permitted algo mask that does not intersect with osmo-bsc.cfg */
6596testcase TC_ho_into_this_bsc_a5_mismatch() runs on test_CT {
6597 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '18'O, alg_expect := '10'O), "0 1",
6598 expect_fail := true); // 0x18 = A5/3 and A5/4
6599}
6600
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006601testcase TC_ho_into_this_bsc_tla_v6() runs on test_CT {
6602 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6603 pars.host_aoip_tla := "::6";
6604 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02006605 f_shutdown_helper(ho := true);
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006606}
6607
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006608/* Similar to TC_ho_into_this_bsc, but when in SRVCC, HO Req contains "Old BSS
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006609 to New BSS Information" IE with "Last Used E-UTRAN PLMN Id", which, when the
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006610 channel is later released (RR CHannel Release), should trigger inclusion of
6611 IE "Cell Selection Indicator after Release of all TCH and SDCCH" with E-UTRAN
6612 neighbors. */
6613testcase TC_srvcc_eutran_to_geran() runs on test_CT {
6614 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6615 pars.last_used_eutran_plmn := '323454'O;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006616 pars.exp_fast_return := true;
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006617 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006618
6619 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6620 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6621 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006622 f_shutdown_helper(ho := true);
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006623}
6624
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006625/* Same as TC_srvcc_eutran_to_geran, but enables ciphering on the target channel. */
6626testcase TC_srvcc_eutran_to_geran_a5_3() runs on test_CT {
6627 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6628 pars.encr := f_encr_params('08'O); /* only A5/3 */
6629 pars.last_used_eutran_plmn := '323454'O;
6630 pars.exp_fast_return := true;
6631 f_tc_ho_into_this_bsc_main(pars);
6632
6633 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6634 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6635 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006636 f_shutdown_helper(ho := true);
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006637}
6638
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006639/* Same as TC_srvcc_eutran_to_geran, but test explicitly forbiding fast return
6640 on the BTS. As a result, RR Release shouldn't contain the EUTRAN neighbor
6641 list when the channel is released. */
6642testcase TC_srvcc_eutran_to_geran_forbid_fast_return() runs on test_CT {
6643 f_init_vty();
6644 f_vty_allow_srvcc_fast_return(true, 0)
6645
6646 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6647 pars.last_used_eutran_plmn := '323454'O;
6648 pars.exp_fast_return := false;
6649 f_tc_ho_into_this_bsc_main(pars);
6650 f_vty_allow_srvcc_fast_return(false, 0);
6651 f_shutdown_helper();
6652}
6653
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01006654/* Same as TC_srvcc_eutran_to_geran, but using SAI as serving Cell Identifier. SYS#5838 */
6655testcase TC_srvcc_eutran_to_geran_src_sai() runs on test_CT {
6656 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6657 pars.last_used_eutran_plmn := '323454'O;
6658 pars.cell_id_source := valueof(ts_CellID_SAI('123456'O, 300, 444));
6659 f_tc_ho_into_this_bsc_main(pars);
6660
6661 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6662 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6663 f_ctrs_bsc_and_bts_verify();
6664 f_shutdown_helper();
6665}
6666
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006667private function f_tc_srvcc_eutran_to_geran_ho_out(charstring id) runs on MSC_ConnHdlr {
6668 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs;
6669 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
6670 f_ho_into_this_bsc(id, oldToNewBSSIEs);
6671 f_ho_out_of_this_bsc(oldToNewBSSIEs);
6672 setverdict(pass);
6673}
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006674
6675private function f_tc_srvcc_eutran_to_geran_ho_out_main(boolean disable_fast_return)
6676 runs on test_CT {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006677 var MSC_ConnHdlr vc_conn;
6678 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6679
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006680 f_init_vty();
6681 f_bts_0_cfg(BSCVTY,
6682 {"neighbor-list mode automatic",
6683 "handover 1",
6684 "handover algorithm 2",
6685 "handover2 window rxlev averaging 1",
6686 "no neighbors",
6687 "neighbor lac 99 arfcn 123 bsic any"});
6688 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6689
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006690 f_init(1, true);
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006691 if (disable_fast_return) {
6692 f_vty_allow_srvcc_fast_return(true, 0);
6693 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006694 f_sleep(1.0);
6695
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006696 f_ctrs_bsc_and_bts_handover_init();
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006697
6698 pars.last_used_eutran_plmn := '323454'O;
6699 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6700 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
6701
6702 vc_conn := f_start_handler(refers(f_tc_srvcc_eutran_to_geran_ho_out), pars);
6703 vc_conn.done;
6704
6705 f_ctrs_bsc_and_bts_add(0, "handover:attempted", 2);
6706 f_ctrs_bsc_and_bts_add(0, "handover:completed", 2);
6707 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted", 1);
6708 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed", 1);
6709 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted", 1);
6710 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed", 1);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006711
6712 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted", 1);
6713 f_ctrs_bsc_and_bts_add(0, "srvcc:completed", 1);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006714 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006715
6716 if (disable_fast_return) {
6717 f_vty_allow_srvcc_fast_return(false, 0);
6718 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006719 f_shutdown_helper();
6720}
6721
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006722/* First, HO into BSC from EUTRAN (SRVCC): HO Request contains "Old BSS to New
6723 BSS Information" IE with "Last Used E-UTRAN PLMN Id".
6724 Second, HO to another BSC: HO Required contains "Old BSS to New BSS Information"
6725 IE with "Last Used E-UTRAN PLMN Id" from first step. */
6726testcase TC_srvcc_eutran_to_geran_ho_out() runs on test_CT {
6727 f_tc_srvcc_eutran_to_geran_ho_out_main(false);
6728}
6729/* Validate subsequent intra-GSM-HO works the same (with OldBSSToNewBSSInfo IE)
6730 * independently of fast-reture allowed/forbidden in local BTS */
6731testcase TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() runs on test_CT {
6732 f_tc_srvcc_eutran_to_geran_ho_out_main(true);
6733}
6734
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006735private function f_tc_ho_in_fail_msc_clears(charstring id) runs on MSC_ConnHdlr {
6736 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6737 f_rslem_register(0, new_chan_nr);
6738 g_chan_nr := new_chan_nr;
6739 f_sleep(1.0);
6740
6741 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6742 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6743 activate(as_Media());
6744
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006745 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006746 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006747 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006748
6749 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6750
6751 var PDU_BSSAP rx_bssap;
6752 var octetstring ho_command_str;
6753
6754 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6755
6756 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6757 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6758 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6759 log("L3 Info in HO Request Ack is ", ho_command);
6760
6761 var GsmArfcn arfcn;
6762 var RslChannelNr actual_new_chan_nr;
6763 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6764 actual_new_chan_nr, arfcn);
6765
6766 if (actual_new_chan_nr != new_chan_nr) {
6767 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6768 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6769 setverdict(fail);
6770 return;
6771 }
6772 log("Handover Command chan_nr is", actual_new_chan_nr);
6773
Neels Hofmeyr61ca08d2019-05-06 23:52:22 +02006774 /* For deterministic test results, give some time for the MGW endpoint to be configured */
6775 f_sleep(1.0);
6776
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006777 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6778 * tells the MS to handover to the new lchan. In this case, the MS
6779 * reports a Handover Failure to the old BSS, which forwards a BSSMAP
6780 * Handover Failure to the MSC. The procedure according to 3GPP TS
6781 * 48.008 3.1.5.3.2 "Handover Failure" is then that the MSC sends a
6782 * BSSMAP Clear Command: */
6783
6784 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6785 var BssmapCause cause := enum2int(cause_val);
6786 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6787
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006788 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006789 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006790 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006791
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006792 setverdict(pass);
6793 f_sleep(1.0);
6794
6795 setverdict(pass);
6796}
6797testcase TC_ho_in_fail_msc_clears() runs on test_CT {
6798 var MSC_ConnHdlr vc_conn;
6799 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6800
6801 f_init(1, true);
6802 f_sleep(1.0);
6803
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006804 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006805
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006806 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6807 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006808
6809 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears), pars);
6810 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006811
6812 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6813 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6814 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6815 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6816 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006817 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006818}
6819
6820private function f_tc_ho_in_fail_msc_clears_after_ho_detect(charstring id) runs on MSC_ConnHdlr {
6821 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6822 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6823 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6824 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6825 * before we get started. */
6826 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6827 f_rslem_register(0, new_chan_nr);
6828 g_chan_nr := new_chan_nr;
6829 f_sleep(1.0);
6830
6831 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6832 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6833 activate(as_Media());
6834
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006835 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006836 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006837 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006838
6839 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6840
6841 var PDU_BSSAP rx_bssap;
6842 var octetstring ho_command_str;
6843
6844 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6845
6846 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6847 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6848 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6849 log("L3 Info in HO Request Ack is ", ho_command);
6850
6851 var GsmArfcn arfcn;
6852 var RslChannelNr actual_new_chan_nr;
6853 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6854 actual_new_chan_nr, arfcn);
6855
6856 if (actual_new_chan_nr != new_chan_nr) {
6857 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6858 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6859 setverdict(fail);
6860 return;
6861 }
6862 log("Handover Command chan_nr is", actual_new_chan_nr);
6863
6864 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6865 * tells the MS to handover to the new lchan. Here comes the new MS on
6866 * the new lchan with a Handover RACH: */
6867
6868 /* send handover detect */
6869
6870 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6871
6872 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6873
6874 /* The MSC chooses to clear the connection now, maybe we got the
6875 * Handover RACH on the new cell but the MS still signaled Handover
6876 * Failure to the old BSS? */
6877
6878 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6879 var BssmapCause cause := enum2int(cause_val);
6880 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6881
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006882 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006883 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006884 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006885
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006886 f_sleep(1.0);
6887}
6888testcase TC_ho_in_fail_msc_clears_after_ho_detect() runs on test_CT {
6889 var MSC_ConnHdlr vc_conn;
6890 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6891
6892 f_init(1, true);
6893 f_sleep(1.0);
6894
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006895 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006896
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006897 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6898 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006899
6900 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears_after_ho_detect), pars);
6901 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006902
6903 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6904 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6905 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6906 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6907 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006908 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006909}
6910
6911/* The new BSS's lchan times out before the MSC decides that handover failed. */
6912private function f_tc_ho_in_fail_no_detect(charstring id) runs on MSC_ConnHdlr {
6913 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6914 f_rslem_register(0, new_chan_nr);
6915 g_chan_nr := new_chan_nr;
6916 f_sleep(1.0);
6917
6918 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6919 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Oliver Smith735b47c2023-02-15 16:03:54 +01006920 activate(as_Media());
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006921
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006922 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006923 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006924 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006925
6926 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6927
6928 var PDU_BSSAP rx_bssap;
6929 var octetstring ho_command_str;
6930
6931 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6932
6933 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6934 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6935 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6936 log("L3 Info in HO Request Ack is ", ho_command);
6937
6938 var GsmArfcn arfcn;
6939 var RslChannelNr actual_new_chan_nr;
6940 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6941 actual_new_chan_nr, arfcn);
6942
6943 if (actual_new_chan_nr != new_chan_nr) {
6944 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6945 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6946 setverdict(fail);
6947 return;
6948 }
6949 log("Handover Command chan_nr is", actual_new_chan_nr);
6950
6951 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6952 * tells the MS to handover to the new lchan. But the MS never shows up
6953 * on the new lchan. */
6954
6955 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6956
6957 /* Did osmo-bsc also send a Clear Request? */
6958 timer T := 0.5;
6959 T.start;
6960 alt {
6961 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
6962 [] T.timeout { }
6963 }
6964
6965 /* MSC plays along with a Clear Command (no matter whether osmo-bsc
6966 * asked for it, this is a Handover Failure after all). */
6967
6968 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6969 var BssmapCause cause := enum2int(cause_val);
6970 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6971
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006972 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006973 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006974 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006975
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006976 f_sleep(1.0);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006977}
6978testcase TC_ho_in_fail_no_detect() runs on test_CT {
6979 var MSC_ConnHdlr vc_conn;
6980 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6981
Oliver Smithd49f46d2023-03-08 12:23:13 +01006982 pars.fail_on_dlcx := false;
6983
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006984 f_init(1, true);
6985 f_sleep(1.0);
6986
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006987 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006988
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006989 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6990 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006991
6992 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect), pars);
6993 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006994
6995 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6996 f_ctrs_bsc_and_bts_add(0, "handover:error");
6997 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6998 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
6999 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007000 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007001}
7002
7003/* Same as f_tc_ho_in_fail_no_detect, but MSC fails to send a Clear Command */
7004private function f_tc_ho_in_fail_no_detect2(charstring id) runs on MSC_ConnHdlr {
7005 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
7006 f_rslem_register(0, new_chan_nr);
7007 g_chan_nr := new_chan_nr;
7008 f_sleep(1.0);
7009
7010 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
7011 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Oliver Smith735b47c2023-02-15 16:03:54 +01007012 activate(as_Media());
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007013
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007014 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007015 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02007016 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007017
7018 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
7019
7020 var PDU_BSSAP rx_bssap;
7021 var octetstring ho_command_str;
7022
7023 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
7024
7025 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
7026 log("Received L3 Info in HO Request Ack: ", ho_command_str);
7027 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
7028 log("L3 Info in HO Request Ack is ", ho_command);
7029
7030 var GsmArfcn arfcn;
7031 var RslChannelNr actual_new_chan_nr;
7032 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
7033 actual_new_chan_nr, arfcn);
7034
7035 if (actual_new_chan_nr != new_chan_nr) {
7036 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
7037 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
7038 setverdict(fail);
7039 return;
7040 }
7041 log("Handover Command chan_nr is", actual_new_chan_nr);
7042
7043 /* Now the MSC forwards the RR Handover Command to the other BSC, which
7044 * tells the MS to handover to the new lchan. But the MS never shows up
7045 * on the new lchan. */
7046
7047 BSSAP.receive(tr_BSSMAP_HandoverFailure);
7048
7049 /* MSC plays dumb and sends no Clear Command */
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007050 var PDU_BSSAP rx_clear_request;
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02007051
7052 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request {
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007053 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
7054 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
7055 };
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02007056 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007057 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007058 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007059
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007060 f_sleep(1.0);
7061}
7062testcase TC_ho_in_fail_no_detect2() runs on test_CT {
7063 var MSC_ConnHdlr vc_conn;
7064 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7065
Oliver Smith735b47c2023-02-15 16:03:54 +01007066 pars.fail_on_dlcx := false;
7067
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007068 f_init(1, true);
7069 f_sleep(1.0);
7070
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007071 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007072
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007073 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
7074 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007075
7076 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect2), pars);
7077 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007078
7079 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7080 f_ctrs_bsc_and_bts_add(0, "handover:error");
7081 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
7082 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
7083 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007084 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007085}
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01007086
Oliver Smith7a8594a2023-02-13 14:30:49 +01007087testcase TC_ho_in_fail_mgw_mdcx_timeout() runs on test_CT {
7088 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7089
7090 pars.ignore_mgw_mdcx := true;
7091 pars.expect_ho_fail_lchan_est := true;
7092
7093 f_tc_ho_into_this_bsc_main(pars);
7094 f_shutdown_helper(ho := true);
7095}
7096
Oliver Smith4eed06f2023-02-15 15:43:19 +01007097testcase TC_ho_in_fail_ipa_crcx_timeout() runs on test_CT {
7098 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7099
7100 pars.ignore_ipa_media := true;
7101 pars.expect_ho_fail_lchan_est := true;
7102 pars.fail_on_dlcx := false;
7103
7104 f_tc_ho_into_this_bsc_main(pars);
7105 f_shutdown_helper(ho := true);
7106}
7107
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01007108/* An incoming inter-BSC HO can either issue the Handover Request message attached to the initial SCCP N-Connect (as in
7109 * the other tests we have so far), or the first CR can be "empty" with the BSSAP request following later. Test the
7110 * empty N-Connect case. */
7111testcase TC_ho_into_this_bsc_sccp_cr_without_bssap() runs on test_CT {
7112 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7113 pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr := false;
7114 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02007115 f_shutdown_helper(ho := true);
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01007116}
7117
Neels Hofmeyr91401012019-07-11 00:42:35 +02007118type record of charstring Commands;
7119
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007120private function f_bts_0_cfg(TELNETasp_PT pt, Commands cmds := {})
Neels Hofmeyr91401012019-07-11 00:42:35 +02007121{
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007122 f_vty_enter_cfg_bts(pt, 0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007123 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007124 f_vty_transceive(pt, cmds[i]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007125 }
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007126 f_vty_transceive(pt, "end");
Neels Hofmeyr91401012019-07-11 00:42:35 +02007127}
7128
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01007129private function f_cs7_inst_0_cfg(TELNETasp_PT pt, Commands cmds := {})
7130{
7131 f_vty_enter_cfg_cs7_inst(pt, 0);
7132 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
7133 f_vty_transceive(pt, cmds[i]);
7134 }
7135 f_vty_transceive(pt, "end");
7136}
7137
Neels Hofmeyr91401012019-07-11 00:42:35 +02007138private function f_probe_for_handover(charstring log_label,
7139 charstring log_descr,
7140 charstring handover_vty_cmd,
7141 boolean expect_handover,
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007142 boolean is_inter_bsc_handover := false,
7143 template uint3_t expect_target_tsc := ?)
Neels Hofmeyr91401012019-07-11 00:42:35 +02007144runs on MSC_ConnHdlr
7145{
Neels Hofmeyrb3fc8982020-05-11 00:16:42 +02007146 /* We're going to thwart any and all handover attempts, just be ready to handle (and ignore) handover target
7147 * lchans to be established on bts 1 or bts 2. */
7148 f_rslem_suspend(RSL1_PROC);
7149 f_rslem_suspend(RSL2_PROC);
7150
Neels Hofmeyr91401012019-07-11 00:42:35 +02007151 var RSL_Message rsl;
7152
7153 var charstring log_msg := " (expecting handover)"
7154 if (not expect_handover) {
7155 log_msg := " (expecting NO handover)";
7156 }
7157 log("f_probe_for_handover starting: " & log_label & ": " & log_descr & log_msg);
7158 f_vty_transceive(BSCVTY, handover_vty_cmd);
7159
Neels Hofmeyr91401012019-07-11 00:42:35 +02007160 timer T := 2.0;
7161 T.start;
7162
7163 alt {
7164 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
7165 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
7166 log("Rx L3 from net: ", l3);
7167 if (ischosen(l3.msgs.rrm.handoverCommand)) {
7168 var RslChannelNr new_chan_nr;
7169 var GsmArfcn arfcn;
7170 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
7171 new_chan_nr, arfcn);
7172 log("Handover to new chan ", new_chan_nr, " on ARFCN ", arfcn);
7173 log(l3.msgs.rrm.handoverCommand);
7174
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007175 /* Verify correct TSC in handoverCommand */
7176 var uint3_t got_tsc := rr_chan_desc_tsc(l3.msgs.rrm.handoverCommand.channelDescription2);
7177 if (not match(got_tsc, expect_target_tsc)) {
7178 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
7179 expect_target_tsc, " got ", got_tsc);
7180 mtc.stop;
7181 } else {
7182 log("handoverCommand: verified TSC = ", got_tsc, " (matches ",
7183 expect_target_tsc, ")");
7184 }
7185
Neels Hofmeyr91401012019-07-11 00:42:35 +02007186 /* Need to register for new lchan on new BTS -- it's either bts 1 or bts 2. It doesn't really
7187 * matter on which BTS it really is, we're not going to follow through an entire handover
7188 * anyway. */
7189 f_rslem_register(0, new_chan_nr, RSL1_PROC);
7190 f_rslem_resume(RSL1_PROC);
7191 f_rslem_register(0, new_chan_nr, RSL2_PROC);
7192 f_rslem_resume(RSL2_PROC);
7193
7194 if (expect_handover and not is_inter_bsc_handover) {
7195 setverdict(pass);
7196 log("f_probe_for_handover(" & log_label & "): Got RSL Handover Command as expected.");
7197 } else {
7198 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got RSL Handover Command. "
7199 & log_label & ": " & log_descr);
7200 }
7201
7202 log("f_probe_for_handover(" & log_label & "): Ending the test: Handover Failure stops the procedure.");
7203 /* osmo-bsc has triggered Handover. That's all we need to know for this test, reply with
7204 * Handover Failure. */
7205 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
7206
7207 /* target BTS is told to release lchan again; don't care which BTS nor what messages. */
7208 f_sleep(0.5);
7209 RSL1.clear;
7210 RSL2.clear;
7211 log("f_probe_for_handover(" & log_label & "): done (got RSL Handover Command)");
7212 break;
7213 } else {
7214 repeat;
7215 }
7216 }
7217 [] BSSAP.receive(tr_BSSMAP_HandoverRequired) {
7218 if (expect_handover and is_inter_bsc_handover) {
7219 setverdict(pass);
7220 log("f_probe_for_handover(" & log_label & "): Got BSSMAP Handover Required as expected.");
7221 } else {
7222 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got BSSMAP Handover Required. "
7223 & log_label & ": " & log_descr);
7224 }
7225
7226 log("f_probe_for_handover(" & log_label & "): done (got BSSMAP Handover Required)");
7227
7228 /* Note: f_tc_ho_neighbor_config_start() sets T7, the timeout for BSSMAP Handover Required, to
7229 * 1 second. There is no legal way to quickly abort a handover after a BSSMAP Handover Required,
7230 * setting a short timeout and waiting is the only way. */
7231 log("f_probe_for_handover(" & log_label & "): waiting for inter-BSC HO to time out...");
7232 f_sleep(1.5);
7233 log("f_probe_for_handover(" & log_label & "): ...done");
7234
7235 break;
7236 }
7237 [] T.timeout {
7238 if (expect_handover) {
7239 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected Handover, but got none. "
7240 & log_label & ": " & log_descr);
7241 } else {
7242 setverdict(pass);
7243 log("f_probe_for_handover(" & log_label & "): Got no Handover, as expected.");
7244 }
7245 log("f_probe_for_handover(" & log_label & "): done (got no Handover)");
7246 break;
7247 }
7248 }
7249
7250 f_rslem_resume(RSL1_PROC);
7251 f_rslem_resume(RSL2_PROC);
7252 f_sleep(3.0);
7253 RSL.clear;
7254
7255 log("f_probe_for_handover(" & log_label & "): done clearing");
7256}
7257
7258/* Test the effect of various neighbor configuration scenarios:
7259 *
7260 * To avoid complexity, block off any actual handover operation, and always remain on the lchan at bts 0.
7261 * Reconfigure the neighbors for bts 0, trigger a Handover, and probe whether osmo-bsc does or doesn't start HO.
7262 */
7263private function f_tc_ho_neighbor_config_start() runs on MSC_ConnHdlr {
7264 g_pars := f_gen_test_hdlr_pars();
7265 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
7266 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007267
7268 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
7269 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
7270
7271 /* Establish lchan at bts 0 */
7272 f_establish_fully(ass_cmd, exp_compl);
7273
7274 /* Shorten the inter-BSC Handover timeout, to not wait so long for inter-BSC Handovers */
7275 f_vty_enter_cfg_network(BSCVTY);
7276 f_vty_transceive(BSCVTY, "timer T7 1");
7277 f_vty_transceive(BSCVTY, "end");
7278}
7279
7280private function f_tc_ho_neighbor_config_1(charstring id) runs on MSC_ConnHdlr {
7281 f_tc_ho_neighbor_config_start();
7282
7283 /*
7284 * bts 0 ARFCN 871 BSIC 10
7285 * bts 1 ARFCN 871 BSIC 11
7286 * bts 2 ARFCN 871 BSIC 12
7287 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7288 */
7289
7290 log("f_tc_ho_neighbor_config: 1. No 'neighbor' config");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007291 f_bts_0_cfg(BSCVTY, {"no neighbors"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007292 f_probe_for_handover("1.a", "HO to bts 1 works, implicitly listed as neighbor (legacy behavior when none are configured)",
7293 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007294 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007295
7296 f_probe_for_handover("1.b", "HO to unknown cell does not start",
7297 "handover any to arfcn 13 bsic 39",
7298 false);
7299
7300 f_probe_for_handover("1.c", "HO to 871-12 is ambiguous = error",
7301 "handover any to arfcn 871 bsic 12",
7302 false);
7303
7304 f_probe_for_handover("1.d", "HO to 871-11 still works (verify that this test properly cleans up)",
7305 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007306 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007307
7308 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007309}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007310testcase TC_ho_neighbor_config_1() runs on test_CT {
7311 var MSC_ConnHdlr vc_conn;
7312 f_init(3, true, guard_timeout := 60.0);
7313 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007314 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007315 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_1));
7316 vc_conn.done;
7317
7318 /* f_tc_ho_neighbor_config_start() */
7319 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7320 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7321
7322 /* 1.a */
7323 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7324 * handover quickly by sending a Handover Failure message. */
7325 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7326 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7327 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7328 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007329 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7330 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007331
7332 /* 1.b */
7333 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7334 f_ctrs_bsc_and_bts_add(0, "handover:error");
7335
7336 /* 1.c */
7337 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7338 f_ctrs_bsc_and_bts_add(0, "handover:error");
7339
7340 /* 1.d */
7341 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7342 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7343 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7344 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007345 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7346 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007347
7348 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007349 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007350}
7351
Neels Hofmeyr91401012019-07-11 00:42:35 +02007352private function f_tc_ho_neighbor_config_2(charstring id) runs on MSC_ConnHdlr {
7353 f_tc_ho_neighbor_config_start();
7354
7355 /*
7356 * bts 0 ARFCN 871 BSIC 10
7357 * bts 1 ARFCN 871 BSIC 11
7358 * bts 2 ARFCN 871 BSIC 12
7359 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7360 */
7361
7362 log("f_tc_ho_neighbor_config: 2. explicit local neighbor: 'neighbor bts 1'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007363 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007364 f_sleep(0.5);
7365
7366 f_probe_for_handover("2.a", "HO to bts 1 works, explicitly listed as neighbor",
7367 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007368 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007369
7370 f_probe_for_handover("2.b", "HO to bts 2 doesn't work, not listed as neighbor",
7371 "handover any to arfcn 871 bsic 12",
7372 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007373 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007374}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007375testcase TC_ho_neighbor_config_2() runs on test_CT {
7376 var MSC_ConnHdlr vc_conn;
7377 f_init(3, true, guard_timeout := 50.0);
7378 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007379 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007380 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_2));
7381 vc_conn.done;
7382
7383 /* f_tc_ho_neighbor_config_start() */
7384 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7385 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7386
7387 /* 2.a */
7388 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7389 * handover quickly by sending a Handover Failure message. */
7390 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7391 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7392 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7393 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007394 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7395 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007396
7397 /* 2.b */
7398 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7399 f_ctrs_bsc_and_bts_add(0, "handover:error");
7400
7401 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007402 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007403}
7404
Neels Hofmeyr91401012019-07-11 00:42:35 +02007405private function f_tc_ho_neighbor_config_3(charstring id) runs on MSC_ConnHdlr {
7406 f_tc_ho_neighbor_config_start();
7407
7408 /*
7409 * bts 0 ARFCN 871 BSIC 10
7410 * bts 1 ARFCN 871 BSIC 11
7411 * bts 2 ARFCN 871 BSIC 12
7412 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7413 */
7414
7415 log("f_tc_ho_neighbor_config: 3. explicit local neighbor: 'neighbor bts 2'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007416 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007417 f_sleep(0.5);
7418
7419 f_probe_for_handover("3.a", "HO to bts 1 doesn't work, not listed as neighbor",
7420 "handover any to arfcn 871 bsic 11",
7421 false);
7422 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",
7423 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007424 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007425 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007426}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007427testcase TC_ho_neighbor_config_3() runs on test_CT {
7428 var MSC_ConnHdlr vc_conn;
7429 f_init(3, true, guard_timeout := 50.0);
7430 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007431 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007432 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_3));
7433 vc_conn.done;
7434
7435 /* f_tc_ho_neighbor_config_start() */
7436 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7437 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7438
7439 /* 3.a */
7440 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7441 f_ctrs_bsc_and_bts_add(0, "handover:error");
7442
7443 /* 3.b */
7444 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7445 * handover quickly by sending a Handover Failure message. */
7446 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7447 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7448 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7449 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007450 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7451 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007452
7453 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007454 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007455}
7456
Neels Hofmeyr91401012019-07-11 00:42:35 +02007457private function f_tc_ho_neighbor_config_4(charstring id) runs on MSC_ConnHdlr {
7458 f_tc_ho_neighbor_config_start();
7459
7460 /*
7461 * bts 0 ARFCN 871 BSIC 10
7462 * bts 1 ARFCN 871 BSIC 11
7463 * bts 2 ARFCN 871 BSIC 12
7464 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7465 */
7466
7467 log("f_tc_ho_neighbor_config: 4. explicit remote neighbor: 'neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007468 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007469 f_sleep(0.5);
7470
7471 f_probe_for_handover("4.a", "HO to bts 1 doesn't work, not listed as neighbor",
7472 "handover any to arfcn 871 bsic 11",
7473 false);
7474 f_probe_for_handover("4.b", "HO to bts 2 doesn't work, not listed as neighbor",
7475 "handover any to arfcn 871 bsic 12",
7476 false);
7477 f_probe_for_handover("4.c", "HO to 123-45 triggers inter-BSC HO",
7478 "handover any to arfcn 123 bsic 45",
7479 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007480 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007481}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007482testcase TC_ho_neighbor_config_4() runs on test_CT {
7483 var MSC_ConnHdlr vc_conn;
7484 f_init(3, true, guard_timeout := 50.0);
7485 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007486 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007487 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_4));
7488 vc_conn.done;
7489
7490 /* f_tc_ho_neighbor_config_start() */
7491 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7492 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7493
7494 /* 4.a */
7495 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7496 f_ctrs_bsc_and_bts_add(0, "handover:error");
7497
7498 /* 4.b */
7499 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7500 f_ctrs_bsc_and_bts_add(0, "handover:error");
7501
7502 /* 4.c */
7503 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7504 * handover quickly by timing out after the Handover Required message */
7505 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7506 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7507 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7508 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7509
7510 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007511 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007512}
7513
Neels Hofmeyr91401012019-07-11 00:42:35 +02007514private function f_tc_ho_neighbor_config_5(charstring id) runs on MSC_ConnHdlr {
7515 f_tc_ho_neighbor_config_start();
7516
7517 /*
7518 * bts 0 ARFCN 871 BSIC 10
7519 * bts 1 ARFCN 871 BSIC 11
7520 * bts 2 ARFCN 871 BSIC 12
7521 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7522 */
7523
7524 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 +02007525 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007526 f_sleep(0.5);
7527
7528 f_probe_for_handover("5.a", "HO to 871-12 triggers inter-BSC HO (ignoring local cells with same ARFCN+BSIC)",
7529 "handover any to arfcn 871 bsic 12",
7530 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007531 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007532}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007533testcase TC_ho_neighbor_config_5() runs on test_CT {
7534 var MSC_ConnHdlr vc_conn;
7535 f_init(3, true);
7536 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007537 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007538 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_5));
7539 vc_conn.done;
7540
7541 /* f_tc_ho_neighbor_config_start() */
7542 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7543 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7544
7545 /* 5 */
7546 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7547 * handover quickly by timing out after the Handover Required message */
7548 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7549 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7550 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7551 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7552
7553 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007554 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007555}
7556
Neels Hofmeyr91401012019-07-11 00:42:35 +02007557private function f_tc_ho_neighbor_config_6(charstring id) runs on MSC_ConnHdlr {
7558 f_tc_ho_neighbor_config_start();
7559
7560 /*
7561 * bts 0 ARFCN 871 BSIC 10
7562 * bts 1 ARFCN 871 BSIC 11
7563 * bts 2 ARFCN 871 BSIC 12
7564 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7565 */
7566
7567 log("f_tc_ho_neighbor_config: 6. config error: explicit local and remote neighbors with ambiguous ARFCN+BSIC:"
7568 & " 'neighbor bts 2; neighbor lac 99 arfcn 871 bsic 12'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007569 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007570 f_sleep(0.5);
7571
7572 f_probe_for_handover("6.a", "HO to 871-12 is ambiguous = error",
7573 "handover any to arfcn 871 bsic 12",
7574 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007575 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007576}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007577testcase TC_ho_neighbor_config_6() runs on test_CT {
7578 var MSC_ConnHdlr vc_conn;
7579 f_init(3, true);
7580 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007581 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007582 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_6));
7583 vc_conn.done;
7584
7585 /* f_tc_ho_neighbor_config_start() */
7586 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7587 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7588
7589 /* 6.a */
7590 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7591 * handover quickly by timing out after the Handover Required message */
7592 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7593 f_ctrs_bsc_and_bts_add(0, "handover:error");
7594
7595 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007596 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007597}
7598
Neels Hofmeyr91401012019-07-11 00:42:35 +02007599private function f_tc_ho_neighbor_config_7(charstring id) runs on MSC_ConnHdlr {
7600 f_tc_ho_neighbor_config_start();
7601
7602 /*
7603 * bts 0 ARFCN 871 BSIC 10
7604 * bts 1 ARFCN 871 BSIC 11
7605 * bts 2 ARFCN 871 BSIC 12
7606 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7607 */
7608
7609 log("f_tc_ho_neighbor_config: 7. explicit local and remote neighbors:"
7610 & " 'neighbor bts 2; neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007611 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007612 f_sleep(0.5);
7613
7614 f_probe_for_handover("7.a", "HO to 871-12 does HO to bts 2",
7615 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007616 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007617 f_probe_for_handover("7.b", "HO to 123-45 triggers inter-BSC HO",
7618 "handover any to arfcn 123 bsic 45",
7619 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007620 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007621}
Neels Hofmeyr91401012019-07-11 00:42:35 +02007622testcase TC_ho_neighbor_config_7() runs on test_CT {
7623 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf2b88032020-06-16 00:35:04 +02007624 f_init(3, true, guard_timeout := 50.0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007625 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007626 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007627 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_7));
7628 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007629
7630 /* f_tc_ho_neighbor_config_start() */
7631 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7632 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7633
7634 /* 7.a */
7635 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7636 * handover quickly by sending a Handover Failure message. */
7637 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7638 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7639 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7640 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007641 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7642 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007643
7644 /* 7.b */
7645 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7646 * handover quickly by timing out after the Handover Required message */
7647 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7648 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7649 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7650 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7651
7652 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007653 f_shutdown_helper(ho := true);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007654}
7655
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007656/* OS#3041: Open and close N connections in a normal fashion, and expect no
7657 * BSSMAP Reset just because of that. */
7658testcase TC_bssap_rlsd_does_not_cause_bssmap_reset() runs on test_CT {
7659 var default d;
7660 var integer i;
7661 var DchanTuple dt;
7662
7663 f_init();
7664
7665 /* Wait for initial BSSMAP Reset to pass */
7666 f_sleep(4.0);
7667
7668 d := activate(no_bssmap_reset());
7669
7670 /* Setup up a number of connections and RLSD them again from the MSC
7671 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7672 * Let's do it some more times for good measure. */
Harald Weltec3260d92018-06-11 17:48:16 +02007673 for (i := 0; i < 4; i := i+1) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007674 /* Since we're doing a lot of runs, give each one a fresh
7675 * T_guard from the top. */
7676 T_guard.start;
7677
7678 /* Setup a BSSAP connection and clear it right away. This is
7679 * the MSC telling the BSC about a planned release, it's not an
7680 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007681 dt := f_est_dchan(int2oct(i,1), 23+i, gen_l3_valid_payload());
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007682
7683 /* MSC disconnects (RLSD). */
7684 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
7685 }
7686
7687 /* In the buggy behavior, a timeout of 2 seconds happens between above
7688 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7689 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7690 f_sleep(4.0);
7691
7692 deactivate(d);
7693 f_shutdown_helper();
7694}
Harald Welte552620d2017-12-16 23:21:36 +01007695
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007696/* OS#3041: Open and close N connections in a normal fashion, and expect no
7697 * BSSMAP Reset just because of that. Invoke the release by a BSSMAP Clear from
7698 * the MSC. */
7699testcase TC_bssmap_clear_does_not_cause_bssmap_reset() runs on test_CT {
7700 var default d;
7701 var integer i;
7702 var DchanTuple dt;
7703 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007704 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_CALL_CONTROL;
7705 var BssmapCause cause := enum2int(cause_val);
7706
7707 f_init();
7708
7709 /* Wait for initial BSSMAP Reset to pass */
7710 f_sleep(4.0);
7711
7712 d := activate(no_bssmap_reset());
7713
7714 /* Setup up a number of connections and RLSD them again from the MSC
7715 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7716 * Let's do it some more times for good measure. */
7717 for (i := 0; i < 8; i := i+1) {
7718 /* Since we're doing a lot of runs, give each one a fresh
7719 * T_guard from the top. */
7720 T_guard.start;
7721
7722 /* Setup a BSSAP connection and clear it right away. This is
7723 * the MSC telling the BSC about a planned release, it's not an
7724 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007725 dt := f_est_dchan(int2oct(i,1), 23+i, gen_l3_valid_payload());
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007726
7727 /* Instruct BSC to clear channel */
7728 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7729
7730 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007731 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007732 }
7733
7734 /* In the buggy behavior, a timeout of 2 seconds happens between above
7735 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7736 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7737 f_sleep(4.0);
7738
7739 deactivate(d);
7740 f_shutdown_helper();
7741}
7742
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007743/* OS#3041: Open and close N connections in a normal fashion, and expect no
7744 * BSSMAP Reset just because of that. Close connections from the MS side with a
7745 * Release Ind on RSL. */
7746testcase TC_ms_rel_ind_does_not_cause_bssmap_reset() runs on test_CT {
7747 var default d;
7748 var integer i;
7749 var DchanTuple dt;
7750 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007751 var integer j;
7752
7753 f_init();
7754
7755 /* Wait for initial BSSMAP Reset to pass */
7756 f_sleep(4.0);
7757
7758 d := activate(no_bssmap_reset());
7759
7760 /* Setup up a number of connections and RLSD them again from the MSC
7761 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7762 * Let's do it some more times for good measure. */
7763 for (i := 0; i < 8; i := i+1) {
7764 /* Since we're doing a lot of runs, give each one a fresh
7765 * T_guard from the top. */
7766 T_guard.start;
7767
7768 /* Setup a BSSAP connection and clear it right away. This is
7769 * the MSC telling the BSC about a planned release, it's not an
7770 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007771 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007772
7773 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007774 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007775
7776 /* expect Clear Request on MSC side */
7777 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
7778
7779 /* Instruct BSC to clear channel */
7780 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
7781 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7782
7783 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007784 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007785 }
7786
7787 /* In the buggy behavior, a timeout of 2 seconds happens between above
7788 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7789 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7790 f_sleep(4.0);
7791
7792 deactivate(d);
7793 f_shutdown_helper();
7794}
7795
Harald Welte94e0c342018-04-07 11:33:23 +02007796/***********************************************************************
7797 * IPA style dynamic PDCH
7798 ***********************************************************************/
7799
7800private function f_dyn_ipa_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7801 template (omit) RSL_Cause nack := omit)
7802runs on test_CT {
7803 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7804 var RSL_Message rsl_unused;
7805 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7806 f_vty_ts_action("pdch activate", bts_nr, trx_nr, ts_nr);
7807 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007808 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007809 if (istemplatekind(nack, "omit")) {
7810 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007811 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007812 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007813 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007814 }
7815}
7816
7817private function f_dyn_ipa_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7818 template (omit) RSL_Cause nack := omit)
7819runs on test_CT {
7820 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7821 var RSL_Message rsl_unused;
7822 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7823 f_vty_ts_action("pdch deactivate", bts_nr, trx_nr, ts_nr);
7824 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007825 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_DEACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007826 if (istemplatekind(nack, "omit")) {
7827 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007828 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007829 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007830 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007831 }
7832}
7833
7834private function f_ts_dyn_mode_get(integer bts_nr, integer trx_nr, integer ts_nr)
7835runs on test_CT return charstring {
7836 var charstring cmd, resp;
7837 cmd := "show timeslot "&int2str(bts_nr)&" "&int2str(trx_nr)&" "&int2str(ts_nr);
Stefan Sperlingcff13562018-11-13 15:24:06 +01007838 return f_vty_transceive_match_regexp_retry(BSCVTY, cmd, "*\((*)\)*", 0, 4, 1.0);
Harald Welte94e0c342018-04-07 11:33:23 +02007839}
7840
7841private function f_ts_dyn_mode_assert(integer bts_nr, integer trx_nr, integer ts_nr,
7842 template charstring exp)
7843runs on test_CT {
7844 var charstring mode := f_ts_dyn_mode_get(bts_nr, trx_nr, ts_nr);
7845 if (not match(mode, exp)) {
7846 setverdict(fail, "Unexpected TS Mode: ", mode);
Daniel Willmannafce8662018-07-06 23:11:32 +02007847 mtc.stop;
Harald Welte94e0c342018-04-07 11:33:23 +02007848 }
7849}
7850
7851private function f_ts_set_chcomb(integer bts_nr, integer trx_nr, integer ts_nr, charstring chcomb)
7852runs on test_CT {
7853 f_vty_enter_cfg_ts(BSCVTY, bts_nr, trx_nr, ts_nr);
7854 f_vty_transceive(BSCVTY, "phys_chan_config " & chcomb);
7855 f_vty_transceive(BSCVTY, "end");
7856}
7857
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007858
7859private function f_ts_reset_chcomb(integer bts_nr) runs on test_CT {
7860 var integer i;
7861 for (i := 0; i < 8; i := i + 1) {
7862 f_ts_set_chcomb(bts_nr, 0, i, phys_chan_config[i]);
7863 }
7864}
7865
Harald Welte94e0c342018-04-07 11:33:23 +02007866private const charstring TCHF_MODE := "TCH/F mode";
7867private const charstring TCHH_MODE := "TCH/H mode";
7868private const charstring PDCH_MODE := "PDCH mode";
7869private const charstring NONE_MODE := "NONE mode";
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007870private const charstring SDCCH8_MODE := "SDCCH8 mode";
Harald Welte94e0c342018-04-07 11:33:23 +02007871
7872/* Test IPA PDCH activation / deactivation triggered by VTY */
7873testcase TC_dyn_pdch_ipa_act_deact() runs on test_CT {
7874 var RSL_Message rsl_unused;
7875
7876 /* change Timeslot 6 before f_init() starts RSL */
7877 f_init_vty();
7878 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7879 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7880
7881 f_init(1, false);
7882 f_sleep(1.0);
7883
7884 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7885
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007886 log("TCH/F_PDCH pchan starts out in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007887 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7888 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007889 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
7890 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007891 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007892 log("TCH/F_PDCH pchan, PDCH ACT was ACKed, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007893 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7894
7895 /* De-activate it via VTY */
7896 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7897 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007898 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007899 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7900
7901 /* re-activate it via VTY */
7902 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn);
7903 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007904 log("TCH/F_PDCH pchan, PDCH ACT via VTY, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007905 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7906
7907 /* and finally de-activate it again */
7908 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7909 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007910 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007911 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7912
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007913 /* clean up config */
7914 f_ts_set_chcomb(0, 0, 6, "PDCH");
7915
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007916 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007917}
7918
7919/* Test IPA PDCH activation NACK */
7920testcase TC_dyn_pdch_ipa_act_nack() runs on test_CT {
7921 var RSL_Message rsl_unused;
7922
7923 /* change Timeslot 6 before f_init() starts RSL */
7924 f_init_vty();
7925 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7926 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7927
7928 f_init(1, false);
7929 f_sleep(1.0);
7930
7931 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7932
7933 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7934 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007935 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
7936 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007937 f_sleep(1.0);
7938 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7939
7940 /* De-activate it via VTY */
7941 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7942 f_sleep(1.0);
7943 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7944
7945 /* re-activate it via VTY, but fail that; check BSC still assumes TCH/F mode */
7946 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn, RSL_ERR_EQUIPMENT_FAIL);
7947 f_sleep(1.0);
7948 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7949
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007950 /* clean up config */
7951 f_ts_set_chcomb(0, 0, 6, "PDCH");
7952
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007953 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007954}
7955
7956
7957/***********************************************************************
7958 * Osmocom style dynamic PDCH
7959 ***********************************************************************/
7960
7961private function f_dyn_osmo_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7962 template (omit) RSL_Cause nack := omit)
7963runs on test_CT {
7964 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
7965 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02007966 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02007967 /* FIXME: no VTY command to activate Osmocom PDCH !! */
7968 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007969 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT(chan_nr, ?));
Harald Welte94e0c342018-04-07 11:33:23 +02007970 if (istemplatekind(nack, "omit")) {
7971 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007972 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02007973 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007974 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007975 }
7976}
7977
7978private function f_dyn_osmo_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7979 template (omit) RSL_Cause nack := omit)
7980runs on test_CT {
7981 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
7982 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02007983 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02007984 /* FIXME: no VTY command to activate Osmocom PDCH !! */
7985 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007986 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007987 if (istemplatekind(nack, "omit")) {
7988 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007989 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007990 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007991 //f_ipa_tx(ts_RSL_RF_CHAN_REL_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007992 }
7993}
7994
7995/* Test Osmocom dyn PDCH activation / deactivation triggered by VTY */
7996testcase TC_dyn_pdch_osmo_act_deact() runs on test_CT {
7997 var RSL_Message rsl_unused;
7998
7999 /* change Timeslot 6 before f_init() starts RSL */
8000 f_init_vty();
8001 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
8002 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8003
8004 f_init(1, false);
8005 f_sleep(1.0);
8006
8007 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
8008
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02008009 log("TCH/F_TCH/H_PDCH pchan starts out in disabled mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02008010 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8011 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008012 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008013
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008014 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02008015 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02008016 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 +02008017 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
8018
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008019 /* clean up config */
8020 f_ts_set_chcomb(0, 0, 6, "PDCH");
8021
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008022 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008023}
8024
8025/* Test Osmocom dyn PDCH activation NACK behavior */
8026testcase TC_dyn_pdch_osmo_act_nack() runs on test_CT {
8027 var RSL_Message rsl_unused;
8028
8029 /* change Timeslot 6 before f_init() starts RSL */
8030 f_init_vty();
8031 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
8032 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8033
8034 f_init(1, false);
8035 f_sleep(1.0);
8036
8037 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
8038
8039 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8040 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008041 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008042
8043 /* NACK this activation and expect the "show timeslot" mode still to be NONE */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008044 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
Harald Welte94e0c342018-04-07 11:33:23 +02008045 f_sleep(1.0);
8046 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8047
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008048 /* clean up config */
8049 f_ts_set_chcomb(0, 0, 6, "PDCH");
8050
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008051 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008052}
8053
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008054/* Test Osmocom dyn TS SDCCH8 activation / deactivation */
8055testcase TC_dyn_ts_sdcch8_act_deact() runs on test_CT {
8056 var RSL_Message rsl_unused, rsl_msg;
8057 var DchanTuple dt;
8058 var BSSAP_N_CONNECT_ind rx_c_ind;
8059
8060 /* change Timeslot 6 before f_init() starts RSL */
8061 f_init_vty();
8062 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
8063 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8064
8065 f_init(1, false);
8066 f_sleep(1.0);
8067
8068 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8069
8070 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8071 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8072 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008073 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008074
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008075 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008076 f_sleep(1.0);
8077 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8078 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8079
8080 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8081 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008082 var DchanTuples sdcch_cleanup := {};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008083 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008084 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008085 dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008086 sdcch_cleanup := sdcch_cleanup & { dt };
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008087 }
8088
8089 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008090 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8091 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8092 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008093
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008094 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008095 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008096 dt.idx := {0, 0};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008097
8098 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008099 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8100 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008101 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
8102
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008103 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 +02008104 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8105 dt.sccp_conn_id := rx_c_ind.connectionId;
8106 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8107
8108 /* Instruct BSC to clear channel */
8109 var BssmapCause cause := 0;
8110 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008111 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008112
8113 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008114 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8115 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008116 f_sleep(1.0);
8117 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8118
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008119 /* Clean up SDCCH lchans */
8120 for (i := 0; i < lengthof(sdcch_cleanup); i := i + 1) {
8121 f_perform_clear_test_ct(sdcch_cleanup[i]);
8122 }
8123
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008124 /* clean up config */
8125 f_ts_set_chcomb(0, 0, 6, "PDCH");
8126
8127 f_shutdown_helper();
8128}
8129
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008130/* Validate all 8 subslots of a dynamics TS configured as SDCCH8 are used */
8131testcase TC_dyn_ts_sdcch8_all_subslots_used() runs on test_CT {
8132 var ASP_RSL_Unitdata rsl_ud;
8133 var integer i;
8134 var integer chreq_total, chreq_nochan;
8135
8136 f_init_vty();
8137 for (i := 1; i < 8; i := i + 1) {
8138 if (i == 2) {
8139 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8140 } else {
8141 f_ts_set_chcomb(0, 0, i, "PDCH");
8142 }
8143 }
8144 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8145
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008146 f_init(1, guard_timeout := 60.0);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008147
8148 /* The dyn TS want to activate PDCH mode, ACK that. */
8149 var RslChannelNr chan_nr;
8150 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008151 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
8152 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008153
8154 f_sleep(1.0);
8155
8156 /* Exhaust all dedicated SDCCH lchans.
8157 /* GSM 44.018 Table 9.1.8.2:
8158 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
8159 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008160 var DchanTuples chan_cleanup := {};
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008161 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008162 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 +02008163 }
8164
8165 /* Only the dyn TS is still available. Its first lchan gets converted to SDCCH8 */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008166 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 +02008167 /* Also occupy the seven other SDCCH of the dyn TS */
8168 for (i := 0; i < 7; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008169 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 +01008170 }
8171
8172 /* Clean up SDCCH lchans */
8173 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8174 f_perform_clear_test_ct(chan_cleanup[i]);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008175 }
8176
8177 /* clean up config */
8178 f_ts_reset_chcomb(0);
8179
8180 f_shutdown_helper();
8181}
8182
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008183/* Test Osmocom dyn TS SDCCH8 activation / deactivation: If activating dyn TS as
8184 SDCCH8 would end up in having no free TCH, then BSC should decide to activate
8185 it as TCH directly instead. SYS#5309. */
8186testcase TC_dyn_ts_sdcch8_tch_call_act_deact() runs on test_CT {
8187 var RSL_Message rsl_unused, rsl_msg;
8188 var DchanTuple dt;
8189 var BSSAP_N_CONNECT_ind rx_c_ind;
8190 var integer i;
8191
8192 /* change Timeslot 6 before f_init() starts RSL */
8193 f_init_vty();
8194 for (i := 1; i < 8; i := i + 1) {
8195 if (i == 6) {
8196 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8197 } else {
8198 f_ts_set_chcomb(0, 0, i, "PDCH");
8199 }
8200 }
8201 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8202
8203 f_init(1, false);
8204 f_sleep(1.0);
8205
8206 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8207
8208 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8209 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8210 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008211 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008212
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008213 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008214 f_sleep(1.0);
8215 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8216 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8217
8218 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8219 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008220 var DchanTuples chan_cleanup := {};
Pau Espin Pedrol2ebbe7c2021-07-23 16:17:09 +02008221 var OCT1 ra := '43'O; /* RA containing reason=originating speech call*/
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008222 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008223 dt := f_est_dchan(ra, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008224 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008225 }
8226
8227 /* Now the dyn ts is selected. First PDCH is released, then TCH chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008228 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int(ra) + i, 1), 2342));
8229 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8230 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008231
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008232 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008233 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008234 dt.idx := {0, 0};
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008235
8236 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008237 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8238 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008239 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
8240
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008241 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 +02008242 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8243 dt.sccp_conn_id := rx_c_ind.connectionId;
8244 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8245
8246 /* Instruct BSC to clear channel */
8247 var BssmapCause cause := 0;
8248 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008249 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008250
8251 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008252 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8253 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008254 f_sleep(1.0);
8255 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8256
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008257 /* Clean up SDCCH lchans */
8258 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8259 f_perform_clear_test_ct(chan_cleanup[i]);
8260 }
8261
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008262 /* clean up config */
8263 f_ts_reset_chcomb(0);
8264 /* TODO: clean up other channels? */
8265
8266 f_shutdown_helper();
8267}
8268
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008269/* Test Osmocom dyn TS SDCCH8 activation / deactivation when SDCCH fails at BTS */
8270testcase TC_dyn_ts_sdcch8_act_nack() runs on test_CT {
8271 var RSL_Message rsl_unused, rsl_msg;
8272 var DchanTuple dt;
8273 var BSSAP_N_CONNECT_ind rx_c_ind;
8274 var GsmRrMessage rr;
8275
8276 /* change Timeslot 6 before f_init() starts RSL */
8277 f_init_vty();
8278 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
8279 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8280
8281 f_init(1, false);
8282 f_sleep(1.0);
8283
8284 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8285
8286 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8287 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8288 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008289 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008290
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008291 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008292 f_sleep(1.0);
8293 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8294 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8295
8296 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8297 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008298 var DchanTuples chan_cleanup := {};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008299 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008300 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008301 dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008302 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008303 }
8304
8305 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008306 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8307 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8308 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008309
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008310 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008311 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008312 dt.idx := {0, 0};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008313
8314 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008315 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(dt.rsl_chan_nr, RSL_ERR_EQUIPMENT_FAIL));
8316 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008317 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
8318 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
8319 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Expected reject");
8320 }
8321
8322 /* FIXME? Currently the TS stays in state BORKEN: */
8323
8324 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008325 /* rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8326 * f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008327 * f_sleep(1.0);
8328 * f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE)
8329 */
8330
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008331 /* Clean up SDCCH lchans */
8332 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8333 f_perform_clear_test_ct(chan_cleanup[i]);
8334 }
8335
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008336 /* clean up config */
8337 f_ts_set_chcomb(0, 0, 6, "PDCH");
8338
8339 f_shutdown_helper();
8340}
8341
Stefan Sperling0796a822018-10-05 13:01:39 +02008342testcase TC_chopped_ipa_ping() runs on test_CT {
Stefan Sperling554123f2018-10-09 14:12:30 +02008343 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port, mp_bsc_ctrl_port};
Stefan Sperling0796a822018-10-05 13:01:39 +02008344 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8345 IPA_Testing.f_run_TC_chopped_ipa_ping(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8346 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008347 f_shutdown_helper();
Stefan Sperling0796a822018-10-05 13:01:39 +02008348}
8349
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008350testcase TC_chopped_ipa_payload() runs on test_CT {
8351 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port
8352 /* TODO: mp_bsc_ctrl_port does not work yet */};
8353 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8354 IPA_Testing.f_run_TC_chopped_ipa_payload(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8355 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008356 f_shutdown_helper();
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008357}
8358
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008359/* Verify the BSC sends the MS Power Parameters IE during CHAN ACT to make sure
8360 the BTS does autonomous MS power control loop */
8361testcase TC_assignment_verify_ms_power_params_ie() runs on test_CT {
8362 var MSC_ConnHdlr vc_conn;
8363 var TestHdlrParams pars := f_gen_test_hdlr_pars();
8364 //pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
8365 pars.exp_ms_power_params := true;
8366
8367 f_init(1, true);
8368 f_sleep(1.0);
8369 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
8370 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008371 f_shutdown_helper();
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008372}
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008373
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008374/* Verify activation and deactivation of the BCCH carrier power reduction mode */
8375testcase TC_c0_power_red_mode() runs on test_CT {
8376 f_init(1);
8377
8378 for (var integer red := 6; red >= 0; red := red - 2) {
8379 /* Configure BCCH carrier power reduction mode via the VTY */
8380 f_vty_transceive(BSCVTY, "bts 0 c0-power-reduction " & int2str(red));
8381
8382 /* Expect Osmocom specific BS Power Control message on the RSL */
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03008383 var template (present) RSL_Message tr_rsl_pdu := tr_RSL_BS_PWR_CTRL(
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008384 chan_nr := t_RslChanNr_BCCH(0),
8385 bs_power := tr_RSL_IE_BS_Power(red / 2));
8386 tr_rsl_pdu.msg_disc := tr_RSL_MsgDisc(RSL_MDISC_CCHAN, false);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008387 var RSL_Message unused := f_exp_ipa_rx(tr_rsl_pdu);
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008388
8389 /* Additionally verify the applied value over the CTRL interface */
8390 var CtrlValue cred := f_ctrl_get_bts(IPA_CTRL, 0, "c0-power-reduction");
8391 if (cred != int2str(red)) {
8392 setverdict(fail, "Unexpected BCCH carrier power reduction value ",
8393 cred, " (expected ", red, ")");
8394 }
8395 }
8396
8397 f_shutdown_helper();
8398}
8399
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008400/***********************************************************************
8401 * MSC Pooling
8402 ***********************************************************************/
8403
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008404template MobileIdentityLV ts_MI_TMSI_NRI_LV(integer nri_v, integer nri_bitlen := 10) :=
Harald Weltebf397612021-01-14 20:39:46 +01008405 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 +02008406
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008407private 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 +02008408runs on MSC_ConnHdlr {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008409 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008410 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008411 f_logp(BSCVTY, "Got RSL RR Release");
8412 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008413 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008414 f_logp(BSCVTY, "Got RSL Deact SACCH");
8415 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008416 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008417 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008418 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8419 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008420 break;
8421 }
8422 }
8423}
8424
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008425private altstep as_mgcp_ack_all_dlcx() runs on MSC_ConnHdlr {
8426 var MgcpCommand mgcp_cmd;
8427 [] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
8428 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
8429 repeat;
8430 }
8431}
8432
8433private altstep as_rsl_ack_all_rel_req() runs on MSC_ConnHdlr {
8434 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
8435 [] RSL.receive(tr_RSL_REL_REQ(g_chan_nr, ?)) {
8436 RSL.send(ts_RSL_REL_CONF(g_chan_nr, main_dcch));
8437 repeat;
8438 }
8439}
8440
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008441friend function f_perform_clear(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC,
8442 template PDU_ML3_NW_MS exp_rr_rel_tmpl := tr_RRM_RR_RELEASE)
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02008443runs on MSC_ConnHdlr {
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008444 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8445 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008446 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008447 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8448 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008449 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008450 f_logp(BSCVTY, "Got RSL RR Release");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008451 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008452 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008453 f_logp(BSCVTY, "Got RSL Deact SACCH");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008454 }
8455 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008456 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008457 /* Also drop the SCCP connection */
8458 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8459 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008460 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008461 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008462 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8463 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008464 }
8465 }
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008466 deactivate(ack_dlcx);
8467 deactivate(ack_rel_req);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008468}
8469
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01008470friend function f_perform_clear_no_rr_rel(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC)
8471runs on MSC_ConnHdlr {
8472 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8473 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
8474 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8475 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8476 interleave {
8477 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
8478 f_logp(BSCVTY, "Got RSL Deact SACCH");
8479 }
8480 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
8481 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8482 /* Also drop the SCCP connection */
8483 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8484 }
8485 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
8486 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
8487 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8488 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
8489 }
8490 }
8491 deactivate(ack_dlcx);
8492 deactivate(ack_rel_req);
8493}
8494
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01008495friend function f_perform_clear_no_lchan()
8496runs on MSC_ConnHdlr {
8497 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8498 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8499 BSSAP.receive(tr_BSSMAP_ClearComplete);
8500 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8501 /* Also drop the SCCP connection */
8502 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8503}
8504
Vadim Yanitskiy65d879d2022-06-23 18:15:39 +07008505friend function f_perform_clear_test_ct(DchanTuple dt)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008506 runs on test_CT
8507{
8508 /* Instruct BSC to clear channel */
8509 var BssmapCause cause := 0;
8510 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008511 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008512}
8513
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008514private function f_perform_compl_l3(RSL_DCHAN_PT rsl_pt, RSLEM_PROC_PT rsl_proc_pt,
8515 template PDU_ML3_MS_NW l3_info, boolean do_clear := true, boolean expect_bssmap_l3 := true)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008516runs on MSC_ConnHdlr {
8517 timer T := 10.0;
8518 var octetstring l3_enc := enc_PDU_ML3_MS_NW(valueof(l3_info));
8519
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008520 f_logp(BSCVTY, "establish channel, send Complete Layer 3 Info");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008521 f_create_bssmap_exp(l3_enc);
8522
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008523 /* RSL_Emulation.f_chan_est() on rsl_pt:
8524 * This is basically code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008525 * RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
8526 */
8527 var RSL_Message rx_rsl;
8528 var GsmRrMessage rr;
8529
8530 /* request a channel to be established */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008531 rsl_pt.send(ts_RSLDC_ChanRqd(g_pars.ra, g_pars.fn));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008532 /* expect immediate assignment.
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008533 * Code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008534 * rx_rsl := f_rx_or_fail(tr_RSL_IMM_ASSIGN);
8535 */
8536 timer Tt := 10.0;
8537
8538 /* request a channel to be established */
8539 Tt.start;
8540 alt {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008541 [] rsl_pt.receive(tr_RSL_IMM_ASSIGN) -> value rx_rsl {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008542 Tt.stop;
8543 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008544 [] rsl_pt.receive {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008545 setverdict(fail, "Unexpected RSL message on DCHAN");
8546 mtc.stop;
8547 }
8548 [] Tt.timeout {
8549 setverdict(fail, "Timeout waiting for RSL on DCHAN");
8550 mtc.stop;
8551 }
8552 }
8553 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
8554 g_chan_nr := rr.payload.imm_ass.chan_desc.chan_nr;
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008555 rsl_pt.send(ts_RSL_EST_IND(g_chan_nr, valueof(g_pars.link_id), l3_enc));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008556
8557
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008558 if (expect_bssmap_l3) {
8559 f_logp(BSCVTY, "expect BSSAP Complete Layer 3 Info at MSC");
8560 var template PDU_BSSAP exp_l3_compl;
8561 exp_l3_compl := tr_BSSMAP_ComplL3()
8562 if (g_pars.aoip == false) {
8563 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := omit;
8564 } else {
8565 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := ?;
8566 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008567
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008568 var PDU_BSSAP bssap;
8569 T.start;
8570 alt {
8571 [] BSSAP.receive(exp_l3_compl) -> value bssap {
8572 f_logp(BSCVTY, "received expected Complete Layer 3 Info at MSC");
8573 log("rx exp_l3_compl = ", bssap);
8574 }
8575 [] BSSAP.receive(tr_BSSMAP_ComplL3) {
8576 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received non-matching COMPLETE LAYER 3 INFORMATION");
8577 }
8578 [] T.timeout {
8579 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
8580 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008581 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008582
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008583 /* start ciphering, if requested */
8584 if (ispresent(g_pars.encr)) {
8585 f_logp(BSCVTY, "start ciphering");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008586 f_cipher_mode(g_pars.encr, rsl_pt := rsl_pt, rsl_proc_pt := rsl_proc_pt);
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008587 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008588 }
8589
8590 if (do_clear) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008591 f_perform_clear(rsl_pt, rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008592 }
8593 setverdict(pass);
8594 f_sleep(1.0);
8595}
8596
8597private function f_tc_mscpool_compl_l3(charstring id) runs on MSC_ConnHdlr {
8598 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8599 if (g_pars.mscpool.rsl_idx == 0) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008600 f_perform_compl_l3(RSL, RSL_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008601 } else if (g_pars.mscpool.rsl_idx == 1) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008602 f_perform_compl_l3(RSL1, RSL1_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008603 } else if (g_pars.mscpool.rsl_idx == 2) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008604 f_perform_compl_l3(RSL2, RSL2_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008605 }
8606}
8607
8608/* Various Complete Layer 3 by IMSI all end up with the first MSC, because the other MSCs are not connected. */
8609private function f_tc_mscpool_L3Compl_on_1_msc(charstring id) runs on MSC_ConnHdlr {
8610 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008611 f_perform_compl_l3(RSL, RSL_PROC, ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O) );
8612 f_perform_compl_l3(RSL, RSL_PROC, ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_IMSI_LV('001010000000002'H))) );
8613 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))) );
8614 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 +02008615}
8616testcase TC_mscpool_L3Compl_on_1_msc() runs on test_CT {
8617
8618 f_init(1, true);
8619 f_sleep(1.0);
8620 var MSC_ConnHdlr vc_conn;
8621 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008622
8623 f_ctrs_msc_init();
8624
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008625 vc_conn := f_start_handler(refers(f_tc_mscpool_L3Compl_on_1_msc), pars);
8626 vc_conn.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008627
8628 f_ctrs_msc_expect(0, "mscpool:subscr:new", 4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008629 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008630}
8631
8632/* Three Layer 3 Complete by IMSI are round-robin'ed across two connected MSCs */
8633/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8634 * just as well using only RSL. */
8635testcase TC_mscpool_L3Complete_by_imsi_round_robin() runs on test_CT {
8636
8637 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8638 f_sleep(1.0);
8639
8640 /* Control which MSC gets chosen next by the round-robin, otherwise
8641 * would be randomly affected by which other tests ran before this. */
8642 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8643
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008644 f_ctrs_msc_init();
8645
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008646 var MSC_ConnHdlr vc_conn1;
8647 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8648 pars1.mscpool.rsl_idx := 0;
8649 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
8650 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8651 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008652 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008653
8654 var MSC_ConnHdlr vc_conn2;
8655 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8656 pars2.mscpool.rsl_idx := 1;
8657 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
8658 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8659 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008660 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008661
8662 /* Test round-robin wrap to the first MSC */
8663 var MSC_ConnHdlr vc_conn3;
8664 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8665 pars3.mscpool.rsl_idx := 2;
8666 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))));
8667 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8668 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008669 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008670 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008671}
8672
8673/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 0
8674 * (configured in osmo-bsc.cfg). */
8675/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8676 * just as well using only RSL. */
8677testcase TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() runs on test_CT {
8678
8679 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8680 f_sleep(1.0);
8681
8682 /* Control which MSC gets chosen next by the round-robin, otherwise
8683 * would be randomly affected by which other tests ran before this. */
8684 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8685
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008686 f_ctrs_msc_init();
8687
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008688 var MSC_ConnHdlr vc_conn1;
8689 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8690 pars1.mscpool.rsl_idx := 0;
8691 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8692 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8693 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008694 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008695
8696 var MSC_ConnHdlr vc_conn2;
8697 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8698 pars2.mscpool.rsl_idx := 1;
8699 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8700 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8701 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008702 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008703
8704 /* Test round-robin wrap to the first MSC */
8705 var MSC_ConnHdlr vc_conn3;
8706 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8707 pars3.mscpool.rsl_idx := 2;
8708 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8709 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8710 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008711 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008712 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008713}
8714
8715/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 1
8716 * (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
8717 * NULL-NRI setting is stronger than that. */
8718/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8719 * just as well using only RSL. */
8720testcase TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() runs on test_CT {
8721
8722 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8723 f_sleep(1.0);
8724
8725 /* Control which MSC gets chosen next by the round-robin, otherwise
8726 * would be randomly affected by which other tests ran before this. */
8727 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8728
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008729 f_ctrs_msc_init();
8730
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008731 var MSC_ConnHdlr vc_conn1;
8732 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8733 pars1.mscpool.rsl_idx := 0;
8734 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8735 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8736 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008737 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008738
8739 var MSC_ConnHdlr vc_conn2;
8740 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8741 pars2.mscpool.rsl_idx := 1;
8742 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8743 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8744 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008745 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008746
8747 /* Test round-robin wrap to the first MSC */
8748 var MSC_ConnHdlr vc_conn3;
8749 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8750 pars3.mscpool.rsl_idx := 2;
8751 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8752 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8753 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008754 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008755 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008756}
8757
8758/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI not
8759 * assigned to any MSC (configured in osmo-bsc.cfg). */
8760/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8761 * just as well using only RSL. */
8762testcase TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() runs on test_CT {
8763
8764 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8765 f_sleep(1.0);
8766
8767 /* Control which MSC gets chosen next by the round-robin, otherwise
8768 * would be randomly affected by which other tests ran before this. */
8769 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8770
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008771 f_ctrs_msc_init();
8772
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008773 var MSC_ConnHdlr vc_conn1;
8774 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8775 pars1.mscpool.rsl_idx := 0;
8776 /* An NRI that is not assigned to any MSC */
8777 pars1.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(1023))));
8778 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8779 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008780 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008781
8782 var MSC_ConnHdlr vc_conn2;
8783 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8784 pars2.mscpool.rsl_idx := 1;
8785 /* An NRI that is not assigned to any MSC */
8786 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(768)), '00F110'O));
8787 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8788 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008789 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008790
8791 /* Test round-robin wrap to the first MSC */
8792 var MSC_ConnHdlr vc_conn3;
8793 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8794 pars3.mscpool.rsl_idx := 2;
8795 /* An NRI that is not assigned to any MSC */
8796 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_SS_ACT, valueof(ts_MI_TMSI_NRI_LV(819))));
8797 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8798 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008799 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008800 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008801}
8802
8803/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI
8804 * assigned to an MSC that is currently not connected (configured in osmo-bsc.cfg). */
8805/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8806 * just as well using only RSL. */
8807testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() runs on test_CT {
8808
8809 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8810 f_sleep(1.0);
8811
8812 /* Control which MSC gets chosen next by the round-robin, otherwise
8813 * would be randomly affected by which other tests ran before this. */
8814 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8815
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008816 f_ctrs_msc_init();
8817
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008818 var MSC_ConnHdlr vc_conn1;
8819 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8820 pars1.mscpool.rsl_idx := 0;
8821 /* An NRI that is assigned to an unconnected MSC */
8822 pars1.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(512))));
8823 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8824 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008825 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8826 f_ctrs_msc_add(0, "mscpool:subscr:new");
8827 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008828
8829 var MSC_ConnHdlr vc_conn2;
8830 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8831 pars2.mscpool.rsl_idx := 1;
8832 /* An NRI that is assigned to an unconnected MSC */
8833 pars2.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(767))));
8834 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8835 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008836 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8837 f_ctrs_msc_add(1, "mscpool:subscr:new");
8838 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008839
8840 /* Test round-robin wrap to the first MSC */
8841 var MSC_ConnHdlr vc_conn3;
8842 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8843 pars3.mscpool.rsl_idx := 2;
8844 /* An NRI that is assigned to an unconnected MSC */
8845 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(750)), '00F110'O));
8846 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8847 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008848 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8849 f_ctrs_msc_add(0, "mscpool:subscr:new");
8850 f_ctrs_msc_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008851 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008852}
8853
8854/* Three Layer 3 Complete by TMSI with valid NRI for the second MSC are all directed to the second MSC (configured in
8855 * osmo-bsc.cfg). */
8856/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8857 * just as well using only RSL. */
8858testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_1() runs on test_CT {
8859
8860 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8861 f_sleep(1.0);
8862
8863 /* All TMSIs in this test point at the second MSC, set the round robin to point at the first MSC to make sure
8864 * this is not using round-robin. */
8865 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8866
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008867 f_ctrs_msc_init();
8868
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008869 var MSC_ConnHdlr vc_conn1;
8870 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
8871 pars1.mscpool.rsl_idx := 0;
8872 /* An NRI of the second MSC's range (256-511) */
8873 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(256))));
8874 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8875 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008876 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008877
8878 var MSC_ConnHdlr vc_conn2;
8879 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8880 pars2.mscpool.rsl_idx := 1;
8881 /* An NRI of the second MSC's range (256-511) */
8882 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(260))));
8883 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8884 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008885 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008886
8887 var MSC_ConnHdlr vc_conn3;
8888 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8889 pars3.mscpool.rsl_idx := 2;
8890 /* An NRI of the second MSC's range (256-511) */
8891 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(511)), '00F110'O));
8892 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8893 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008894 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008895 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008896}
8897
8898/* Layer 3 Complete by TMSI with valid NRI for the third MSC are directed to the third MSC (configured in osmo-bsc.cfg),
8899 * while a round-robin remains unaffected by that. */
8900/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8901 * just as well using only RSL. */
8902testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_2() runs on test_CT {
8903
8904 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8905 f_sleep(1.0);
8906
8907 /* All TMSIs in this test point at the third MSC, set the round robin to point at the second MSC to make sure
8908 * this is not using round-robin. */
8909 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
8910
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008911 f_ctrs_msc_init();
8912
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008913 var MSC_ConnHdlr vc_conn1;
8914 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 2);
8915 pars1.mscpool.rsl_idx := 0;
8916 /* An NRI of the third MSC's range (512-767) */
8917 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(512))));
8918 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8919 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008920 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008921
8922 var MSC_ConnHdlr vc_conn2;
8923 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8924 pars2.mscpool.rsl_idx := 1;
8925 /* An NRI of the third MSC's range (512-767) */
8926 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(678))));
8927 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8928 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008929 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008930
8931 /* The above forwardings to third MSC have not affected the round robin, which still points at the second MSC */
8932 var MSC_ConnHdlr vc_conn3;
8933 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8934 pars3.mscpool.rsl_idx := 2;
8935 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000013'H)), '00F110'O));
8936 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8937 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008938 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008939 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008940}
8941
8942/* LU with a TMSI but indicating a different PLMN in its previous LAI: ignore the NRI. */
8943/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8944 * just as well using only RSL. */
8945testcase TC_mscpool_LU_by_tmsi_from_other_PLMN() runs on test_CT {
8946
8947 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8948 f_sleep(1.0);
8949
8950 /* The TMSIs in this test points at the second MSC, but since it is from a different PLMN, round-robin is used
8951 * instead, and hits msc 0. */
8952 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8953
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008954 f_ctrs_msc_init();
8955
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008956 /* An NRI of the second MSC's range (256-511), but a PLMN that doesn't match with osmo-bsc.cfg */
8957 var MSC_ConnHdlr vc_conn1;
8958 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8959 pars1.mscpool.rsl_idx := 0;
8960 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(260)), '99F999'O));
8961 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8962 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008963 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008964
8965 /* An NRI of the third MSC's range (512-767) and a matching PLMN gets directed by NRI. */
8966 var MSC_ConnHdlr vc_conn2;
8967 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8968 pars2.mscpool.rsl_idx := 1;
8969 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(555)), '00F110'O));
8970 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8971 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008972 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008973 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008974}
8975
8976/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by IMSI, which would be
8977 * round-robined to another MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
8978private function f_tc_mscpool_paging_imsi(charstring id) runs on MSC_ConnHdlr {
8979 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
8980 //cid_list := { cIl_allInBSS := ''O };
8981 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
8982 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
8983 var BSSAP_N_UNITDATA_req paging;
8984 var hexstring imsi := '001010000000123'H;
8985
8986 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8987
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008988 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008989 valueof(ts_BSSMAP_Paging(imsi, cid_list, omit, bssmap_chneed))));
8990 BSSAP.send(paging);
8991
8992 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
8993 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
8994 * channel number is picked here. */
8995 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
8996 f_rslem_register(0, new_chan_nr);
8997 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(imsi)));
8998 f_rslem_unregister(0, new_chan_nr);
8999
9000 /* Despite the round robin pointing at the second MSC ('roundrobin next 1'), the earlier Paging for the same IMSI
9001 * causes this Paging Response to go to the first MSC (bssap_idx := 0). */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02009002 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(valueof(ts_MI_IMSI_LV(imsi))) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009003 f_sleep(1.0);
9004}
9005testcase TC_mscpool_paging_and_response_imsi() runs on test_CT {
9006 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
9007 f_sleep(1.0);
9008
9009 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
9010 * second MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
9011 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
9012
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009013 f_ctrs_msc_init();
9014
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009015 var MSC_ConnHdlr vc_conn1;
9016 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9017 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009018 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
9019 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009020 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_imsi), pars1);
9021 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009022 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009023 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009024}
9025
9026/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by TMSI with an NRI value
9027 * that matches a different MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
9028private function f_tc_mscpool_paging_tmsi(charstring id) runs on MSC_ConnHdlr {
9029 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
9030 //cid_list := { cIl_allInBSS := ''O };
9031 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
9032 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
9033 var integer nri_v := 300; /* <-- second MSC's NRI */
Harald Weltebf397612021-01-14 20:39:46 +01009034 var octetstring tmsi := f_gen_tmsi(suffix := 0, nri_v := nri_v);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009035 var BSSAP_N_UNITDATA_req paging;
9036
9037 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9038
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009039 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009040 valueof(ts_BSSMAP_Paging('001010000000011'H, cid_list, tmsi, bssmap_chneed))));
9041 BSSAP.send(paging);
9042
9043 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
9044 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
9045 * channel number is picked here. */
9046 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
9047 f_rslem_register(0, new_chan_nr);
9048 RSL.receive(tr_RSL_PAGING_CMD(t_MI_TMSI(tmsi)));
9049 f_rslem_unregister(0, new_chan_nr);
9050
9051 /* Despite the NRI matching the second MSC (NRI from 'msc 1' in osmo-bsc.cfg) and round robin pointing at the
9052 * third MSC ('roundrobin next 2'), the earlier Paging for the same TMSI causes this Paging Response to go to
9053 * the first MSC (bssap_idx := 0). */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02009054 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 +02009055 f_sleep(1.0);
9056}
9057testcase TC_mscpool_paging_and_response_tmsi() runs on test_CT {
9058 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
9059 f_sleep(1.0);
9060
9061 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
9062 * third MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
9063 f_vty_transceive(BSCVTY, "mscpool roundrobin next 2");
9064
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009065 f_ctrs_msc_init();
9066
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009067 var MSC_ConnHdlr vc_conn1;
9068 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9069 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009070 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
9071 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009072 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_tmsi), pars1);
9073 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009074 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009075 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009076}
9077
9078/* For round-robin, skip an MSC that has 'no allow-attach' set. */
9079/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
9080 * just as well using only RSL. */
9081testcase TC_mscpool_no_allow_attach_round_robin() runs on test_CT {
9082
9083 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9084 f_sleep(1.0);
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00009085 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
9086 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009087
9088 /* Control which MSC gets chosen next by the round-robin, otherwise
9089 * would be randomly affected by which other tests ran before this. */
9090 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9091
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009092 f_ctrs_msc_init();
9093
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009094 var MSC_ConnHdlr vc_conn1;
9095 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9096 pars1.mscpool.rsl_idx := 0;
9097 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
9098 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9099 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009100 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009101
9102 var MSC_ConnHdlr vc_conn2;
9103 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
9104 pars2.mscpool.rsl_idx := 1;
9105 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9106 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9107 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009108 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009109
9110 var MSC_ConnHdlr vc_conn3;
9111 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
9112 pars3.mscpool.rsl_idx := 2;
9113 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))));
9114 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9115 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009116 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009117 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009118}
9119
9120/* An MSC that has 'no allow-attach' set should still serve subscribers that are already attached according to their
9121 * TMSI NRI. */
9122testcase TC_mscpool_no_allow_attach_valid_nri() runs on test_CT {
9123
9124 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9125 f_sleep(1.0);
9126
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00009127 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
9128 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
9129
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009130 /* Control which MSC gets chosen next by the round-robin, otherwise
9131 * would be randomly affected by which other tests ran before this. */
9132 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9133
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009134 f_ctrs_msc_init();
9135
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009136 /* Round robin points at msc 0, but the valid NRI directs to msc 1, even though msc 1 has 'no allow-attach'. */
9137 var MSC_ConnHdlr vc_conn1;
9138 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
9139 pars1.mscpool.rsl_idx := 0;
9140 /* An NRI of the second MSC's range (256-511) */
9141 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_TMSI_NRI_LV(260))));
9142 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9143 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009144 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009145
9146 var MSC_ConnHdlr vc_conn2;
9147 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 0);
9148 pars2.mscpool.rsl_idx := 1;
9149 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9150 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9151 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009152 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009153
9154 var MSC_ConnHdlr vc_conn3;
9155 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 2);
9156 pars3.mscpool.rsl_idx := 2;
9157 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000003'H))));
9158 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9159 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009160 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009161 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009162}
9163
Philipp Maier783681c2020-07-16 16:47:06 +02009164/* Allow/Deny emergency calls globally via VTY */
9165private function f_vty_allow_emerg_msc(boolean allow) runs on test_CT {
9166 f_vty_enter_cfg_msc(BSCVTY, 0);
9167 if (allow) {
9168 f_vty_transceive(BSCVTY, "allow-emergency allow");
9169 } else {
9170 f_vty_transceive(BSCVTY, "allow-emergency deny");
9171 }
9172 f_vty_transceive(BSCVTY, "exit");
9173 f_vty_transceive(BSCVTY, "exit");
9174}
9175
9176/* Allow/Deny emergency calls per BTS via VTY */
9177private function f_vty_allow_emerg_bts(boolean allow, integer bts_nr) runs on test_CT {
9178 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9179 if (allow) {
9180 f_vty_transceive(BSCVTY, "rach emergency call allowed 1");
9181 } else {
9182 f_vty_transceive(BSCVTY, "rach emergency call allowed 0");
9183 }
9184 f_vty_transceive(BSCVTY, "exit");
9185 f_vty_transceive(BSCVTY, "exit");
Neels Hofmeyrb6ed80c2020-10-12 22:52:39 +00009186 f_vty_transceive(BSCVTY, "exit");
Philipp Maier783681c2020-07-16 16:47:06 +02009187}
9188
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02009189/* Allow/Forbid Fast Return after SRVCC on a given BTS via VTY */
9190private function f_vty_allow_srvcc_fast_return(boolean allow, integer bts_nr) runs on test_CT {
9191 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9192 if (allow) {
9193 f_vty_transceive(BSCVTY, "srvcc fast-return allow");
9194 } else {
9195 f_vty_transceive(BSCVTY, "srvcc fast-return forbid");
9196 }
9197 f_vty_transceive(BSCVTY, "exit");
9198 f_vty_transceive(BSCVTY, "exit");
9199 f_vty_transceive(BSCVTY, "exit");
9200}
9201
Pau Espin Pedrol14475352021-07-22 15:48:16 +02009202/* Allow/Forbid TCH for signalling if SDCCH exhausted on a given BTS via VTY */
9203private function f_vty_allow_tch_for_signalling(boolean allow, integer bts_nr) runs on test_CT {
9204 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9205 if (allow) {
9206 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 1");
9207 } else {
9208 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 0");
9209 }
9210 f_vty_transceive(BSCVTY, "exit");
9211 f_vty_transceive(BSCVTY, "exit");
9212 f_vty_transceive(BSCVTY, "exit");
9213}
9214
Pau Espin Pedrol35609792023-01-03 16:56:59 +01009215/* Begin assignment procedure and send an EMERGENCY SETUP (RR) */
Philipp Maier783681c2020-07-16 16:47:06 +02009216private function f_assignment_emerg_setup() runs on MSC_ConnHdlr {
9217 var PDU_ML3_MS_NW emerg_setup;
9218 var octetstring emerg_setup_enc;
9219 var RSL_Message emerg_setup_data_ind;
9220
9221 f_establish_fully(omit, omit);
9222
9223 emerg_setup := valueof(ts_ML3_MO_CC_EMERG_SETUP(1, valueof(ts_Bcap_voice)));
9224 emerg_setup_enc := enc_PDU_ML3_MS_NW(emerg_setup);
9225 emerg_setup_data_ind := valueof(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), emerg_setup_enc));
9226
9227 RSL.send(emerg_setup_data_ind);
9228}
9229
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009230/* expect EmergencySetup on BSSAP after calling f_assignment_emerg_setup() */
9231private function f_assignment_emerg_setup_exp_bssap()
9232runs on MSC_ConnHdlr {
Philipp Maier783681c2020-07-16 16:47:06 +02009233 var PDU_BSSAP emerg_setup_data_ind_bssap;
9234 var PDU_ML3_MS_NW emerg_setup;
9235 timer T := 3.0;
9236
Philipp Maier783681c2020-07-16 16:47:06 +02009237 T.start;
9238 alt {
9239 [] BSSAP.receive(tr_BSSAP_DTAP) -> value emerg_setup_data_ind_bssap {
9240 emerg_setup := dec_PDU_ML3_MS_NW(emerg_setup_data_ind_bssap.pdu.dtap);
9241 if (not isbound(emerg_setup.msgs.cc.emergencySetup)) {
9242 setverdict(fail, "no emergency setup");
9243 }
9244 }
9245 [] BSSAP.receive {
9246 setverdict(fail, "unexpected BSSAP message!");
9247 }
9248 [] T.timeout {
9249 setverdict(fail, "timout waiting for EMERGENCY SETUP!");
9250 }
9251 }
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009252}
9253
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009254private function f_assignment_emerg_setup_voice()
9255runs on MSC_ConnHdlr {
9256 /* Go on with voice call assignment */
9257 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
9258 var PDU_BSSAP ass_cmd := f_gen_ass_req();
9259
9260 /* Below speechOrDataIndicator and codecList are copied from an emergency call captured during tests.
9261 * They seem a bit weird (AMR-WB, and the order differ between speechId_DataIndicator and the codecList), but
9262 * seems a good idea to see how osmo-bsc reacts to this. */
9263 ass_cmd.pdu.bssmap.assignmentRequest.channelType := {
9264 elementIdentifier := '0B'O, /* overwritten */
9265 lengthIndicator := 0, /* overwritten */
9266 speechOrDataIndicator := '0001'B, /* speech */
9267 spare1_4 := '0000'B,
9268 channelRateAndType := ChRate_TCHForH_Fpref,
9269 speechId_DataIndicator := 'c2918105'O
9270 };
9271 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({
9272 ts_CodecHR, ts_CodecAMR_WB, ts_CodecEFR, ts_CodecFR}));
9273
9274 f_rslem_dchan_queue_enable();
9275
9276 var ExpectCriteria mgcpcrit := {
9277 connid := omit,
9278 endpoint := omit,
9279 transid := omit
9280 };
9281 f_create_mgcp_expect(mgcpcrit);
9282
9283 BSSAP.send(ass_cmd);
9284
9285 var AssignmentState st := valueof(ts_AssignmentStateInit);
9286 st.voice_call := true;
9287 st.is_assignment := false;
9288 alt {
9289 [] as_modify(st);
9290 [] as_Media();
9291 [st.modify_done] BSSAP.receive(exp_compl) {
9292 setverdict(pass);
9293 }
9294 }
9295
9296 /* Voice call carries on ... */
9297 f_sleep(2.0);
9298}
9299
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009300/* Test if the EMERGENCY SETUP gets passed on to the MSC via A when EMERGENCY
9301 * CALLS are permitted by the BSC config. */
9302private function f_TC_assignment_emerg_setup_allow(charstring id) runs on MSC_ConnHdlr {
9303
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009304 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
9305 * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
9306 * another lchan. */
9307 g_pars.ra := f_rnd_ra_emerg();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009308 f_assignment_emerg_setup();
9309 f_assignment_emerg_setup_exp_bssap();
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009310 f_assignment_emerg_setup_voice();
Philipp Maier783681c2020-07-16 16:47:06 +02009311
9312 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009313 f_perform_clear();
Philipp Maier783681c2020-07-16 16:47:06 +02009314}
9315
9316/* Test if the EMERGENCY SETUP gets blocked by the BSC if EMERGENCY CALLS are
9317 * forbidden by the BSC config. */
9318private function f_TC_assignment_emerg_setup_deny(charstring id) runs on MSC_ConnHdlr {
9319 var PDU_BSSAP emerg_setup_data_ind_bssap;
9320 timer T := 3.0;
9321
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009322 f_assignment_emerg_setup();
Philipp Maier783681c2020-07-16 16:47:06 +02009323
9324 T.start;
9325 alt {
9326 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
9327 setverdict(pass);
9328 }
9329 [] RSL.receive {
9330 setverdict(fail, "unexpected RSL message!");
9331 }
9332 [] T.timeout {
9333 setverdict(fail, "timout waiting for RR CHANNEL RELEASE!");
9334 }
9335 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009336 BSSAP.receive(tr_BSSMAP_ClearRequest);
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01009337 f_perform_clear_no_rr_rel();
Philipp Maier783681c2020-07-16 16:47:06 +02009338}
9339
9340/* EMERGENCY CALL situation #1, allowed globally and by BTS */
9341testcase TC_assignment_emerg_setup_allow() runs on test_CT {
9342 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9343 var MSC_ConnHdlr vc_conn;
9344
9345 f_init(1, true);
9346 f_sleep(1.0);
9347
9348 f_vty_allow_emerg_msc(true);
9349 f_vty_allow_emerg_bts(true, 0);
9350 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
9351 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009352 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009353}
9354
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +01009355/* Test MO emergency call using MobileIdentity=IMEI (possible for emergency
9356 * calls from phones without SIM card).
9357 * 3GPP TS 24.008 section 10.5.1.4, OS#5849 */
9358testcase TC_assignment_emerg_setup_allow_imei() runs on test_CT {
9359 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9360 var MSC_ConnHdlr vc_conn;
9361
9362 /* Remove IMSI set by f_gen_test_hdlr_pars(), then IMEI will be used to place the call */
9363 pars.imsi := omit;
9364
9365 f_init(1, true);
9366 f_sleep(1.0);
9367
9368 f_vty_allow_emerg_msc(true);
9369 f_vty_allow_emerg_bts(true, 0);
9370 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
9371 vc_conn.done;
9372 f_shutdown_helper();
9373}
9374
Philipp Maier783681c2020-07-16 16:47:06 +02009375/* EMERGENCY CALL situation #2, forbidden globally but allowed by BTS */
9376testcase TC_assignment_emerg_setup_deny_msc() runs on test_CT {
9377 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9378 var MSC_ConnHdlr vc_conn;
9379
9380 f_init(1, true);
9381 f_sleep(1.0);
9382
9383 f_vty_allow_emerg_msc(false);
9384 f_vty_allow_emerg_bts(true, 0);
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009385 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx): */
9386 pars.ra := f_rnd_ra_emerg();
Philipp Maier783681c2020-07-16 16:47:06 +02009387 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9388 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009389 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009390}
9391
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009392/* EMERGENCY CALL situation #3, allowed globally but forbidden by BTS.
9393 * The RACH req (and hence CHAN RQD) indicate other than emergency call.
9394 * Hence BSC only learns about it being an emergency call later during call setup.
9395 * If interested in the ra="emergency call" + deny bts policy case,
9396 * see TC_chan_rqd_emerg_deny.
9397 */
Philipp Maier783681c2020-07-16 16:47:06 +02009398testcase TC_assignment_emerg_setup_deny_bts() runs on test_CT {
9399 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9400 var MSC_ConnHdlr vc_conn;
9401
9402 /* Note: This simulates a spec violation by the MS, correct MS
9403 * implementations would not try to establish an emergency call because
9404 * the system information tells in advance that emergency calls are
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009405 * not allowed */
Philipp Maier783681c2020-07-16 16:47:06 +02009406
9407 f_init(1, true);
9408 f_sleep(1.0);
9409
9410 f_vty_allow_emerg_msc(true);
9411 f_vty_allow_emerg_bts(false, 0);
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009412 /* Note: Here we implicitly leave default g_pars.ra which is different than "emergency call" */
Philipp Maier783681c2020-07-16 16:47:06 +02009413 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9414 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009415 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009416}
9417
Philipp Maier82812002020-08-13 18:48:27 +02009418/* Test what happens when an emergency call arrives while all TCH channels are
9419 * busy, the BSC is expected to terminate one call in favor of the incoming
9420 * emergency call */
9421testcase TC_emerg_premption() runs on test_CT {
9422 var ASP_RSL_Unitdata rsl_ud;
9423 var integer i;
9424 var integer chreq_total, chreq_nochan;
9425 var RSL_Message rx_rsl;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009426 var octetstring l3_payload := gen_l3_valid_payload();
Philipp Maier82812002020-08-13 18:48:27 +02009427
9428 f_init(1);
9429 f_sleep(1.0);
9430
9431 f_vty_allow_emerg_msc(true);
9432 f_vty_allow_emerg_bts(true, 0);
9433
9434 /* Fill up all channels on the BTS */
9435 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
9436 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
9437 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 +02009438 f_chreq_act_ack('33'O, i);
Philipp Maier82812002020-08-13 18:48:27 +02009439 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009440 IPA_RSL[0][0].clear;
Philipp Maier82812002020-08-13 18:48:27 +02009441 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
9442 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
9443
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009444 /* Send EST IND for the first TCH, so we get to test the RR release cause */
9445 var RslChannelNr first_tch := valueof(t_RslChanNr_Bm(1));
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009446 f_ipa_tx(ts_RSL_EST_IND(first_tch, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009447
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009448 /* Accept BSSAP conn, so we get to test the Clear Request cause */
9449 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009450 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009451 var integer sccp_conn_id := rx_c_ind.connectionId;
9452 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
9453
Philipp Maier82812002020-08-13 18:48:27 +02009454 /* Send Channel request for emegergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009455 f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
Philipp Maier82812002020-08-13 18:48:27 +02009456
9457 /* Expect the BSC to release one (the first) TCH/F on the BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009458 f_expect_chan_rel(first_tch, expect_rr_chan_rel := true, expect_rll_rel_req := false,
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009459 expect_rr_cause := GSM48_RR_CAUSE_PREMPTIVE_REL);
Philipp Maier82812002020-08-13 18:48:27 +02009460
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009461 /* Also expect a BSSMAP Clear Request with PREEMPTION */
9462 var BSSAP_N_DATA_ind rx_clear_req;
9463 const myBSSMAP_Cause preemption := GSM0808_CAUSE_PREEMPTION;
9464 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_clear_req;
9465 log("XXX ", rx_clear_req);
9466 if (rx_clear_req.userData.pdu.bssmap.clearRequest.cause.causeValue != int2bit(enum2int(preemption), 7)) {
9467 setverdict(fail, "BSSMAP Clear Request: expected cause PREEMPTION");
9468 }
9469
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009470 /* Expect the BSC to send activate/assign the channel for the emergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009471 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009472 if (first_tch != rx_rsl.ies[0].body.chan_nr) {
9473 setverdict(fail, "different TCH lchan activated than expected");
9474 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009475 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(first_tch, 33));
9476 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Philipp Maier104f4c02020-09-11 18:12:18 +02009477
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009478 /* complete the BSSMAP Clear to satisfy the conn leak check */
9479 BSSAP.send(ts_BSSAP_DATA_req(sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(preemption))));
9480 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearComplete)) {
9481 BSSAP.send(ts_BSSAP_DISC_req(sccp_conn_id, 0));
9482 }
9483
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009484 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009485}
9486
9487/* Hopping parameters per a timeslot */
Vadim Yanitskiybc6654a2020-09-13 01:27:40 +07009488private type record length(0..64) of GsmArfcn ArfcnList;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009489private type record FHParamsTs {
9490 boolean enabled,
9491 uint6_t hsn,
9492 uint6_t maio,
9493 ArfcnList ma
9494};
9495
9496/* Hopping parameters per a transceiver */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009497private type record FHParamsTrx {
Philipp Maier798d8952021-10-19 14:43:19 +02009498 GsmBandArfcn arfcn,
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009499 FHParamsTs ts[8]
9500};
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009501
9502/* Randomly generate the hopping parameters for the given timeslot numbers */
9503private function f_TC_fh_params_gen(template integer tr_tn := (1, 3, 5))
9504runs on test_CT return FHParamsTrx {
9505 var FHParamsTrx fhp;
9506
Philipp Maier798d8952021-10-19 14:43:19 +02009507 /* Generate a random ARFCN in the range of 0 - 3. This ARFCN will
9508 * fall in the GSM900 band. */
9509 fhp.arfcn.arfcn := f_rnd_int(3);
9510 fhp.arfcn.pcs := false;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009511
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009512 for (var integer tn := 0; tn < 8; tn := tn + 1) {
9513 if (not match(tn, tr_tn)) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009514 fhp.ts[tn].enabled := false;
9515 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009516 continue;
9517 }
9518
9519 /* Random HSN / MAIO values: 0..63 */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009520 fhp.ts[tn].hsn := f_rnd_int(64);
9521 fhp.ts[tn].maio := f_rnd_int(64);
9522 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009523
9524 /* Random Mobile Allocation (hopping channels) */
9525 var integer ma_len := 2 + f_rnd_int(9); /* 2..10 channels */
9526 var integer step := 3 + f_rnd_int(4); /* 3..6 stepping */
9527 for (var integer i := 1; i <= ma_len; i := i + 1) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009528 fhp.ts[tn].ma := fhp.ts[tn].ma & { i * step };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009529 }
9530
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009531 fhp.ts[tn].enabled := true;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009532 }
9533
9534 log("f_TC_fh_params_gen(): ", fhp);
9535 return fhp;
9536}
9537
9538/* Make sure that the given Channel Description IE matches the hopping configuration */
9539private function f_TC_fh_params_match_chan_desc(in FHParamsTrx fhp, in ChannelDescription cd)
9540{
9541 var template (present) ChannelDescription tr_cd;
9542 var template (present) MaioHsn tr_maio_hsn;
9543 var uint3_t tn := cd.chan_nr.tn;
9544
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009545 if (fhp.ts[tn].enabled) {
9546 tr_maio_hsn := tr_HsnMaio(fhp.ts[tn].hsn, fhp.ts[tn].maio);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009547 tr_cd := tr_ChanDescH1(cd.chan_nr, tr_maio_hsn);
9548 } else {
Philipp Maier798d8952021-10-19 14:43:19 +02009549 tr_cd := tr_ChanDescH0(cd.chan_nr, fhp.arfcn.arfcn);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009550 }
9551
9552 if (not match(cd, tr_cd)) {
9553 setverdict(fail, "Channel Description IE does not match: ",
9554 cd, " vs expected ", tr_cd);
9555 }
9556}
9557
9558/* Make sure that the given Mobile Allocation IE matches the hopping configuration */
9559private function f_TC_fh_params_match_ma(in FHParamsTrx fhp, uint3_t tn,
9560 in MobileAllocationLV ma)
9561{
9562 var template MobileAllocationLV tr_ma := f_TC_fh_params_gen_tr_ma(fhp, tn, ma);
9563
9564 if (not match(ma, tr_ma)) {
9565 setverdict(fail, "Mobile Allocation IE does not match (tn := ",
9566 tn, "): ", ma, " vs expected: ", tr_ma);
9567 } else {
9568 setverdict(pass);
9569 }
9570}
9571
9572private function f_TC_fh_params_gen_tr_ma(in FHParamsTrx fhp, uint3_t tn,
9573 in MobileAllocationLV ma)
9574return template MobileAllocationLV {
9575 /* Mobile Allocation IE is expected to be empty if hopping is not enabled */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009576 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009577 return { len := 0, ma := ''B };
9578 }
9579
9580 var bitstring full_mask := f_pad_bit(''B, 1024, '0'B);
9581 var bitstring slot_mask := f_pad_bit(''B, 1024, '0'B);
9582 var bitstring ma_mask := ''B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009583
9584 /* Compose the full bit-mask (all channels, up to 1024 entries) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009585 for (var integer i := 0; i < lengthof(fhp.ts); i := i + 1) {
9586 for (var integer j := 0; j < lengthof(fhp.ts[i].ma); j := j + 1) {
9587 if (full_mask[fhp.ts[i].ma[j]] == '1'B)
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009588 { continue; }
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009589 full_mask[fhp.ts[i].ma[j]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009590 }
9591 }
9592
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009593 /* Take ARFCN of the TRX itself into account */
Philipp Maier798d8952021-10-19 14:43:19 +02009594 full_mask[fhp.arfcn.arfcn] := '1'B;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009595
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009596 /* Compose a bit-mask for the given timeslot number */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009597 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9598 slot_mask[fhp.ts[tn].ma[i]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009599 }
9600
9601 /* Finally, compose the Mobile Allocation bit-mask */
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009602 for (var integer i := 1; i < lengthof(full_mask); i := i + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009603 if (full_mask[i] != '1'B)
9604 { continue; }
9605
9606 /* FIXME: ma_mask := ma_mask & slot_mask[i]; // triggers a bug in TITAN */
9607 if (slot_mask[i] == '1'B) {
9608 ma_mask := ma_mask & '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009609 } else {
9610 ma_mask := ma_mask & '0'B;
9611 }
9612 }
9613
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009614 /* ARFCN 0 (if present) goes to the last position of the bit-mask */
9615 if (full_mask[0] == '1'B) {
9616 /* FIXME: ma_mask := ma_mask & slot_mask[0]; // triggers a bug in TITAN */
9617 if (slot_mask[0] == '1'B) {
9618 ma_mask := ma_mask & '1'B;
9619 } else {
9620 ma_mask := ma_mask & '0'B;
9621 }
9622 }
9623
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009624 /* Ensure that ma_mask is octet-aligned */
Vadim Yanitskiy2aa02522020-09-06 14:05:23 +07009625 var integer ma_mask_len := (lengthof(ma_mask) + 8 - 1) / 8;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009626 ma_mask := f_pad_bit(ma_mask, ma_mask_len * 8, '0'B);
9627
9628 return { len := ma_mask_len, ma := ma_mask };
9629}
9630
Philipp Maier798d8952021-10-19 14:43:19 +02009631/* Configure the appropriate band for a given arfcn, exc */
9632private function f_TC_set_band_by_arfcn(integer bts_nr, GsmBandArfcn arfcn) runs on test_CT
9633{
9634 var charstring band;
9635 var GsmBandArfcn arfcn_ := valueof(ts_GsmBandArfcn(arfcn.arfcn, arfcn.pcs, false));
9636
9637 select (arfcn_) {
9638 case (tr_GsmBandArfcn((259..293), false, ?)) { band := "GSM450"; }
9639 case (tr_GsmBandArfcn((306..340), false, ?)) { band := "GSM480"; }
9640 case (tr_GsmBandArfcn((438..511), false, ?)) { band := "GSM750"; }
9641 case (tr_GsmBandArfcn((128..251), false, ?)) { band := "GSM850"; }
9642 case (tr_GsmBandArfcn((0..124), false, ?)) { band := "GSM900"; }
9643 case (tr_GsmBandArfcn((955..1023), false, ?)) { band := "GSM900"; }
9644 case (tr_GsmBandArfcn((512..885), false, ?)) { band := "DCS1800"; }
9645 case (tr_GsmBandArfcn((512..810), true, ?)) { band := "PCS1900"; }
9646 case else { return; }
9647 }
9648
9649 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9650 f_vty_transceive(BSCVTY, "band " & band);
9651 f_vty_transceive(BSCVTY, "end");
9652}
9653
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009654/* Configure the hopping parameters in accordance with the given record */
9655private function f_TC_fh_params_set(in FHParamsTrx fhp,
9656 uint8_t bts_nr := 0,
9657 uint8_t trx_nr := 0)
9658runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009659
9660 f_TC_set_band_by_arfcn(bts_nr, fhp.arfcn);
9661
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009662 /* Enter the configuration node for the given BTS/TRX numbers */
9663 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9664
Philipp Maier798d8952021-10-19 14:43:19 +02009665 f_vty_transceive(BSCVTY, "arfcn " & int2str(fhp.arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009666
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009667 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009668 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9669
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009670 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009671 f_vty_transceive(BSCVTY, "hopping enabled 0");
9672 f_vty_transceive(BSCVTY, "exit"); /* go back */
9673 continue;
9674 }
9675
9676 /* Configure HSN / MAIO values */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009677 f_vty_transceive(BSCVTY, "hopping sequence-number " & int2str(fhp.ts[tn].hsn));
9678 f_vty_transceive(BSCVTY, "hopping maio " & int2str(fhp.ts[tn].maio));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009679
9680 /* Configure the Mobile Allocation (hopping channels) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009681 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9682 f_vty_transceive(BSCVTY, "hopping arfcn add " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009683 }
9684
9685 f_vty_transceive(BSCVTY, "hopping enabled 1");
9686 f_vty_transceive(BSCVTY, "exit"); /* go back */
9687 }
9688
9689 f_vty_transceive(BSCVTY, "end");
9690}
9691
9692/* Disable frequency hopping on all timeslots */
9693private function f_TC_fh_params_unset(in FHParamsTrx fhp,
9694 uint8_t bts_nr := 0,
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009695 uint8_t trx_nr := 0,
Philipp Maier798d8952021-10-19 14:43:19 +02009696 GsmBandArfcn arfcn := {pcs := false, arfcn := 871})
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009697runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009698
9699 f_TC_set_band_by_arfcn(bts_nr, arfcn);
9700
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009701 /* Enter the configuration node for the given BTS/TRX numbers */
9702 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9703
Philipp Maier798d8952021-10-19 14:43:19 +02009704 f_vty_transceive(BSCVTY, "arfcn " & int2str(arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009705
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009706 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009707 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9708
9709 /* Delete all ARFCNs from the Mobile Allocation (if any) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009710 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9711 f_vty_transceive(BSCVTY, "hopping arfcn del " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009712 }
9713
9714 f_vty_transceive(BSCVTY, "hopping enabled 0");
9715 f_vty_transceive(BSCVTY, "exit"); /* go back */
9716 }
9717
9718 f_vty_transceive(BSCVTY, "end");
9719 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9720}
9721
9722/* Verify presence and correctness of the hopping parameters (HSN, MAIO)
9723 * in the Channel Identification IE of the RSL CHANnel ACTIVation message. */
9724testcase TC_fh_params_chan_activ() runs on test_CT {
9725 var FHParamsTrx fhp := f_TC_fh_params_gen();
9726 var RSL_Message rsl_msg;
9727 var RSL_IE_Body ie;
9728
9729 f_init_vty();
9730
9731 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9732 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9733
9734 f_init(1);
9735
9736 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9737 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009738 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9739 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009740
9741 /* Make sure that Channel Identification IE is present */
9742 if (not f_rsl_find_ie(rsl_msg, RSL_IE_CHAN_IDENT, ie)) {
9743 setverdict(fail, "RSL Channel Identification IE is absent");
9744 continue;
9745 }
9746
9747 /* Make sure that hopping parameters (HSN/MAIO) match */
9748 f_TC_fh_params_match_chan_desc(fhp, ie.chan_ident.ch_desc.v);
9749
9750 /* "Mobile Allocation shall be included but empty" - let's check this */
9751 if (ie.chan_ident.ma.v.len != 0) {
9752 setverdict(fail, "Mobile Allocation IE is not empty: ",
9753 ie.chan_ident.ma, ", despite it shall be");
9754 continue;
9755 }
9756 }
9757
9758 /* Disable frequency hopping */
9759 f_TC_fh_params_unset(fhp);
9760
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009761 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009762}
9763
9764/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Immediate Assignment */
9765testcase TC_fh_params_imm_ass() runs on test_CT {
9766 var FHParamsTrx fhp := f_TC_fh_params_gen();
9767 var RSL_Message rsl_msg;
9768 var RSL_IE_Body ie;
9769
9770 f_init_vty();
9771
9772 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9773 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9774
9775 f_init(1);
9776
9777 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9778 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009779 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9780 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009781
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009782 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9783 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009784
9785 /* Make sure that Full Immediate Assign Info IE is present */
9786 if (not f_rsl_find_ie(rsl_msg, RSL_IE_FULL_IMM_ASS_INFO, ie)) {
9787 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
9788 continue;
9789 }
9790
9791 /* Decode the actual Immediate Assignment message */
9792 var GsmRrMessage rr_msg := dec_GsmRrMessage(ie.full_imm_ass_info.payload);
9793 if (not match(rr_msg.header, t_RrHeader(IMMEDIATE_ASSIGNMENT, ?))) {
9794 setverdict(fail, "Failed to match Immediate Assignment: ", rr_msg);
9795 continue;
9796 }
9797
9798 /* Make sure that hopping parameters (HSN/MAIO) match */
9799 f_TC_fh_params_match_chan_desc(fhp, rr_msg.payload.imm_ass.chan_desc);
9800
9801 /* Make sure that the Mobile Allocation IE matches */
9802 f_TC_fh_params_match_ma(fhp, rr_msg.payload.imm_ass.chan_desc.chan_nr.tn,
9803 rr_msg.payload.imm_ass.mobile_allocation);
9804 }
9805
9806 /* Disable frequency hopping */
9807 f_TC_fh_params_unset(fhp);
Philipp Maier82812002020-08-13 18:48:27 +02009808
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009809 f_shutdown_helper();
Philipp Maier82812002020-08-13 18:48:27 +02009810}
9811
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009812/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Assignment Command */
9813testcase TC_fh_params_assignment_cmd() runs on test_CT {
9814 var FHParamsTrx fhp := f_TC_fh_params_gen();
9815 var RSL_Message rsl_msg;
9816 var RSL_IE_Body ie;
9817
9818 f_init_vty();
9819
9820 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9821 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9822
9823 f_init(1);
9824
9825 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02009826 vc_MGCP[0].stop;
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009827
9828 var template PDU_BSSAP ass_cmd := f_gen_ass_req();
9829 ass_cmd.pdu.bssmap.assignmentRequest.codecList := ts_BSSMAP_IE_CodecList({ts_CodecFR});
9830
9831 /* CS domain (TCH): 4 (TCH/F) + 2 (TCH/H) channels available
9832 * NOTE: only 3 SDCCH/4 channels are available on CCCH+SDCCH4+CBCH */
9833 for (var integer i := 0; i < 3; i := i + 1) {
9834 /* Establish a dedicated channel, so we can trigger (late) TCH assignment */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009835 var DchanTuple dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009836
9837 /* Send a BSSMAP Assignment Command, expect CHANnel ACTIVation */
9838 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009839 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009840
9841 /* ACKnowledge CHANnel ACTIVation, expect RSL DATA REQuest */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009842 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9843 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009844
9845 /* Make sure that L3 Information IE is present */
9846 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
9847 setverdict(fail, "RSL L3 Information IE is absent");
9848 continue;
9849 }
9850
9851 /* Decode the L3 message and make sure it is (RR) Assignment Command */
9852 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
9853 if (not match(l3_msg.header, t_RrL3Header(ASSIGNMENT_COMMAND))) {
9854 setverdict(fail, "Failed to match Assignment Command: ", l3_msg);
9855 continue;
9856 }
9857
9858 /* Make sure that hopping parameters (HSN/MAIO) match */
9859 var ChannelDescription chan_desc := l3_msg.payload.ass_cmd.chan_desc;
9860 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9861
9862 /* Make sure that Cell Channel Description IE is present if FH is enabled */
9863 if (chan_desc.h and not ispresent(l3_msg.payload.ass_cmd.cell_chan_desc)) {
Vadim Yanitskiy38d069d2020-09-02 17:18:57 +07009864 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009865 continue;
9866 }
9867
9868 /* Make sure that the Mobile Allocation IE matches (if present) */
9869 var boolean ma_present := ispresent(l3_msg.payload.ass_cmd.mobile_allocation);
9870 if (chan_desc.h and ma_present) {
9871 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
9872 l3_msg.payload.ass_cmd.mobile_allocation.v);
9873 } else if (chan_desc.h and not ma_present) {
9874 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
9875 continue;
9876 } else if (not chan_desc.h and ma_present) {
9877 setverdict(fail, "FH disabled, but Mobile Allocation IE is present");
9878 continue;
9879 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009880
9881 f_perform_clear_test_ct(dt);
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009882 }
9883
9884 /* Give the IUT some time to release all channels */
9885 f_sleep(3.0);
9886
9887 /* Disable frequency hopping */
9888 f_TC_fh_params_unset(fhp);
9889
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009890 f_shutdown_helper();
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009891}
9892
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009893/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Handover Command */
9894private function f_TC_fh_params_handover_cmd(in FHParamsTrx fhp)
9895runs on test_CT {
9896 var RSL_Message rsl_msg;
9897 var RSL_IE_Body ie;
9898 var DchanTuple dt;
9899
9900 /* Establish a dedicated channel, so we can trigger handover */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009901 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiyc18ff472021-11-18 20:15:37 +03009902 f_sleep(0.5);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009903
9904 /* Trigger handover from BTS0 to BTS1 */
9905 f_bts_0_cfg(BSCVTY, { "neighbor bts 1" });
9906 f_vty_handover(BSCVTY, 0, 0, dt.rsl_chan_nr, 1);
9907
9908 /* Expect RSL CHANnel ACTIVation on BTS1/TRX0/TS1 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009909 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx := {1, 0});
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009910
9911 /* ACKnowledge channel activation and expect (RR) Handover Command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009912 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33), idx := {1, 0});
9913 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009914
9915 /* Make sure that L3 Information IE is present */
9916 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
9917 setverdict(fail, "RSL L3 Information IE is absent");
9918 return;
9919 }
9920
9921 /* Decode the L3 message and make sure it is (RR) Handover Command */
9922 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
9923 if (not match(l3_msg.header, t_RrL3Header(HANDOVER_COMMAND))) {
9924 setverdict(fail, "Failed to match Handover Command: ", l3_msg);
9925 return;
9926 }
9927
9928 /* Make sure that we've got SDCCH/8 on TS1 (expected to be hopping) */
9929 var ChannelDescription chan_desc := l3_msg.payload.ho_cmd.chan_desc;
9930 if (not match(chan_desc.chan_nr, t_RslChanNr_SDCCH8(1, ?))) {
9931 setverdict(fail, "Unexpected channel number: ", chan_desc.chan_nr);
9932 return;
9933 }
9934
9935 /* Make sure that hopping parameters (HSN/MAIO) match */
9936 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9937
9938 /* Make sure that Cell Channel Description IE is present */
9939 if (not ispresent(l3_msg.payload.ho_cmd.cell_chan_desc)) {
9940 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
9941 return;
9942 }
9943
9944 /* Make sure that the Mobile Allocation (after time) IE is present and matches */
9945 var boolean ma_present := ispresent(l3_msg.payload.ho_cmd.mobile_allocation);
9946 if (ma_present) {
9947 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
9948 l3_msg.payload.ho_cmd.mobile_allocation.v);
9949 } else {
9950 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
9951 return;
9952 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009953
9954 f_perform_clear_test_ct(dt);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009955}
9956testcase TC_fh_params_handover_cmd() runs on test_CT {
9957 var FHParamsTrx fhp := f_TC_fh_params_gen();
9958
9959 f_init_vty();
9960
9961 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8 on BTS1/TRX0 */
9962 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
9963
9964 f_vty_transceive(BSCVTY, "timeslot 0");
9965 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
9966 f_vty_transceive(BSCVTY, "exit"); /* go back */
9967
9968 f_vty_transceive(BSCVTY, "timeslot 1");
9969 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8");
9970 f_vty_transceive(BSCVTY, "end"); /* we're done */
9971
9972 f_TC_fh_params_set(fhp, 1); /* Enable frequency hopping on BTS1 */
9973 f_vty_transceive(BSCVTY, "drop bts connection 1 oml");
9974
9975 f_init(2);
9976
9977 f_TC_fh_params_handover_cmd(fhp);
9978
9979 /* Disable frequency hopping on BTS1 */
9980 f_TC_fh_params_unset(fhp, 1);
9981
9982 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
9983 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
9984
9985 f_vty_transceive(BSCVTY, "timeslot 0");
9986 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
9987 f_vty_transceive(BSCVTY, "exit"); /* go back */
9988
9989 f_vty_transceive(BSCVTY, "timeslot 1");
9990 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
9991 f_vty_transceive(BSCVTY, "end"); /* we're done */
9992
9993 f_shutdown_helper();
9994}
9995
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009996/* Verify the hopping parameters in System Information Type 4 */
9997testcase TC_fh_params_si4_cbch() runs on test_CT {
9998 var FHParamsTrx fhp := f_TC_fh_params_gen(tr_tn := 1);
9999 var ASP_RSL_Unitdata rx_rsl_ud;
10000 timer T := 5.0;
10001
10002 f_init_vty();
10003
10004 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8+CBCH */
10005 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
10006
10007 f_vty_transceive(BSCVTY, "timeslot 0");
10008 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
10009 f_vty_transceive(BSCVTY, "exit"); /* go back */
10010
10011 f_vty_transceive(BSCVTY, "timeslot 1");
10012 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8+cbch");
10013 f_vty_transceive(BSCVTY, "end"); /* we're done */
10014
10015 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
10016 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
10017
10018 f_init(1);
10019
10020 T.start;
10021 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010022 [] 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 +070010023 var RSL_IE_Body ie := rx_rsl_ud.rsl.ies[2].body; /* FULL BCCH Information IE */
10024 var SystemInformation si := dec_SystemInformation(ie.other.payload);
10025
10026 /* Make sure that what we decoded is System Information Type 4 */
10027 if (si.header.message_type != SYSTEM_INFORMATION_TYPE_4) {
10028 setverdict(fail, "RSL FULL BCCH Information IE contains: ", si);
10029 repeat;
10030 }
10031
10032 /* Make sure that CBCH Channel Description IE is present */
10033 if (not ispresent(si.payload.si4.cbch_chan_desc)) {
10034 setverdict(fail, "CBCH Channel Description IE is absent");
10035 break;
10036 }
10037
10038 /* Finally, check the hopping parameters (HSN, MAIO) */
10039 var ChannelDescription chan_desc := si.payload.si4.cbch_chan_desc.v;
10040 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
10041
10042 /* 3GPP TS 44.018, section 9.1.36.2 "CBCH Mobile Allocation":
10043 * The CBCH Mobile Allocation IE *shall* be present if FH is enabled. */
10044 if (chan_desc.h and not ispresent(si.payload.si4.cbch_mobile_alloc)) {
10045 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
10046 break;
10047 } else if (chan_desc.h and ispresent(si.payload.si4.cbch_mobile_alloc)) {
10048 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
10049 si.payload.si4.cbch_mobile_alloc.v);
10050 }
10051 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010052 [] IPA_RSL[0][0].receive { repeat; }
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010053 [] T.timeout {
10054 setverdict(fail, "Timeout waiting for RSL BCCH INFOrmation (SI4)");
10055 }
10056 }
10057
10058 /* Disable frequency hopping */
10059 f_TC_fh_params_unset(fhp);
10060
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +070010061 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010062 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
10063
10064 f_vty_transceive(BSCVTY, "timeslot 0");
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +070010065 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010066 f_vty_transceive(BSCVTY, "exit"); /* go back */
10067
10068 f_vty_transceive(BSCVTY, "timeslot 1");
10069 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
10070 f_vty_transceive(BSCVTY, "end"); /* we're done */
10071
Vadim Yanitskiy21726312020-09-04 01:45:36 +070010072 f_shutdown_helper();
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010073}
10074
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010075template (value) PDU_BSSAP_LE ts_BSSMAP_LE_BSSLAP(template (value) BSSLAP_PDU bsslap)
10076 := ts_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, data := enc_BSSLAP_PDU(valueof(bsslap)));
10077
10078private function f_match_bsslap(PDU_BSSAP_LE got_bsslap_msg,
10079 template (present) BSSLAP_PDU expect_bsslap)
10080{
10081 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(got_bsslap_msg.pdu.bssmap.co_info.bsslap_apdu.data);
10082 if (not match(bsslap, expect_bsslap)) {
10083 log("EXPECTING BSSLAP: ", expect_bsslap);
10084 log("GOT BSSLAP: ", bsslap);
10085 setverdict(fail, "BSSLAP is not as expected");
10086 mtc.stop;
10087 }
10088 setverdict(pass);
10089}
10090
10091/* GAD: this is an Ellipsoid point with uncertainty circle, encoded as in 3GPP TS 23.032 §7.3.2. */
10092const octetstring gad_ell_point_unc_circle := '10b0646d0d5f6627'O;
10093
10094private function f_expect_bsslap(template (present) BSSLAP_PDU expect_rx_bsslap) runs on MSC_ConnHdlr {
10095 var PDU_BSSAP_LE rx_bsslap;
10096 BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap);
10097 f_match_bsslap(rx_bsslap, expect_rx_bsslap);
10098}
10099
10100/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10101 * Request on Lb interface. Either with or without the SMLC doing a BSSLAP TA Request. */
10102private function f_lcs_loc_req_for_active_ms(boolean do_ta_request := false) runs on MSC_ConnHdlr {
10103 f_sleep(1.0);
10104
10105 f_establish_fully(omit, omit);
10106 f_bssap_le_register_imsi(g_pars.imsi, omit);
10107
10108 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10109 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10110
10111 var PDU_BSSAP_LE plr;
10112 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10113
10114 if (not do_ta_request) {
10115 /* verify TA Layer 3 in APDU. First the APDU type (BSSLAP), then the BSSLAP data contents. */
10116 var template BSSMAP_LE_IE_APDU expect_apdu := tr_BSSMAP_LE_APDU(BSSMAP_LE_PROT_BSSLAP, ?);
10117 if (not match(plr.pdu.bssmap.perf_loc_req.bsslap_apdu, expect_apdu)) {
10118 log("EXPECTING BSSMAP-LE APDU IE ", expect_apdu);
10119 log("GOT BSSMAP-LE APDU IE ", plr.pdu.bssmap.perf_loc_req.bsslap_apdu);
10120 setverdict(fail, "BSSMAP-LE APDU IE is not as expected");
10121 mtc.stop;
10122 }
10123 var template BSSLAP_PDU expect_ta_layer3 := tr_BSSLAP_TA_Layer3(tr_BSSLAP_IE_TA(0));
10124 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(plr.pdu.bssmap.perf_loc_req.bsslap_apdu.data);
10125 if (not match(bsslap, expect_ta_layer3)) {
10126 log("EXPECTING BSSLAP TA Layer 3: ", expect_ta_layer3);
10127 log("GOT BSSLAP: ", bsslap);
10128 setverdict(fail, "BSSLAP is not as expected");
10129 mtc.stop;
10130 }
10131 /* OsmoBSC directly sent the TA as BSSLAP APDU in the BSSMAP-LE Perform Location Request to the SMLC. The SMLC
10132 * has no need to request the TA from the BSC and directly responds. */
10133 } else {
10134 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10135 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10136 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10137 }
10138
10139 /* SMLC got the TA from the BSC, now responds with geo information data. */
10140 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10141 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10142 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10143
10144 /* The LCS was using an active A-interface conn. It should still remain active after this. */
10145 f_mo_l3_transceive();
10146
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010147 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010148
10149 f_sleep(2.0);
10150 setverdict(pass);
10151}
10152
10153/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10154 * Request on Lb interface. Without the SMLC doing a BSSLAP TA Request. */
10155private function f_tc_lcs_loc_req_for_active_ms(charstring id) runs on MSC_ConnHdlr {
10156 f_lcs_loc_req_for_active_ms(false);
10157}
10158testcase TC_lcs_loc_req_for_active_ms() runs on test_CT {
10159 var MSC_ConnHdlr vc_conn;
10160 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10161
10162 f_init(1, true);
10163 f_sleep(1.0);
10164 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms), pars);
10165 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010166 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010167}
10168
10169/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10170 * Request on Lb interface. With the SMLC doing a BSSLAP TA Request. */
10171private function f_tc_lcs_loc_req_for_active_ms_ta_req(charstring id) runs on MSC_ConnHdlr {
10172 f_lcs_loc_req_for_active_ms(true);
10173}
10174testcase TC_lcs_loc_req_for_active_ms_ta_req() runs on test_CT {
10175 var MSC_ConnHdlr vc_conn;
10176 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10177
10178 f_init(1, true);
10179 f_sleep(1.0);
10180 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_ta_req), pars);
10181 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010182 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010183}
10184
10185/* Clear the A-interface conn only, without doing anything on Abis. Useful for LCS, for cases where there is only an A
10186 * conn without an active lchan. */
10187private function f_clear_A_conn() runs on MSC_ConnHdlr
10188{
10189 var BssmapCause cause := 0;
10190 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
10191 BSSAP.receive(tr_BSSMAP_ClearComplete);
10192 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
10193
10194 timer no_more_bssap := 5.0;
10195 no_more_bssap.start;
10196 alt {
10197 [] no_more_bssap.timeout { break; }
10198 [] BSSAP.receive(tr_BSSAP_BSSMAP) {
10199 setverdict(fail, "Expected no more BSSAP after Clear Complete");
10200 mtc.stop;
10201 }
10202 }
10203 setverdict(pass);
10204}
10205
10206/* Verify that the A-interface connection is still working, and then clear it, without doing anything on Abis. Useful
10207 * for LCS, for cases where there is only an A conn without an active lchan. */
10208private function f_verify_active_A_conn_and_clear() runs on MSC_ConnHdlr
10209{
10210 f_logp(BSCVTY, "f_verify_active_A_conn_and_clear: test A link, then clear");
10211
10212 /* When an lchan is active, we can send some L3 data from the BTS side and verify that it shows up on the other
10213 * side towards the MSC. When there is no lchan, this is not possible. To probe whether the A-interface
10214 * connection is still up, we need something that echos back on the A-interface. Another LCS request! */
10215 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10216 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10217 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10218
10219 /* Right, the Perform Location Request showed up on Lb, now we can clear the A conn. */
10220 f_clear_A_conn();
10221 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10222 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10223}
10224
10225/* With *no* active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10226 * Request on Lb interface. BSC will Page for the subscriber as soon as we (virtual SMLC) request the TA via BSSLAP.
10227 */
10228private function f_tc_lcs_loc_req_for_idle_ms(charstring id) runs on MSC_ConnHdlr {
10229 f_sleep(1.0);
10230
10231 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10232 f_bssap_le_register_imsi(g_pars.imsi, omit);
10233
10234 /* Register to receive the Paging Command */
10235 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10236 g_chan_nr := new_chan_nr;
10237 f_rslem_register(0, g_chan_nr);
10238
10239 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10240 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10241 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10242 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10243
10244 var PDU_BSSAP_LE plr;
10245 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10246
10247 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10248 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10249
10250 /* OsmoBSC needs to Page */
10251 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi)));
10252 f_logp(BSCVTY, "got Paging Command");
10253
10254 /* MS requests channel. Since the Paging was for LCS, the Paging Response does not trigger a Complete Layer 3 to
10255 * the MSC, and releases the lchan directly. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010256 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);
10257 f_expect_lchan_rel(RSL, RSL_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010258
10259 /* From the Paging Response, the TA is now known to the BSC, and it responds to the SMLC. */
10260
10261 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10262
10263 /* SMLC got the TA from the BSC, now responds with geo information data. */
10264 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10265 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10266
10267 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10268
10269 /* The lchan is gone, the A-interface conn was created for the LCS only.
10270 * Still it is clearly the MSC's job to decide whether to tear down the conn or not. */
10271 f_verify_active_A_conn_and_clear();
10272
10273 f_sleep(2.0);
10274 setverdict(pass);
10275}
10276testcase TC_lcs_loc_req_for_idle_ms() runs on test_CT {
10277 var MSC_ConnHdlr vc_conn;
10278 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10279
10280 f_init(1, true);
10281 f_sleep(1.0);
10282
10283 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10284 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10285
10286 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms), pars);
10287 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010288 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010289}
10290
10291/* With no active lchan, start BSSMAP Perform Location Request on A interface, but omit IMSI; expect failure response.
10292 */
10293private function f_tc_lcs_loc_req_no_subscriber(charstring id) runs on MSC_ConnHdlr {
10294 f_sleep(1.0);
10295
10296 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10297 f_bssap_le_register_imsi(g_pars.imsi, omit);
10298
10299 /* provoke an abort by omitting both IMSI and IMEI */
10300 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10301 valueof(ts_BSSMAP_Perform_Location_Request(omit,
10302 ts_CellId_CGI('262'H, '42'H, 23, 42)))));
10303 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10304
10305 /* BSC tells MSC about failure */
10306 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10307 locationEstimate := omit, positioningData := omit,
10308 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_DATA_MISSING_IN_REQ)));
10309
10310 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10311 f_verify_active_A_conn_and_clear();
10312
10313 f_sleep(2.0);
10314 setverdict(pass);
10315}
10316testcase TC_lcs_loc_req_no_subscriber() runs on test_CT {
10317 var MSC_ConnHdlr vc_conn;
10318 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10319
10320 f_init(1, true);
10321 f_sleep(1.0);
10322
10323 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10324 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10325
10326 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_no_subscriber), pars);
10327 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010328 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010329}
10330
10331/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10332 * BSSMAP-LE Perform Location Response (before or after sending a BSSLAP TA Request) */
10333private function f_lcs_loc_req_for_active_ms_le_timeout(boolean do_ta) runs on MSC_ConnHdlr {
10334 f_sleep(1.0);
10335
10336 f_establish_fully(omit, omit);
10337 f_bssap_le_register_imsi(g_pars.imsi, omit);
10338
10339 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10340 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10341
10342 var PDU_BSSAP_LE plr;
10343 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10344
10345 if (do_ta) {
10346 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10347 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10348 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10349 }
10350
10351 /* SMLC fails to respond, BSC runs into timeout */
10352 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_SYSTEM_FAILURE));
10353 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10354
10355 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10356 locationEstimate := omit, positioningData := omit,
10357 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_SYSTEM_FAILURE)));
10358
10359 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10360 f_verify_active_A_conn_and_clear();
10361
10362 f_sleep(2.0);
10363 setverdict(pass);
10364}
10365
10366/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10367 * BSSMAP-LE Perform Location Response, without sending a BSSLAP TA Request. */
10368private function f_tc_lcs_loc_req_for_active_ms_le_timeout(charstring id) runs on MSC_ConnHdlr {
10369 f_lcs_loc_req_for_active_ms_le_timeout(false);
10370}
10371
10372testcase TC_lcs_loc_req_for_active_ms_le_timeout() runs on test_CT {
10373 var MSC_ConnHdlr vc_conn;
10374 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10375
10376 f_init(1, true);
10377 f_sleep(1.0);
10378 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout), pars);
10379 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010380 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010381}
10382
10383/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10384 * BSSMAP-LE Perform Location Response, after sending a BSSLAP TA Request. */
10385private function f_tc_lcs_loc_req_for_active_ms_le_timeout2(charstring id) runs on MSC_ConnHdlr {
10386 f_lcs_loc_req_for_active_ms_le_timeout(true);
10387}
10388
10389testcase TC_lcs_loc_req_for_active_ms_le_timeout2() runs on test_CT {
10390 var MSC_ConnHdlr vc_conn;
10391 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10392
10393 f_init(1, true);
10394 f_sleep(1.0);
10395 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout2), pars);
10396 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010397 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010398}
10399
10400/* With *no* active lchan, start a Perform Location Request, expecting that the MS will be Paged. */
10401private function f_tc_lcs_loc_req_for_idle_ms_no_pag_resp(charstring id) runs on MSC_ConnHdlr {
10402 f_sleep(1.0);
10403
10404 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10405 f_bssap_le_register_imsi(g_pars.imsi, omit);
10406
10407 /* Register to receive the Paging Command */
10408 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10409 g_chan_nr := new_chan_nr;
10410 f_rslem_register(0, g_chan_nr);
10411
10412 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10413 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10414 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10415 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10416
10417 var PDU_BSSAP_LE plr;
10418 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10419
10420 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10421 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10422
10423 /* OsmoBSC needs to Page */
10424 var PDU_BSSAP_LE rx_bsslap;
10425 alt {
10426 [] RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi))) {
10427 f_logp(BSCVTY, "got Paging Command");
10428 repeat;
10429 }
10430 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10431 /* MS does not respond to Paging, TA Req runs into timeout. */
10432 f_match_bsslap(rx_bsslap, tr_BSSLAP_Abort(?));
10433 }
10434 }
10435
10436 /* SMLC responds with failure */
10437 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(omit, BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10438 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10439
10440 /* BSC tells MSC about failure */
10441 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10442 locationEstimate := omit, positioningData := omit,
10443 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_REQUEST_ABORTED)));
10444
10445 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10446 f_verify_active_A_conn_and_clear();
10447
10448 f_sleep(2.0);
10449 setverdict(pass);
10450}
10451testcase TC_lcs_loc_req_for_idle_ms_no_pag_resp() runs on test_CT {
10452 var MSC_ConnHdlr vc_conn;
10453 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10454
10455 f_init(1, true);
10456 f_sleep(1.0);
10457
10458 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10459 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10460
10461 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms_no_pag_resp), pars);
10462 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010463 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010464}
10465
10466/* During an ongoing Location Request, the MS sends a CM Service Request. Expect the same A-conn to be re-used / taken
10467 * over. */
10468private function f_tc_cm_service_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10469 f_sleep(1.0);
10470
10471 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10472 f_bssap_le_register_imsi(g_pars.imsi, omit);
10473
10474 /* Register to receive the Paging Command */
10475 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10476 g_chan_nr := new_chan_nr;
10477 f_rslem_register(0, g_chan_nr);
10478
10479 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10480 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10481 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10482 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10483
10484 var PDU_BSSAP_LE plr;
10485 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10486
10487 /* As the A-interface conn was established for LCS, the MS coincidentally decides to issue a CM Service Request
10488 * and establish Layer 3. It should use the existing A-interface conn. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010489 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 +020010490 do_clear := false, expect_bssmap_l3 := true);
10491
10492 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10493 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10494
10495 /* OsmoBSC already has an lchan, no need to Page, just returns the TA */
10496 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10497
10498 /* SMLC got the TA from the BSC, now responds with geo information data. */
10499 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10500 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10501 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10502
10503 /* The lchan should still exist, it was from a CM Service Request. */
10504 f_mo_l3_transceive();
10505
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010506 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010507
10508 f_sleep(2.0);
10509 setverdict(pass);
10510}
10511testcase TC_cm_service_during_lcs_loc_req() runs on test_CT {
10512 var MSC_ConnHdlr vc_conn;
10513 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10514
10515 f_init(1, true);
10516 f_sleep(1.0);
10517
10518 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10519 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10520
10521 vc_conn := f_start_handler(refers(f_tc_cm_service_during_lcs_loc_req), pars);
10522 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010523 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010524}
10525
10526/* During an ongoing Perform Location Request, do a Handover, an expect a BSSLAP Reset message from the BSC to indicate
10527 * the new lchan after handover. */
10528private function f_tc_ho_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10529 f_sleep(1.0);
10530
10531 f_establish_fully(omit, omit);
10532 f_bssap_le_register_imsi(g_pars.imsi, omit);
10533
10534 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10535 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10536
10537 var PDU_BSSAP_LE plr;
10538 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10539
10540 /* SMLC ponders the Location Request, in the meantime the BSC decides to handover */
10541 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
10542
10543 var HandoverState hs := {
10544 rr_ho_cmpl_seen := false,
10545 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +020010546 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010547 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010548 };
10549 /* issue hand-over command on VTY */
10550 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
10551 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
10552 f_rslem_suspend(RSL1_PROC);
10553
10554 /* From the MGW perspective, a handover is is characterized by
10555 * performing one MDCX operation with the MGW. So we expect to see
10556 * one more MDCX during handover. */
10557 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
10558
10559 alt {
10560 [] as_handover(hs);
10561 }
10562
10563 var PDU_BSSAP_LE rx_bsslap;
10564
10565 interleave {
10566 /* Expect the BSC to inform the MSC about the handover */
10567 [] BSSAP.receive(tr_BSSMAP_HandoverPerformed);
10568
10569 /* Expect the BSC to inform the SMLC about the handover */
10570 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10571 f_match_bsslap(rx_bsslap, tr_BSSLAP_Reset(BSSLAP_CAUSE_INTRA_BSS_HO));
10572 }
10573 }
10574
10575 /* SMLC now responds with geo information data. */
10576 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10577 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10578 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10579
10580 /* lchan still active */
10581 f_mo_l3_transceive(RSL1);
10582
10583 /* MSC decides it is done now. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010584 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010585
10586 f_sleep(2.0);
10587 setverdict(pass);
10588}
10589testcase TC_ho_during_lcs_loc_req() runs on test_CT {
10590 var MSC_ConnHdlr vc_conn;
10591 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10592
10593 f_init(2, true);
10594 f_sleep(1.0);
10595 vc_conn := f_start_handler(refers(f_tc_ho_during_lcs_loc_req), pars);
10596 vc_conn.done;
Oliver Smith39f53072022-10-27 14:44:04 +020010597 f_shutdown_helper(ho := true);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010598}
10599
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010600private function f_tc_emerg_call_and_lcs_loc_req(charstring id) runs on MSC_ConnHdlr
10601{
10602 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
10603 * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
10604 * another lchan. */
Pau Espin Pedrol1809bce2023-01-03 16:54:41 +010010605 g_pars.ra := f_rnd_ra_emerg();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010606 f_assignment_emerg_setup();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +010010607 f_assignment_emerg_setup_exp_bssap();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010608
10609 /* Here would usually be a CC Call Proceeding from the MSC, but what does the BSC care about DTAP. */
10610
10611 /* Do a Location Request in-between the CC call setup */
10612 f_bssap_le_register_imsi(g_pars.imsi, omit);
10613 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10614 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10615 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10616 /* SMLC got the TA from the BSC, now responds with geo information data. */
10617 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10618 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10619 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10620
Pau Espin Pedrol14076d32023-01-03 17:07:59 +010010621 f_assignment_emerg_setup_voice();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010622
10623 setverdict(pass);
10624 f_perform_clear();
10625}
10626
10627testcase TC_emerg_call_and_lcs_loc_req() runs on test_CT {
10628 var MSC_ConnHdlr vc_conn;
10629 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10630
10631 f_init(1, true);
10632 f_sleep(1.0);
10633 f_vty_allow_emerg_msc(true);
10634 f_vty_allow_emerg_bts(true, 0);
10635 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req), pars);
10636 vc_conn.done;
10637 f_shutdown_helper();
10638}
10639
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020010640private altstep no_bssmap_clear_req() runs on MSC_ConnHdlr {
10641 [] BSSAP.receive(tr_BSSMAP_ClearRequest) {
10642 setverdict(fail, "unexpected BSSMAP Clear Request");
10643 mtc.stop;
10644 }
10645}
10646
10647private type enumerated RslRel {
10648 RSLREL_REL_IND,
10649 RSLREL_CONN_FAIL
10650};
10651
10652private function f_emerg_call_and_lcs_loc_req_early_lchan_release(RslRel rsl_rel) runs on MSC_ConnHdlr
10653{
10654 g_pars.ra := f_rnd_ra_emerg();
10655 f_assignment_emerg_setup();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +010010656 f_assignment_emerg_setup_exp_bssap();
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020010657
10658 /* Start a Location Request to locate the emergency */
10659 f_bssap_le_register_imsi(g_pars.imsi, omit);
10660 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10661 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10662 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10663
10664 /* 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
10665 * do a Clear Command when the Location Response arrives. */
10666 activate(no_bssmap_clear_req());
10667
10668 /* the lchan gets interrupted while the Location Request has no response */
10669 select (rsl_rel) {
10670 case (RSLREL_REL_IND) {
10671 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
10672 f_expect_lchan_rel(RSL, RSL_PROC);
10673 }
10674 case (RSLREL_CONN_FAIL) {
10675 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
10676 }
10677 case else {
10678 setverdict(fail, "Unknown RslRel type");
10679 mtc.stop;
10680 }
10681 }
10682
10683 /* Still expect the Location Response to find its way to the MSC. */
10684 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10685 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10686 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10687
10688 setverdict(pass);
10689
10690 select (rsl_rel) {
10691 case (RSLREL_REL_IND) {
10692 f_perform_clear_no_lchan();
10693 }
10694 case (RSLREL_CONN_FAIL) {
10695 f_perform_clear();
10696 }
10697 }
10698}
10699
10700private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind(charstring id) runs on MSC_ConnHdlr
10701{
10702 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_REL_IND);
10703}
10704
10705testcase TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() runs on test_CT {
10706 var MSC_ConnHdlr vc_conn;
10707 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10708
10709 f_init(1, true);
10710 f_sleep(1.0);
10711 f_vty_allow_emerg_msc(true);
10712 f_vty_allow_emerg_bts(true, 0);
10713 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind), pars);
10714 vc_conn.done;
10715 f_shutdown_helper();
10716}
10717
10718private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail(charstring id) runs on MSC_ConnHdlr
10719{
10720 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_CONN_FAIL);
10721}
10722
10723testcase TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() runs on test_CT {
10724 var MSC_ConnHdlr vc_conn;
10725 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10726
10727 f_init(1, true);
10728 f_sleep(1.0);
10729 f_vty_allow_emerg_msc(true);
10730 f_vty_allow_emerg_bts(true, 0);
10731 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail), pars);
10732 vc_conn.done;
10733 f_shutdown_helper();
10734}
10735
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010736/* Attempt Complete Layer 3 without any MSC available (OS#4832) */
10737private function f_tc_no_msc(charstring id) runs on MSC_ConnHdlr {
10738 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10739
10740 /* Also disable attach for the single connected MSC */
10741 f_vty_msc_allow_attach(BSCVTY, { false });
10742
10743 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) ));
10744 f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
10745
10746 /* No MSC is found, expecting a proper release on RSL */
10747 interleave {
10748 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
10749 f_logp(BSCVTY, "Got RSL RR Release");
10750 }
10751 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
10752 f_logp(BSCVTY, "Got RSL Deact SACCH");
10753 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020010754 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010755 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
10756 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020010757 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010758 }
10759 }
10760 setverdict(pass);
10761}
10762testcase TC_no_msc() runs on test_CT {
10763
10764 f_init(1, true);
10765 f_sleep(1.0);
10766 var MSC_ConnHdlr vc_conn;
10767 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10768
10769 f_ctrs_bsc_init(counternames_bsc_mscpool);
10770
10771 vc_conn := f_start_handler(refers(f_tc_no_msc), pars);
10772 vc_conn.done;
10773
10774 f_ctrs_bsc_add("mscpool:subscr:no_msc");
10775 f_ctrs_bsc_verify();
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010776 f_shutdown_helper();
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010777}
10778
Harald Welte0ea2d5e2018-04-07 21:40:29 +020010779/* Dyn PDCH todo:
10780 * activate OSMO as TCH/F
10781 * activate OSMO as TCH/H
10782 * does the BSC-located PCU socket get the updated INFO?
10783 * what if no PCU is connected at the time?
10784 * is the info correct on delayed PCU (re)connect?
10785 */
Harald Welte94e0c342018-04-07 11:33:23 +020010786
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010787private function f_TC_refuse_mode_modif_to_vamos(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +020010788 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020010789 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010790
10791 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
10792 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
10793 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
10794 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
10795 g_pars.ass_codec_list.codecElements[0];
10796 if (isvalue(g_pars.expect_mr_s0_s7)) {
10797 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
10798 g_pars.expect_mr_s0_s7;
10799 }
10800 }
10801 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
10802 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
10803 log("expecting ASS COMPL like this: ", exp_compl);
10804
10805 f_establish_fully(ass_cmd, exp_compl);
10806
Neels Hofmeyr8746b0d2021-06-01 17:25:39 +020010807 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 +000010808
10809 var RSL_Message rsl;
10810
10811 timer T := 5.0;
10812 T.start;
10813 alt {
10814 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
10815 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
10816 log("Rx L3 from net: ", l3);
10817 if (ischosen(l3.msgs.rrm.channelModeModify)) {
10818 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
10819 mtc.stop;
10820 }
10821 }
10822 [] RSL.receive(tr_RSL_MODE_MODIFY_REQ(g_chan_nr, ?)) -> value rsl {
10823 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
10824 mtc.stop;
10825 }
10826 [] T.timeout {
10827 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related Mode Modify should happen. */
10828 setverdict(pass);
10829 }
10830 }
10831 T.stop;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010832
10833 f_perform_clear();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010834}
10835
10836/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel Mode Modify to VAMOS mode is refused by
10837 * osmo-bsc. */
10838testcase TC_refuse_mode_modif_to_vamos() runs on test_CT {
10839 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10840 var MSC_ConnHdlr vc_conn;
10841
10842 f_init(1, true);
10843 f_sleep(1.0);
10844
10845 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10846 vc_conn := f_start_handler(refers(f_TC_refuse_mode_modif_to_vamos), pars);
10847 vc_conn.done;
10848 f_shutdown_helper();
10849}
10850
10851/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel activation to VAMOS mode is refused by osmo-bsc.
10852 */
10853testcase TC_refuse_chan_act_to_vamos() runs on test_CT {
10854 f_init_vty();
10855
10856 f_init(1, false);
10857 f_sleep(1.0);
10858
10859 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 activate-vamos fr");
10860
10861 var ASP_RSL_Unitdata rx_rsl_ud;
10862 timer T := 5.0;
10863
10864 T.start;
10865 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010866 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(?, IPAC_PROTO_RSL_TRX0)) -> value rx_rsl_ud {
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010867 if (rx_rsl_ud.rsl.msg_type == RSL_MT_CHAN_ACTIV) {
10868 T.stop;
10869 setverdict(fail, "CHANnel ACTivate in VAMOS mode succeeded even though BTS does not support VAMOS");
10870 mtc.stop;
10871 }
10872 repeat;
10873 }
10874 [] T.timeout {
10875 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related CHANnel ACTivate should happen. */
10876 setverdict(pass);
10877 }
10878 }
10879}
10880
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010881private function f_TC_reassignment_codec(charstring id) runs on MSC_ConnHdlr {
10882 /* First fully set up a speech lchan */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010883 f_assignment_codec(id, do_perform_clear := false);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010884
10885 /* Trigger re-assignment to another lchan */
10886 var AssignmentState assignment_st := valueof(ts_AssignmentStateInit);
10887
10888 /* Re-Assignment should tell the MGW endpoint the new lchan's RTP address and port, so expecting to see exactly
10889 * one MDCX on MGCP. */
10890 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].mdcx_seen_exp + 1;
10891
10892 /* The new lchan will see all-new IPAC_CRCX and IPAC_MDCX messages telling the BTS the same RTP address and port
10893 * as the old lchan used. */
10894 g_media.bts.ipa_crcx_seen := false;
10895 g_media.bts.ipa_mdcx_seen := false;
10896
10897 /* Send different BTS side RTP port number for the new lchan */
10898 g_media.bts.bts.port_nr := 4223;
10899
10900 f_rslem_register(0, valueof(ts_RslChanNr_Bm(2))); /* <-- FIXME: can we somehow infer the timeslot that will be used? */
10901
10902 /* Trigger re-assignment. */
10903 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot " & int2str(g_chan_nr.tn) & " sub-slot 0 assignment");
10904
10905 timer T := 5.0;
10906 T.start;
10907 alt {
10908 [] as_assignment(assignment_st);
10909 [] as_Media();
10910 [] T.timeout {
10911 break;
10912 }
10913 }
10914
10915 if (not assignment_st.assignment_done) {
10916 setverdict(fail, "Assignment did not complete");
10917 mtc.stop;
10918 }
10919
10920 f_check_mgcp_expectations()
10921 setverdict(pass);
10922
10923 f_sleep(2.0);
10924 log("show lchan summary: ", f_vty_transceive_ret(BSCVTY, "show lchan summary"));
10925
10926 /* Instruct BSC to clear channel */
10927 var BssmapCause cause := 0;
10928 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
10929 interleave {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010930 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {}
10931 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020010932 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010933 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020010934 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010935 }
10936 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
10937 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
10938 }
10939 }
Neels Hofmeyr40a45d12021-09-23 22:57:12 +020010940 f_expect_dlcx_conns();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010941
10942 f_sleep(0.5);
10943}
10944
10945testcase TC_reassignment_fr() runs on test_CT {
10946 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10947 var MSC_ConnHdlr vc_conn;
10948
10949 f_init(1, true);
10950 f_sleep(1.0);
10951
Neels Hofmeyrac432fa2021-11-02 16:45:56 +010010952 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010953
10954 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10955 vc_conn := f_start_handler(refers(f_TC_reassignment_codec), pars);
10956 vc_conn.done;
10957
10958 /* from f_establish_fully() */
10959 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
10960 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
10961 /* from re-assignment */
10962 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
10963 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
10964 f_ctrs_bsc_and_bts_verify();
10965 f_shutdown_helper();
10966}
10967
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010968const charstring REEST_LOST_CONNECTION := "REEST_LOST_CONNECTION";
10969const charstring REEST_CLEAR := "REEST_CLEAR";
10970const charstring REEST_CLEAR_DONE := "REEST_CLEAR_DONE";
10971
10972/* CM Re-Establishment, 3GPP TS 24.008 4.5.1.6.
10973 * The MS <-> BTS loses radio connection, MS shows up on second BTS and asks for CM Re-Establishment.
10974 * BSC should establish a separate A conn for the same MS, the original A conn is then cleared by
10975 * the MSC as the CM Re-Establishment is handled.
10976 *
10977 * MS bts0 bts1 bsc msc test-component
10978 * |<----->|<----------------->|<-0-->| _1 Establish channel on bts 0
10979 * | | _1 wait a bit, to settle down
10980 * |<-x x--| | _1 "lose connection"
10981 * | | REEST_LOST_CONNECTION
10982 * |----------------->|------->|--1-->| _2 new A-conn: Chan Rqd, Imm Ass, Compl L3 with CM Re-Establishment Req
10983 * | | REEST_CLEAR
10984 * | |<-0---| _1 Clear Command on first A-conn
10985 * | |--0-->| _1 Clear Complete
10986 * | |<----------------->| | _1 Release first channel
10987 * | | REEST_CLEAR_DONE
10988 * |<-----------------|<-------|<-1---| _2 Chan Activ, Assignment Command
10989 * |<-----------------|<-------|<-1---| _2 Clear Command, Release
10990 *
10991 */
10992private function f_tc_cm_reestablishment_1(charstring id) runs on MSC_ConnHdlr {
10993 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
10994 var PDU_BSSAP ass_cmd := f_gen_ass_req();
10995
10996 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
10997 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10998
10999 f_establish_fully(ass_cmd, exp_compl);
11000
11001 /* The original channel loses connection, MS attemts CM Re-Establishment on another cell, see
11002 * f_tc_cm_reestablishment_2(). This established channel stays active until MSC sends a Clear Command. The time
11003 * when exactly that happens is determined by f_tc_cm_reestablishment_2(). */
11004 f_sleep(2.0);
11005 COORD.send(REEST_LOST_CONNECTION);
11006
11007 alt {
11008 [] COORD.receive(REEST_CLEAR);
11009 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
11010 setverdict(fail, "Unexpected channel release");
11011 mtc.stop;
11012 }
11013 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
11014 setverdict(fail, "Unexpected channel release");
11015 mtc.stop;
11016 }
11017 }
11018 f_perform_clear()
Neels Hofmeyr969abd02021-09-23 22:24:08 +020011019 f_create_mgcp_delete_ep(g_media.mgcp_ep);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011020 COORD.send(REEST_CLEAR_DONE);
11021}
11022
11023private function f_tc_cm_reestablishment_2(charstring id) runs on MSC_ConnHdlr {
11024 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
11025
11026 /* The MS lost the connection on the first channel, now establishes another one */
11027 COORD.receive(REEST_LOST_CONNECTION);
11028
11029 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
11030 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REESTABL_REQ(mi));
11031 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
11032
11033 f_create_bssmap_exp(l3_enc);
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011034 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 +020011035 BSSAP.receive(tr_BSSMAP_ComplL3(l3_enc));
11036
11037 /* MSC got the CM Re-Establishment request and first off clears the previous conn. */
11038 COORD.send(REEST_CLEAR);
11039 COORD.receive(REEST_CLEAR_DONE);
11040
11041 f_sleep(2.0);
11042
11043 /* Answer the CM Re-Establishment with an Assignment Command. */
11044 var template PDU_BSSAP expect_assignment_compl := f_gen_exp_compl();
11045 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11046 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11047 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11048
11049 var AssignmentState st := valueof(ts_AssignmentStateInit);
11050 st.voice_call := true;
11051 st.is_assignment := true;
11052
11053 var ExpectCriteria mgcpcrit := {
11054 connid := omit,
11055 endpoint := omit,
11056 transid := omit
11057 };
11058 f_create_mgcp_expect(mgcpcrit);
11059
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011060 f_rslem_dchan_queue_enable(RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011061
11062 BSSAP.send(ass_cmd);
11063
11064 var PDU_BSSAP bssap;
11065
11066 alt {
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011067 [] as_assignment(st, rsl_pt := RSL1, rsl_proc_pt := RSL1_PROC);
11068 [] as_Media_ipacc(RSL1, RSL2);
11069 [] as_Media_mgw();
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011070 [st.assignment_done] BSSAP.receive(expect_assignment_compl) {
11071 break;
11072 }
11073 }
11074
11075 f_sleep(3.0);
11076
11077 f_logp(BSCVTY, "f_tc_cm_reestablishment_2 clearing");
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011078 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011079}
11080
11081testcase TC_cm_reestablishment() runs on test_CT {
11082 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
11083 var MSC_ConnHdlr vc_conn1;
11084
11085 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
11086 var MSC_ConnHdlr vc_conn2;
11087 pars2.imsi := pars1.imsi;
11088 pars2.media_nr := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011089 pars2.expect_tsc := c_BtsParams[1].tsc;
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011090
11091 f_init(2, true, guard_timeout := 40.0);
11092 f_sleep(1.0);
11093
11094 vc_conn1 := f_start_handler_create(pars1);
11095 vc_conn2 := f_start_handler_create(pars2);
11096 connect(vc_conn1:COORD, vc_conn2:COORD);
11097 f_start_handler_run(vc_conn1, refers(f_tc_cm_reestablishment_1), pars1);
11098 f_start_handler_run(vc_conn2, refers(f_tc_cm_reestablishment_2), pars2);
11099 vc_conn1.done;
11100 vc_conn2.done;
11101
11102 f_shutdown_helper();
11103}
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000011104
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011105function f_exp_ipa_rx_nonfatal(template (present) RSL_Message t_rx,
11106 boolean ignore_other_rx := true,
11107 BtsTrxIdx idx := {0, 0},
11108 float Tval := 2.0)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011109runs on test_CT return template (omit) RSL_Message {
11110 var ASP_RSL_Unitdata rx_rsl_ud;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011111 timer T := Tval;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011112
11113 T.start;
11114 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011115 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011116 T.stop;
11117 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011118 [ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
11119 [not ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011120 log("f_exp_ipa_rx_nonfatal(): Got different message than ", t_rx);
11121 T.stop;
11122 return omit;
11123 }
11124 [] T.timeout {
11125 return omit;
11126 }
11127 }
11128 return rx_rsl_ud.rsl;
11129}
11130
11131private function f_vty_set_imm_ass(TELNETasp_PT pt, BtsNr bts_nr := 0, charstring imm_ass_setting := "post-chan-ack") {
11132 f_vty_enter_cfg_bts(pt, bts_nr);
11133 f_vty_transceive(pt, "immediate-assignment " & imm_ass_setting);
11134 f_vty_transceive(pt, "exit");
11135 f_vty_transceive(pt, "exit");
11136 f_vty_transceive(pt, "exit");
11137}
11138
11139private function f_verify_imm_ass(RSL_Message imm_ass, template uint8_t ra := ?, template GsmFrameNumber fn := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +030011140 template (present) RslChannelNr chan_nr := ?,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011141 template (present) uint12_t arfcn := ?,
11142 template (present) uint3_t tsc := ?)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011143{
11144 var RSL_IE_Body full_imm_ass_info;
11145 if (not f_rsl_find_ie(imm_ass, RSL_IE_FULL_IMM_ASS_INFO, full_imm_ass_info)) {
11146 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
11147 mtc.stop;
11148 }
11149
11150 var GsmRrMessage rr_imm_ass := dec_GsmRrMessage(full_imm_ass_info.full_imm_ass_info.payload);
11151 var template GsmRrMessage expect_imm_ass := tr_IMM_ASS(ra := ra,
11152 fn := fn,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011153 ch_desc := tr_ChanDescH0(chan_nr, arfcn, tsc),
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011154 page_mode := ?);
11155 if (not match(rr_imm_ass, expect_imm_ass)) {
11156 log("Error: expected ", expect_imm_ass, " got ", rr_imm_ass);
11157 setverdict(fail, "Failed to match Immediate Assignment");
11158 mtc.stop;
11159 }
11160}
11161
11162testcase TC_imm_ass_post_chan_ack() runs on test_CT {
11163 var RSL_Message chan_act;
11164 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011165 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011166
11167 f_init(1, false);
11168 f_sleep(1.0);
11169
11170 /* (should be the default anyway, just to make things clear) */
11171 f_vty_set_imm_ass(BSCVTY, 0, "post-chan-ack");
11172
11173 /* RA containing reason=LU */
11174 var GsmFrameNumber fn := 2342;
11175 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011176 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011177
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011178 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011179
11180 /* First send the Chan Act ACK */
11181 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011182 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011183 var RSL_IE_Body chan_ident_ie;
11184 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11185 setverdict(fail, "RSL Channel Identification IE is absent");
11186 mtc.stop;
11187 }
11188
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011189 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn + 10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011190
11191 /* Then expect the Immediate Assignment, after we ACKed the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011192 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011193
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011194 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11195 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011196
11197 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011198 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011199
11200 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011201 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011202 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011203 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11204
11205 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011206 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011207 f_shutdown_helper();
11208}
11209
11210testcase TC_imm_ass_pre_chan_ack() runs on test_CT {
11211 var RSL_Message chan_act;
11212 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011213 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011214
11215 f_init(1, false);
11216 f_sleep(1.0);
11217
11218 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11219
11220 /* RA containing reason=LU */
11221 var GsmFrameNumber fn := 2342;
11222 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011223 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011224
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011225 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011226 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011227 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011228 var RSL_IE_Body chan_ident_ie;
11229 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11230 setverdict(fail, "RSL Channel Identification IE is absent");
11231 mtc.stop;
11232 }
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011233
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011234 /* (set bts 0 cfg back to default) */
11235 f_vty_set_imm_ass(BSCVTY);
11236
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011237 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011238 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011239 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11240 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011241
11242 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011243 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011244
11245 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011246 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011247
11248 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011249 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011250 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011251 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11252
11253 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011254 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011255 f_shutdown_helper();
11256}
11257
Neels Hofmeyr23158742021-09-07 19:08:07 +020011258testcase TC_imm_ass_pre_ts_ack() runs on test_CT {
11259 var RSL_Message chan_act;
11260 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011261 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyr23158742021-09-07 19:08:07 +020011262
11263 f_init(1, false);
11264 f_sleep(1.0);
11265
11266 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11267
11268 /* RA containing reason=LU */
11269 var GsmFrameNumber fn := 2342;
11270 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011271 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011272
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011273 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011274 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011275 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr23158742021-09-07 19:08:07 +020011276 var RSL_IE_Body chan_ident_ie;
11277 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11278 setverdict(fail, "RSL Channel Identification IE is absent");
11279 mtc.stop;
11280 }
11281
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011282 /* (set bts 0 cfg back to default) */
11283 f_vty_set_imm_ass(BSCVTY);
11284
Neels Hofmeyr23158742021-09-07 19:08:07 +020011285 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011286 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011287 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11288 chan_ident_ie.chan_ident.ch_desc.v.tsc);
11289
11290 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011291 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011292
11293 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011294 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011295
11296 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011297 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011298 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr23158742021-09-07 19:08:07 +020011299 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11300
11301 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011302 f_perform_clear_test_ct(dt);
Neels Hofmeyr23158742021-09-07 19:08:07 +020011303 f_shutdown_helper();
11304}
11305
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011306testcase TC_imm_ass_pre_chan_ack_dyn_ts() runs on test_CT {
11307 /* change Timeslot 6 before f_init() starts RSL */
11308 f_init_vty();
11309 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11310 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11311
11312 f_init(1, false);
11313 f_sleep(1.0);
11314
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011315 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011316 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11317 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011318 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11319 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011320
11321 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11322 f_ts_set_chcomb(0, 0, 6, "PDCH");
11323
11324 /* block all static timeslots so that the dyn TS will be used */
11325 f_disable_all_tch_f();
11326 f_disable_all_tch_h();
11327 f_disable_all_sdcch();
11328
11329 var RSL_Message chan_act;
11330 var RSL_Message imm_ass;
11331
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011332 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11333
11334 /* RA containing reason=LU */
11335 var GsmFrameNumber fn := 2342;
11336 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011337 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011338
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011339 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011340 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
11341 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011342
11343 /* Now activation as SDCCH8 */
11344 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011345 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011346
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011347 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011348 var RSL_IE_Body chan_ident_ie;
11349 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11350 setverdict(fail, "RSL Channel Identification IE is absent");
11351 mtc.stop;
11352 }
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011353
11354 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011355 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011356 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11357 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011358
11359 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011360 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011361
11362 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011363 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011364
11365 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011366 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011367 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011368 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11369
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011370 /* (set bts 0 cfg back to default) */
11371 f_vty_set_imm_ass(BSCVTY);
11372
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011373 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011374 f_perform_clear_test_ct(dt);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011375 f_shutdown_helper();
11376}
11377
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011378testcase TC_imm_ass_pre_ts_ack_dyn_ts() runs on test_CT {
11379 /* change Timeslot 6 before f_init() starts RSL */
11380 f_init_vty();
11381 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11382 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11383
11384 f_init(1, false);
11385 f_sleep(1.0);
11386
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011387 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011388 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11389 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011390 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11391 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011392
11393 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11394 f_ts_set_chcomb(0, 0, 6, "PDCH");
11395
11396 /* block all static timeslots so that the dyn TS will be used */
11397 f_disable_all_tch_f();
11398 f_disable_all_tch_h();
11399 f_disable_all_sdcch();
11400
11401 var RSL_Message chan_act;
11402 var RSL_Message imm_ass;
11403
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011404 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11405
11406 /* RA containing reason=LU */
11407 var GsmFrameNumber fn := 2342;
11408 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011409 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011410
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011411 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011412 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011413
11414 /* And already the Immediate Assignment even before the PDCH Deact ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011415 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011416
11417 /* continue the Osmo style PDCH Deact (usual chan rel) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011418 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011419
11420 /* Now activation as SDCCH8 */
11421 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011422 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011423
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011424 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011425 var RSL_IE_Body chan_ident_ie;
11426 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11427 setverdict(fail, "RSL Channel Identification IE is absent");
11428 mtc.stop;
11429 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011430 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011431
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011432 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11433 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011434
11435 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011436 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011437
11438 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011439 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011440 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011441 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11442
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011443 /* (set bts 0 cfg back to default) */
11444 f_vty_set_imm_ass(BSCVTY);
11445
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011446 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011447 f_perform_clear_test_ct(dt);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011448 f_shutdown_helper();
11449}
11450
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011451/* GET and SET the bts.N.trx.M.rf_locked CTRL variable */
11452testcase TC_ctrl_trx_rf_locked() runs on test_CT {
11453 var MSC_ConnHdlr vc_conn;
11454
11455 f_init(nr_bts := 2, handler_mode := true, nr_msc := 1);
11456 f_sleep(1.0);
11457
11458 /* BTS 0, 1, 2 are OML unlocked, only BTS 0, 1 are actually connected to RSL. */
11459 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11460 "0,0,operational,unlocked,on,rsl-up;" &
11461 "1,0,operational,unlocked,on,rsl-up;" &
11462 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011463 "2,1,operational,unlocked,on,rsl-down;" &
11464 "2,2,operational,unlocked,on,rsl-down;" &
11465 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011466 "3,0,inoperational,locked,on,rsl-down;");
11467
11468 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock BTS 1 TRX 0");
11469 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11470 /* give it a moment to settle the FSM status */
11471 f_sleep(1.0);
11472
11473 /* Now BTS 1 TRX 0 should reflect "locked". Note the RF policy stays "on", because this is still handled
11474 * globally in osmo-bsc. Probably after sending "rf_locked 1" for a TRX, that TRX should reflect an RF policy
11475 * of "off"? But that's for a future patch if at all. */
11476 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11477 "0,0,operational,unlocked,on,rsl-up;" &
11478 "1,0,operational,locked,on,rsl-up;" &
11479 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011480 "2,1,operational,unlocked,on,rsl-down;" &
11481 "2,2,operational,unlocked,on,rsl-down;" &
11482 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011483 "3,0,inoperational,locked,on,rsl-down;");
11484
11485 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock the already locked TRX, nothing should change");
11486 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11487 f_sleep(1.0);
11488 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11489 "0,0,operational,unlocked,on,rsl-up;" &
11490 "1,0,operational,locked,on,rsl-up;" &
11491 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011492 "2,1,operational,unlocked,on,rsl-down;" &
11493 "2,2,operational,unlocked,on,rsl-down;" &
11494 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011495 "3,0,inoperational,locked,on,rsl-down;");
11496
11497 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock BTS 1 TRX 0");
11498 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "0");
11499 f_sleep(1.0);
11500 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11501 "0,0,operational,unlocked,on,rsl-up;" &
11502 "1,0,operational,unlocked,on,rsl-up;" &
11503 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011504 "2,1,operational,unlocked,on,rsl-down;" &
11505 "2,2,operational,unlocked,on,rsl-down;" &
11506 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011507 "3,0,inoperational,locked,on,rsl-down;");
11508
11509 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an already unlocked TRX, nothing should change");
11510 f_ctrl_set(IPA_CTRL, "bts.0.trx.0.rf_locked", "0");
11511 f_sleep(1.0);
11512 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11513 "0,0,operational,unlocked,on,rsl-up;" &
11514 "1,0,operational,unlocked,on,rsl-up;" &
11515 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011516 "2,1,operational,unlocked,on,rsl-down;" &
11517 "2,2,operational,unlocked,on,rsl-down;" &
11518 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011519 "3,0,inoperational,locked,on,rsl-down;");
11520
11521 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an inoperational TRX");
11522 f_ctrl_set(IPA_CTRL, "bts.3.trx.0.rf_locked", "0");
11523 f_sleep(1.0);
11524 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11525 "0,0,operational,unlocked,on,rsl-up;" &
11526 "1,0,operational,unlocked,on,rsl-up;" &
11527 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011528 "2,1,operational,unlocked,on,rsl-down;" &
11529 "2,2,operational,unlocked,on,rsl-down;" &
11530 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011531 "3,0,inoperational,locked,on,rsl-down;");
11532
11533 f_shutdown_helper();
11534}
11535
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011536const CounterNameVals counternames_cm_serv_rej := {
11537 { "cm_serv_rej", 0 },
11538 { "cm_serv_rej:imsi_unknown_in_hlr", 0 },
11539 { "cm_serv_rej:illegal_ms", 0 },
11540 { "cm_serv_rej:imsi_unknown_in_vlr", 0 },
11541 { "cm_serv_rej:imei_not_accepted", 0 },
11542 { "cm_serv_rej:illegal_me", 0 },
11543 { "cm_serv_rej:plmn_not_allowed", 0 },
11544 { "cm_serv_rej:loc_not_allowed", 0 },
11545 { "cm_serv_rej:roaming_not_allowed", 0 },
11546 { "cm_serv_rej:network_failure", 0 },
11547 { "cm_serv_rej:synch_failure", 0 },
11548 { "cm_serv_rej:congestion", 0 },
11549 { "cm_serv_rej:srv_opt_not_supported", 0 },
11550 { "cm_serv_rej:rqd_srv_opt_not_supported", 0 },
11551 { "cm_serv_rej:srv_opt_tmp_out_of_order", 0 },
11552 { "cm_serv_rej:call_can_not_be_identified", 0 },
11553 { "cm_serv_rej:incorrect_message", 0 },
11554 { "cm_serv_rej:invalid_mandantory_inf", 0 },
11555 { "cm_serv_rej:msg_type_not_implemented", 0 },
11556 { "cm_serv_rej:msg_type_not_compatible", 0 },
11557 { "cm_serv_rej:inf_eleme_not_implemented", 0 },
11558 { "cm_serv_rej:condtional_ie_error", 0 },
11559 { "cm_serv_rej:msg_not_compatible", 0 },
11560 { "cm_serv_rej:protocol_error", 0 },
11561 { "cm_serv_rej:retry_in_new_cell", 0 }
11562};
11563
11564private function f_TC_cm_serv_rej(charstring id) runs on MSC_ConnHdlr
11565{
11566 f_create_chan_and_exp();
Vadim Yanitskiya7fc5a62021-12-04 20:10:08 +030011567 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011568 BSSAP.send(ts_PDU_DTAP_MT(ts_CM_SERV_REJ('02'O), '00'O));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011569 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_CM_SERV_REJ));
11570 f_perform_clear();
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011571 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011572}
11573testcase TC_cm_serv_rej() runs on test_CT {
11574 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11575 var MSC_ConnHdlr vc_conn;
11576
11577 f_init(1, true);
11578 f_sleep(1.0);
11579
11580 f_ctrs_bts_init(1, counternames_cm_serv_rej);
11581
11582 vc_conn := f_start_handler(refers(f_TC_cm_serv_rej), pars);
11583 vc_conn.done;
11584
11585 f_ctrs_bts_add(0, "cm_serv_rej", 1);
11586 f_ctrs_bts_add(0, "cm_serv_rej:imsi_unknown_in_hlr", 1);
11587 f_ctrs_bts_verify();
11588
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011589 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011590 f_shutdown_helper();
11591}
11592
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011593/* Reproduce a segfault happening when the SDCCH (primary) lchan is lost in-between a TCH Channel Activ and its Channel
11594 * Activ Ack (SYS#5627). */
11595private function f_TC_lost_sdcch_during_assignment(charstring id) runs on MSC_ConnHdlr {
11596 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Vadim Yanitskiyf0310e32021-10-26 00:30:59 +030011597
11598 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11599 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011600
11601 var BSSMAP_FIELD_CodecType codecType;
11602 codecType := valueof(ass_cmd.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType);
11603
11604 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
11605
11606 /* First establish a signalling lchan */
11607 f_create_chan_and_exp();
11608 f_rslem_dchan_queue_enable();
11609
11610 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011611
11612 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
Oliver Smith735b47c2023-02-15 16:03:54 +010011613 activate(as_Media_mgw());
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011614
11615 var RslChannelNr chan_nr := { u := { ch0 := RSL_CHAN_NR_Bm_ACCH }, tn := 1 };
11616 f_rslem_register(0, chan_nr);
11617
11618 f_rslem_set_auto_chan_act_ack(RSL_PROC, false);
11619 BSSAP.send(ass_cmd);
11620
11621
11622 /* Wait for the Channel Activ for the TCH channel */
11623 var ASP_RSL_Unitdata rx_rsl_ud;
11624 RSL.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), sid := ?)) -> value rx_rsl_ud;
11625
11626 /* make the original SDCCH disappear */
11627 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
11628
11629 /* and ACK the TCH channel activation. This caused a segfault up to OsmoBSC 1.7.0 (SYS#5627) */
11630 RSL.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_ACK(chan_nr, 23), rx_rsl_ud.streamId));
11631
11632 interleave {
11633 [] BSSAP.receive(tr_BSSMAP_AssignmentFail);
11634 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
11635 }
11636
11637 BSSAP.send(ts_BSSMAP_ClearCommand(0));
11638 BSSAP.receive(tr_BSSMAP_ClearComplete);
11639 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
11640
11641 var MgcpCommand mgcp;
Vadim Yanitskiy6be4cf42022-06-04 21:25:47 +060011642 var MGCP_RecvFrom mrf;
11643 var template MgcpMessage msg_dlcx := { command := tr_DLCX };
11644 alt {
11645 [g_pars.aoip] MGCP.receive(tr_DLCX) -> value mgcp {
11646 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
11647 }
11648 [not g_pars.aoip] MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
11649 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, MgcpMessage:{
11650 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
11651 }));
11652 }
11653 }
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011654
11655 f_sleep(0.5);
11656}
11657testcase TC_lost_sdcch_during_assignment() runs on test_CT {
11658 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11659 var MSC_ConnHdlr vc_conn;
11660
Oliver Smith735b47c2023-02-15 16:03:54 +010011661 pars.fail_on_dlcx := false;
11662
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011663 f_init(1, true);
11664 f_sleep(1.0);
11665
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011666 vc_conn := f_start_handler(refers(f_TC_lost_sdcch_during_assignment), pars);
11667 vc_conn.done;
11668
11669 f_shutdown_helper();
11670}
11671
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011672const CounterNameVals counternames_bsc_bts_all_available_allocated := {
11673 { "all_allocated:sdcch", 0 },
11674 { "all_allocated:static_sdcch", 0 },
11675 { "all_allocated:tch", 0 },
11676 { "all_allocated:static_tch", 0 }
11677}
11678
11679private function f_all_allocated_expect_counter_change(charstring_list expect_changed) runs on test_CT
11680{
11681 /* Make sure counters settle first */
11682 f_sleep(1.0);
11683
11684 /* Take a baseline of counters */
11685 f_ctrs_bsc_and_bts_init(1, counternames_bsc_bts_all_available_allocated);
11686
11687 /* Elapse some time so that we see changes in counters, hopefully where expected */
11688 f_sleep(2.0);
11689
11690 /* Get new counters */
11691 var charstring_list all_changed := {};
11692 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bsc", g_ctr_bsc);
11693 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bts", g_ctr_bts);
11694
11695 /* Compare with expectations */
11696 var charstring_list all_expect_changed := {};
11697 for (var integer i := 0; i < lengthof(expect_changed); i := i + 1) {
11698 all_expect_changed := all_expect_changed & { "bsc.0." & expect_changed[i], "bts.0." & expect_changed[i] };
11699 }
11700 f_counter_name_vals_expect_changed_list(all_changed, all_expect_changed);
11701}
11702
11703testcase TC_ratectr_all_available_allocated() runs on test_CT {
11704 var ASP_RSL_Unitdata rsl_ud;
11705 var integer i;
11706 var integer chreq_total, chreq_nochan;
11707
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011708 f_init(1, guard_timeout := 60.0);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011709 f_sleep(1.0);
11710
11711 /* Exhaust all dedicated SDCCH lchans.
11712 /* GSM 44.018 Table 9.1.8.2:
11713 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11714 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011715 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011716 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011717 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 +020011718 }
11719
11720 /* Since only bts 0 is connected, expecting all_allocated to become true for both bts 0 and the "global" bsc
11721 * level.
11722 * All SDCCH are now occupied. */
11723 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11724
11725 /* Also fill up all remaining (TCH) channels */
11726 for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011727 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 +020011728 }
11729
11730 /* All TCH are now also occupied */
11731 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11732 "all_allocated:tch", "all_allocated:static_tch"});
11733
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011734 /* Clean up SDCCH lchans */
11735 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
11736 f_perform_clear_test_ct(chan_cleanup[i]);
11737 }
11738
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011739 f_shutdown_helper();
11740}
11741
11742testcase TC_ratectr_all_available_allocated_dyn() runs on test_CT {
11743 var ASP_RSL_Unitdata rsl_ud;
11744 var integer i;
11745 var integer chreq_total, chreq_nochan;
11746
11747 f_init_vty();
11748 f_ts_set_chcomb(0, 0, 2, "TCH/F_TCH/H_PDCH");
11749 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11750 /* Now we have 3 TCH/F, 1 OSMO_DYN, 1 TCH/H */
11751
11752 f_init(1, guard_timeout := 60.0);
11753 f_sleep(1.0);
11754
11755 /* The dyn TS wants to activate PDCH mode, ACK that. */
11756 var RslChannelNr chan_nr;
11757 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011758 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11759 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011760
11761 /* Exhaust all dedicated SDCCH lchans.
11762 /* GSM 44.018 Table 9.1.8.2:
11763 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11764 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011765 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011766 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011767 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 +020011768 }
11769
11770 /* The static SDCCH should now be occupied, while still 3x8 dynamic SDCCH potentially remain. So only
11771 * all_allocated:static_sdcch is counted, all_allocated:sdcch remains zero. */
11772 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch"});
11773
11774 /* Request more SDCCH, hence convert the first dyn TS to SDCCH8.
11775 * Will release them later, so remember all the DchanTuples. */
11776 var DchanTuples dyn_sddch := {};
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011777 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 +020011778
11779 /* Also occupy the seven other SDCCH of the dyn TS */
11780 for (i := 0; i < 7; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011781 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 +020011782 }
11783
11784 /* Now all dynamic SDCCH are also occupied, so for the first time all_allocated:sdcch will trigger... */
11785 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11786
11787 /* occupy the remaining TCH, three TCH/F and two TCH/H lchans */
11788 for (i := 0; i < 5; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011789 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 +020011790 }
11791
11792 /* All TCH lchans are now also occupied, both static and dynamic */
11793 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11794 "all_allocated:tch", "all_allocated:static_tch"});
11795
11796 /* Starting to release the dyn TS: as soon as the first SDCCH gets released, all_allocated:sdcch stops
11797 * incrementing. */
11798 var BssmapCause cause := 0;
11799 var DchanTuple dt := dyn_sddch[0];
11800 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011801 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011802
11803 /* one dyn TS SDCCH is free again, so only the static_sdcch should increment. For tch, both static and dynamic
11804 * count as occupied, so those still both increment. */
11805 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch",
11806 "all_allocated:tch", "all_allocated:static_tch"});
11807
11808 /* Release the remaining SDCCH of the dyn TS, so it becomes available as TCH again */
11809 for (i := 1; i < lengthof(dyn_sddch); i := i+1) {
11810 dt := dyn_sddch[i];
11811 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011812 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011813 }
11814
11815 /* All SDCCH on the dyn TS are released, the dyn TS wants to activate PDCH again */
11816 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011817 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11818 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011819
11820 /* Now all channels are occupied except the dyn TS, so expecting only the static counters to increment */
11821 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch", "all_allocated:static_tch"});
11822
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011823 /* Clean up SDCCH lchans */
11824 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
11825 f_perform_clear_test_ct(chan_cleanup[i]);
11826 }
11827
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011828 /* clean up config */
11829 f_ts_reset_chcomb(0);
11830
11831 f_shutdown_helper();
11832}
11833
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011834private function f_TC_chan_alloc_algo(DchanTuple dt, BtsTrxIdx idx)
11835runs on test_CT {
11836 /* MSC sends an Assignment Request */
11837 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11838 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11839 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11840 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
11841
11842 /* Expect the BSC to allocate a TCH channel on the given BTS/TRX */
11843 var RSL_Message rsl_chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
11844 /* Send CHAN ACT NACK, so that the requested TCH channel becomes BORKEN */
11845 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(rsl_chan_act.ies[0].body.chan_nr, RSL_ERR_EQUIPMENT_FAIL), idx);
11846 /* Expect to receive an Assignment Failure */
11847 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail));
11848}
11849
11850testcase TC_chan_alloc_algo_ascending() runs on test_CT {
11851 /* We need to access BTS2, which has 4 TRXs */
11852 f_init(nr_bts := 3);
11853
11854 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020011855 vc_MGCP[0].stop;
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011856
11857 f_vty_enter_cfg_bts(BSCVTY, 2);
11858 f_vty_transceive(BSCVTY, "channel allocator ascending");
11859 f_vty_transceive(BSCVTY, "end");
11860
11861 /* Expect the BSC to allocate 4 x TCH/F channels on BTS2/TRX0 */
11862 for (var integer i := 0; i < 4; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011863 var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), {2, 0});
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011864 f_TC_chan_alloc_algo(dt, {2, 0});
11865 f_perform_clear_test_ct(dt);
11866 }
11867
11868 /* At this point all 4 x TCH/F channels are BORKEN, but they will be
11869 * resurrected upon the A-bis/OML link re-establishment. */
11870 f_shutdown_helper();
11871}
11872
11873testcase TC_chan_alloc_algo_descending() runs on test_CT {
11874 /* We need to access BTS2, which has 4 TRXs */
11875 f_init(nr_bts := 3);
11876
11877 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020011878 vc_MGCP[0].stop;
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011879
11880 f_vty_enter_cfg_bts(BSCVTY, 2);
11881 f_vty_transceive(BSCVTY, "channel allocator descending");
11882 f_vty_transceive(BSCVTY, "end");
11883
11884 /* Expect the BSC to allocate 5 x TCH/F channels on BTS2/TRX3 */
11885 for (var integer i := 0; i < 5; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011886 var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), {2, 0});
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011887 f_TC_chan_alloc_algo(dt, {2, 3});
11888 f_perform_clear_test_ct(dt);
11889 }
11890
11891 /* At this point all 5 x TCH/F channels are BORKEN, but they will be
11892 * resurrected upon the A-bis/OML link re-establishment. */
11893 f_shutdown_helper();
11894}
11895
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011896testcase TC_chan_alloc_algo_ass_dynamic() runs on test_CT {
11897 const BtsTrxIdx TRX0 := {2, 0};
11898 const BtsTrxIdx TRX3 := {2, 3};
11899
11900 /* We need to access BTS2, which has 4 TRXs */
11901 f_init(nr_bts := 3);
11902
11903 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020011904 vc_MGCP[0].stop;
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011905
11906 f_vty_enter_cfg_bts(BSCVTY, 2);
11907 f_vty_transceive(BSCVTY, "channel allocator mode assignment dynamic");
11908 f_vty_transceive(BSCVTY, "channel allocator dynamic-param ul-rxlev thresh 50 avg-num 2");
11909 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 0");
11910 f_vty_transceive(BSCVTY, "end");
11911
11912 var DchanTuple dt;
11913
11914 f_logp(BSCVTY, "Case a) Unknown Uplink RxLev, fall-back to ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011915 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011916 f_TC_chan_alloc_algo(dt, TRX0);
11917 f_perform_clear_test_ct(dt);
11918
11919 f_logp(BSCVTY, "Case b) Not enough RxLev samples, use ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011920 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011921 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
11922 ts_RSL_IE_UplinkMeas(30, 0),
11923 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070011924 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011925 f_TC_chan_alloc_algo(dt, TRX0);
11926 f_perform_clear_test_ct(dt);
11927
11928 f_logp(BSCVTY, "Case c) Uplink RxLev below the threshold, use ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011929 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011930 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
11931 ts_RSL_IE_UplinkMeas(45, 0),
11932 ts_RSL_IE_BS_Power(0)), TRX0);
11933 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
11934 ts_RSL_IE_UplinkMeas(48, 0),
11935 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070011936 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011937 f_TC_chan_alloc_algo(dt, TRX0);
11938 f_perform_clear_test_ct(dt);
11939
11940 f_logp(BSCVTY, "Case d) Uplink RxLev above the threshold, use descending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011941 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011942 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
11943 ts_RSL_IE_UplinkMeas(50, 0),
11944 ts_RSL_IE_BS_Power(0)), TRX0);
11945 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
11946 ts_RSL_IE_UplinkMeas(58, 0),
11947 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070011948 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011949 f_TC_chan_alloc_algo(dt, TRX3);
11950 f_perform_clear_test_ct(dt);
11951
11952 f_vty_enter_cfg_bts(BSCVTY, 2);
11953 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 90");
11954 f_vty_transceive(BSCVTY, "end");
11955
11956 f_logp(BSCVTY, "Case e) Uplink RxLev above the threshold, but C0 load is not");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011957 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011958 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
11959 ts_RSL_IE_UplinkMeas(50, 0),
11960 ts_RSL_IE_BS_Power(0)), TRX0);
11961 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
11962 ts_RSL_IE_UplinkMeas(58, 0),
11963 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070011964 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011965 f_TC_chan_alloc_algo(dt, TRX0);
11966 f_perform_clear_test_ct(dt);
11967
11968 f_vty_enter_cfg_bts(BSCVTY, 2);
11969 f_vty_transceive(BSCVTY, "channel allocator ascending");
11970 f_vty_transceive(BSCVTY, "end");
11971
11972 /* At this point some TCH/F channels are BORKEN, but they will be
11973 * resurrected upon the A-bis/OML link re-establishment. */
11974 f_shutdown_helper();
11975}
11976
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020011977private function f_vty_mgw_enable(integer mgw_nr := 1) runs on test_CT {
11978 var rof_charstring cmds := {
11979 "remote-ip " & mp_test_ip,
11980 "remote-port " & int2str(2427 + mgw_nr)
11981 };
11982 f_vty_config3(BSCVTY, {"network", "mgw " & int2str(mgw_nr)}, cmds);
11983 f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " reconnect")
11984}
11985private function f_vty_mgw_disable(integer mgw_nr := 1) runs on test_CT {
11986 f_vty_config3(BSCVTY, {"network"}, { "no mgw " &int2str(mgw_nr) });
11987}
11988private function f_vty_mgw_block(integer mgw_nr := 1, boolean blocked := true) runs on test_CT {
11989 var charstring arg;
11990 if (blocked) {
11991 arg := "block";
11992 } else {
11993 arg := "unblock";
11994 }
11995 f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " " & arg);
11996}
11997private const charstring COORD_CMD_ESTABLISHED := "COORD_CMD_ESTABLISHED";
11998private function f_TC_mgwpool_call_seq_1(charstring id) runs on MSC_ConnHdlr {
11999 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12000 var PDU_BSSAP ass_cmd := f_gen_ass_req();
12001 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12002 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12003
12004 f_establish_fully(ass_cmd, exp_compl);
12005 COORD.send(COORD_CMD_ESTABLISHED);
12006
12007 COORD.receive(COORD_CMD_ESTABLISHED);
12008 f_perform_clear()
12009 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12010}
12011private function f_TC_mgwpool_call_seq_2(charstring id) runs on MSC_ConnHdlr {
12012 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12013 var PDU_BSSAP ass_cmd := f_gen_ass_req();
12014 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12015 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12016
12017
12018 COORD.receive(COORD_CMD_ESTABLISHED);
12019 f_establish_fully(ass_cmd, exp_compl);
12020 COORD.send(COORD_CMD_ESTABLISHED);
12021
12022 f_perform_clear()
12023 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12024}
12025/* Test load is spread around 2 available MGWs */
12026testcase TC_mgwpool_all_used() runs on test_CT {
12027 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12028 var MSC_ConnHdlr vc_conn1;
12029 pars1.mgwpool_idx := 0;
12030
12031 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12032 var MSC_ConnHdlr vc_conn2;
12033 pars2.mgwpool_idx := 1;
12034
12035 f_init(1, true, nr_mgw := 2);
12036 f_sleep(1.0);
12037
12038 f_vty_mgw_enable(1);
12039
12040 vc_conn1 := f_start_handler_create(pars1);
12041 vc_conn2 := f_start_handler_create(pars2);
12042 connect(vc_conn1:COORD, vc_conn2:COORD);
12043 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12044 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12045 vc_conn1.done;
12046 vc_conn2.done;
12047
12048 f_vty_mgw_disable(1);
12049
12050 f_shutdown_helper();
12051}
12052
12053/* Test blocked MGW in the pool are not selected */
12054testcase TC_mgwpool_blocked_not_used() runs on test_CT {
12055 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12056 var MSC_ConnHdlr vc_conn1;
12057 pars1.mgwpool_idx := 0;
12058
12059 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12060 var MSC_ConnHdlr vc_conn2;
12061 pars2.mgwpool_idx := 0; /* expect it in the first one, since the second will be blocked */
12062 pars2.media_nr := 2;
12063
12064 f_init(1, true, nr_mgw := 2);
12065 f_sleep(1.0);
12066
12067 f_vty_mgw_enable(1);
12068 f_vty_mgw_block(1, true);
12069
12070 vc_conn1 := f_start_handler_create(pars1);
12071 vc_conn2 := f_start_handler_create(pars2);
12072 connect(vc_conn1:COORD, vc_conn2:COORD);
12073 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12074 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12075 vc_conn1.done;
12076 vc_conn2.done;
12077
12078 f_vty_mgw_disable(1);
12079
12080 f_shutdown_helper();
12081}
12082
Pau Espin Pedrol3f41e322022-10-20 19:34:43 +020012083/* Test BTS pinning to an MGW is applied */
12084testcase TC_mgwpool_pin_bts() runs on test_CT {
12085 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12086 var MSC_ConnHdlr vc_conn1;
12087 pars1.mgwpool_idx := 0;
12088
12089 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12090 var MSC_ConnHdlr vc_conn2;
12091 pars2.mgwpool_idx := 0; /* expect it in the first one, since the BTS is pinned to the first MGW */
12092 pars2.media_nr := 2;
12093
12094 f_init(1, true, nr_mgw := 2);
12095 f_sleep(1.0);
12096
12097 f_vty_mgw_enable(1);
12098 f_vty_cfg_bts(BSCVTY, 0, { "mgw pool-target 0" });
12099
12100 vc_conn1 := f_start_handler_create(pars1);
12101 vc_conn2 := f_start_handler_create(pars2);
12102 connect(vc_conn1:COORD, vc_conn2:COORD);
12103 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12104 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12105 vc_conn1.done;
12106 vc_conn2.done;
12107
12108 f_vty_cfg_bts(BSCVTY, 0, { "no mgw pool-target" } );
Vadim Yanitskiy389d7e02022-10-25 17:44:05 +070012109 f_vty_mgw_disable(1);
Pau Espin Pedrol3f41e322022-10-20 19:34:43 +020012110
12111 f_shutdown_helper();
12112}
12113
Oliver Smithc9a5f532022-10-21 11:32:23 +020012114private function f_tc_ho_meas_rep_multi_band(charstring id) runs on MSC_ConnHdlr {
12115 g_pars := f_gen_test_hdlr_pars();
12116 var PDU_BSSAP ass_req := f_gen_ass_req();
12117 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12118 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12119 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12120 f_establish_fully(ass_req, exp_compl);
12121
12122 /* Send a measurement report with bad rxlev except on 3rd entry. The
12123 * measurement report is divided into two sub lists, as described in
12124 * 3GPP TS 04.08 § 10.5.2.20. */
12125 var NcellReports neighbor_rep := {
12126 /* Sub list 1: same band */
Oliver Smitha6773042022-10-24 12:56:30 +020012127 { rxlev := 0, bcch_freq := 0, bsic := 12 }, /* ARFCN 800, band 1800, LAC 98 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012128 /* Sub list 2: different band */
Oliver Smitha6773042022-10-24 12:56:30 +020012129 { rxlev := 0, bcch_freq := 1, bsic := 13 }, /* ARFCN 200, band 850, LAC 97 */
12130 { rxlev := 40, bcch_freq := 2, bsic := 14 }, /* ARFCN 1000, band 900, LAC 99 */
12131 { rxlev := 0, bcch_freq := 3, bsic := 11 } /* ARFCN 0, band 900, LAC 96 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012132 };
12133 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
12134 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
12135 l3_mr, 0));
12136
12137 /* Expect a handover to the third entry. If the BSC parsed the report
Oliver Smitha6773042022-10-24 12:56:30 +020012138 * correctly, the third entry has LAC 99. */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012139 var template BSSMAP_FIELD_CellIdentificationList cid_list := {
Oliver Smitha6773042022-10-24 12:56:30 +020012140 cIl_LAC := { ts_BSSMAP_CI_LAC(99) }
Oliver Smithc9a5f532022-10-21 11:32:23 +020012141 };
12142 alt {
12143 [] BSSAP.receive(tr_BSSMAP_HandoverRequired(cid_list := cid_list)) {
12144 setverdict(pass);
12145 }
12146 [] BSSAP.receive(tr_BSSMAP_HandoverRequired()) {
12147 setverdict(fail, "Handover has unexpected LAC in Cell Identification List. The BSC probably"
12148 & " didn't parse the multi-band measurement report correctly.");
12149 }
12150 }
12151
12152 f_ho_out_of_this_bsc(skip_meas_rep := true);
12153}
12154testcase TC_ho_meas_rep_multi_band() runs on test_CT {
12155 /* Verify that the BSC parses the measurement report correctly when
12156 * neighbors in multiple bands are configured (OS#5717). See
12157 * gsm_arfcn2band_rc() in libosmocore src/gsm/gsm_utils.c for the
12158 * ARFCN -> band mapping. The MS is connected to band 1800. */
12159 var MSC_ConnHdlr vc_conn;
12160
12161 f_init_vty();
12162 f_bts_0_cfg(BSCVTY,
12163 {"neighbor-list mode automatic",
12164 "handover 1",
12165 "handover algorithm 2",
12166 "handover2 window rxlev averaging 1",
12167 "no neighbors",
12168 "neighbor lac 99 arfcn 1000 bsic any", /* band 900 */
12169 "neighbor lac 98 arfcn 800 bsic any", /* band 1800 */
12170 "neighbor lac 97 arfcn 200 bsic any", /* band 850 */
Oliver Smitha6773042022-10-24 12:56:30 +020012171 "neighbor lac 96 arfcn 0 bsic any"}); /* band 900 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012172 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
12173
12174 f_init(1, true);
12175 f_sleep(1.0);
12176
12177 f_ctrs_bsc_and_bts_handover_init();
12178
12179 vc_conn := f_start_handler(refers(f_tc_ho_meas_rep_multi_band));
12180 vc_conn.done;
12181
12182 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
12183 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
12184 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
12185 f_ctrs_bsc_and_bts_add(0, "handover:completed");
12186 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
12187 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
12188 f_ctrs_bsc_and_bts_verify();
12189 f_shutdown_helper(ho := true);
12190}
12191
Harald Welte28d943e2017-11-25 15:00:50 +010012192control {
Harald Welte898113b2018-01-31 18:32:21 +010012193 /* CTRL interface testing */
Harald Welte4003d112017-12-09 22:35:39 +010012194 execute( TC_ctrl_msc_connection_status() );
Stefan Sperlingb041b3d2018-01-03 17:14:55 +010012195 execute( TC_ctrl_msc0_connection_status() );
Neels Hofmeyrf65ce872021-09-23 18:40:10 +020012196 /* In SCCPlite tests, only one MSC is configured. These tests assume that three MSCs are configured, so only run
12197 * these in the AoIP test suite. */
12198 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12199 execute( TC_stat_num_msc_connected_1() );
12200 execute( TC_stat_num_msc_connected_2() );
12201 execute( TC_stat_num_msc_connected_3() );
12202 }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +020012203 execute( TC_stat_num_bts_connected_1() );
12204 execute( TC_stat_num_bts_connected_2() );
12205 execute( TC_stat_num_bts_connected_3() );
Harald Welte96c94412017-12-09 03:12:45 +010012206 execute( TC_ctrl() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012207 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER) {
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +020012208 execute( TC_ctrl_location() );
12209 }
Harald Welte898113b2018-01-31 18:32:21 +010012210
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020012211 execute( TC_si_default() );
Neels Hofmeyr66aeba42020-07-06 02:21:21 +020012212 execute( TC_si2quater_2_earfcns() );
12213 execute( TC_si2quater_3_earfcns() );
12214 execute( TC_si2quater_4_earfcns() );
12215 execute( TC_si2quater_5_earfcns() );
12216 execute( TC_si2quater_6_earfcns() );
Neels Hofmeyrad132f22020-07-08 02:20:16 +020012217 execute( TC_si2quater_12_earfcns() );
12218 execute( TC_si2quater_23_earfcns() );
12219 execute( TC_si2quater_32_earfcns() );
12220 execute( TC_si2quater_33_earfcns() );
12221 execute( TC_si2quater_42_earfcns() );
12222 execute( TC_si2quater_48_earfcns() );
12223 execute( TC_si2quater_49_earfcns() );
Pau Espin Pedrol85a84432020-07-20 18:45:03 +020012224 execute( TC_si_acc_rotate() );
Alexander Couzens4ad3a352020-09-10 22:29:12 +020012225 execute( TC_si_acc_ramp_rotate() );
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020012226
Harald Welte898113b2018-01-31 18:32:21 +010012227 /* RSL DCHAN Channel ACtivation / Deactivation */
Harald Welteae026692017-12-09 01:03:01 +010012228 execute( TC_chan_act_noreply() );
Harald Welte4003d112017-12-09 22:35:39 +010012229 execute( TC_chan_act_counter() );
Harald Welteae026692017-12-09 01:03:01 +010012230 execute( TC_chan_act_ack_noest() );
Philipp Maier9c60a622020-07-09 15:08:46 +020012231 execute( TC_chan_act_ack_noest_emerg() );
Philipp Maier606f07d2020-08-12 17:21:58 +020012232 execute( TC_chan_rqd_emerg_deny() );
Harald Welteae026692017-12-09 01:03:01 +010012233 execute( TC_chan_act_ack_est_ind_noreply() );
12234 execute( TC_chan_act_ack_est_ind_refused() );
Harald Welte618ef642017-12-14 14:58:20 +010012235 execute( TC_chan_act_nack() );
Harald Welte799c97b2017-12-14 17:50:30 +010012236 execute( TC_chan_exhaustion() );
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +070012237 execute( TC_chan_deact_silence() );
Harald Welte4003d112017-12-09 22:35:39 +010012238 execute( TC_chan_rel_rll_rel_ind() );
12239 execute( TC_chan_rel_conn_fail() );
12240 execute( TC_chan_rel_hard_clear() );
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +020012241 execute( TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() );
12242 execute( TC_chan_rel_last_eutran_plmn_hard_clear_csfb() );
Harald Welte99787102019-02-04 10:41:36 +010012243 execute( TC_chan_rel_hard_clear_csfb() );
Harald Welted8c36cd2017-12-09 23:05:31 +010012244 execute( TC_chan_rel_hard_rlsd() );
Harald Welte550daf92018-06-11 19:22:13 +020012245 execute( TC_chan_rel_hard_rlsd_ms_dead() );
Harald Welte85804d42017-12-10 14:11:58 +010012246 execute( TC_chan_rel_a_reset() );
Pau Espin Pedrolc675b612020-01-09 19:55:40 +010012247 execute( TC_chan_rel_sccp_tiar_timeout() );
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +020012248 execute( TC_chan_rel_rr_cause() );
Harald Welte6f521d82017-12-11 19:52:02 +010012249
Harald Weltecfe2c962017-12-15 12:09:32 +010012250 execute( TC_outbound_connect() );
Harald Welte898113b2018-01-31 18:32:21 +010012251
12252 /* Assignment related */
Harald Welte16a4adf2017-12-14 18:54:01 +010012253 execute( TC_assignment_cic_only() );
Harald Welte235ebf12017-12-15 14:18:16 +010012254 execute( TC_assignment_csd() );
12255 execute( TC_assignment_ctm() );
12256 execute( TC_assignment_sign() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020012257 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12258 execute( TC_assignment_aoip_tla_v6() );
12259 }
Harald Welte235ebf12017-12-15 14:18:16 +010012260 execute( TC_assignment_fr_a5_0() );
12261 execute( TC_assignment_fr_a5_1() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012262 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte8f67d1d2018-05-25 20:38:42 +020012263 execute( TC_assignment_fr_a5_1_codec_missing() );
12264 }
Harald Welte235ebf12017-12-15 14:18:16 +010012265 execute( TC_assignment_fr_a5_3() );
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +020012266 execute( TC_assignment_fr_a5_4() );
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +020012267 execute( TC_assignment_fr_a5_4_fail() );
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +020012268 execute( TC_assignment_fr_a5_not_sup() );
Harald Welte3c86ea02018-05-10 22:28:05 +020012269 execute( TC_ciph_mode_a5_0() );
12270 execute( TC_ciph_mode_a5_1() );
Oliver Smith50b98122021-07-09 15:00:28 +020012271 execute( TC_ciph_mode_a5_2_0() );
Oliver Smith1dff88d2021-07-09 08:45:51 +020012272 execute( TC_ciph_mode_a5_2_1() );
Harald Welte3c86ea02018-05-10 22:28:05 +020012273 execute( TC_ciph_mode_a5_3() );
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +020012274 execute( TC_ciph_mode_a5_4() );
Harald Welte16a4adf2017-12-14 18:54:01 +010012275
Harald Welte60aa5762018-03-21 19:33:13 +010012276 execute( TC_assignment_codec_fr() );
Neels Hofmeyr559d5d02021-04-16 16:50:49 +020012277 execute( TC_assignment_codec_fr_by_mode_modify() );
Harald Welte60aa5762018-03-21 19:33:13 +010012278 execute( TC_assignment_codec_hr() );
12279 execute( TC_assignment_codec_efr() );
12280 execute( TC_assignment_codec_amr_f() );
12281 execute( TC_assignment_codec_amr_h() );
Philipp Maier8a581d22019-03-26 18:32:48 +010012282
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012283 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier8a581d22019-03-26 18:32:48 +010012284 execute( TC_assignment_codec_amr_f_S1() );
12285 execute( TC_assignment_codec_amr_h_S1() );
12286 execute( TC_assignment_codec_amr_f_S124() );
12287 execute( TC_assignment_codec_amr_h_S124() );
12288 execute( TC_assignment_codec_amr_f_S0() );
12289 execute( TC_assignment_codec_amr_f_S02() );
12290 execute( TC_assignment_codec_amr_f_S024() );
12291 execute( TC_assignment_codec_amr_f_S0247() );
12292 execute( TC_assignment_codec_amr_h_S0() );
12293 execute( TC_assignment_codec_amr_h_S02() );
12294 execute( TC_assignment_codec_amr_h_S024() );
12295 execute( TC_assignment_codec_amr_h_S0247() );
12296 execute( TC_assignment_codec_amr_f_S01234567() );
12297 execute( TC_assignment_codec_amr_f_S0234567() );
12298 execute( TC_assignment_codec_amr_f_zero() );
12299 execute( TC_assignment_codec_amr_f_unsupp() );
12300 execute( TC_assignment_codec_amr_h_S7() );
Neels Hofmeyr21863562020-11-26 00:34:33 +000012301 execute( TC_assignment_codec_amr_f_start_mode_auto() );
12302 execute( TC_assignment_codec_amr_h_start_mode_auto() );
Neels Hofmeyr3eb94562020-11-26 02:40:26 +000012303 execute( TC_assignment_codec_amr_f_start_mode_4() );
12304 execute( TC_assignment_codec_amr_h_start_mode_4() );
Neels Hofmeyr454d7922020-11-26 02:24:57 +000012305 execute( TC_assignment_codec_amr_startmode_cruft() );
Philipp Maier8a581d22019-03-26 18:32:48 +010012306 }
Harald Welte60aa5762018-03-21 19:33:13 +010012307
Philipp Maierac09bfc2019-01-08 13:41:39 +010012308 execute( TC_assignment_codec_fr_exhausted_req_hr() );
12309 execute( TC_assignment_codec_fr_exhausted_req_fr() );
12310 execute( TC_assignment_codec_fr_exhausted_req_fr_hr() );
12311 execute( TC_assignment_codec_fr_exhausted_req_hr_fr() );
12312 execute( TC_assignment_codec_hr_exhausted_req_fr() );
12313 execute( TC_assignment_codec_hr_exhausted_req_hr() );
12314 execute( TC_assignment_codec_hr_exhausted_req_hr_fr() );
12315 execute( TC_assignment_codec_hr_exhausted_req_fr_hr() );
12316 execute( TC_assignment_codec_req_hr_fr() );
12317 execute( TC_assignment_codec_req_fr_hr() );
Pau Espin Pedrol14475352021-07-22 15:48:16 +020012318 execute( TC_assignment_sdcch_exhausted_req_signalling() );
12319 execute( TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() );
12320 execute( TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() );
Philipp Maierac09bfc2019-01-08 13:41:39 +010012321
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +020012322 execute( TC_assignment_codec_hr_osmux_on() );
Pau Espin Pedrol23510fb2021-07-20 17:00:38 +020012323 execute( TC_assignment_osmux() );
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020012324 execute( TC_assignment_osmux_cn() );
12325 execute( TC_assignment_osmux_bts() );
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +020012326
Harald Welte898113b2018-01-31 18:32:21 +010012327 /* RLL Establish Indication on inactive DCHAN / SAPI */
Harald Welte5cd20ed2017-12-13 21:03:20 +010012328 execute( TC_rll_est_ind_inact_lchan() );
12329 execute( TC_rll_est_ind_inval_sapi1() );
12330 execute( TC_rll_est_ind_inval_sapi3() );
12331 execute( TC_rll_est_ind_inval_sacch() );
12332
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +070012333 /* DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
12334 execute( TC_tch_dlci_link_id_sapi() );
12335
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070012336 /* SAPI N Reject triggered by RLL establishment failures */
12337 execute( TC_rll_rel_ind_sapi_n_reject() );
12338 execute( TC_rll_err_ind_sapi_n_reject() );
12339 execute( TC_rll_timeout_sapi_n_reject() );
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +070012340 execute( TC_rll_sapi_n_reject_dlci_cc() );
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070012341
Harald Welte898113b2018-01-31 18:32:21 +010012342 /* Paging related tests */
Harald Welte6f521d82017-12-11 19:52:02 +010012343 execute( TC_paging_imsi_nochan() );
12344 execute( TC_paging_tmsi_nochan() );
12345 execute( TC_paging_tmsi_any() );
12346 execute( TC_paging_tmsi_sdcch() );
12347 execute( TC_paging_tmsi_tch_f() );
12348 execute( TC_paging_tmsi_tch_hf() );
12349 execute( TC_paging_imsi_nochan_cgi() );
12350 execute( TC_paging_imsi_nochan_lac_ci() );
12351 execute( TC_paging_imsi_nochan_ci() );
12352 execute( TC_paging_imsi_nochan_lai() );
12353 execute( TC_paging_imsi_nochan_lac() );
12354 execute( TC_paging_imsi_nochan_all() );
Harald Welte751d3eb2018-01-31 15:51:06 +010012355 execute( TC_paging_imsi_nochan_plmn_lac_rnc() );
12356 execute( TC_paging_imsi_nochan_rnc() );
12357 execute( TC_paging_imsi_nochan_lac_rnc() );
12358 execute( TC_paging_imsi_nochan_lacs() );
12359 execute( TC_paging_imsi_nochan_lacs_empty() );
Stefan Sperling049a86e2018-03-20 15:51:00 +010012360 execute( TC_paging_imsi_nochan_cgi_unknown_cid() );
Harald Welte10985002017-12-12 09:29:15 +010012361 execute( TC_paging_imsi_a_reset() );
Harald Weltee65d40e2017-12-13 00:09:06 +010012362 execute( TC_paging_imsi_load() );
Philipp Maier779a7922018-02-16 11:00:37 +010012363 execute( TC_paging_counter() );
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +010012364 execute( TC_paging_resp_unsol() );
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +020012365 execute( TC_paging_500req() );
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +020012366 execute( TC_paging_450req_no_paging_load_ind() );
Pau Espin Pedrol07657ae2023-01-03 12:08:05 +010012367 execute( TC_paging_imsi_nochan_ci_resp_invalid_mi() );
Harald Welte4e9b9cc2017-12-14 18:31:02 +010012368
12369 execute( TC_rsl_drop_counter() );
Stefan Sperling830dc9d2018-02-12 21:08:28 +010012370 execute( TC_rsl_unknown_unit_id() );
12371
12372 execute( TC_oml_unknown_unit_id() );
Harald Welte898113b2018-01-31 18:32:21 +010012373
12374 execute( TC_classmark() );
Harald Welteeddf0e92020-06-21 19:42:15 +020012375 execute( TC_common_id() );
Harald Welte898113b2018-01-31 18:32:21 +010012376 execute( TC_unsol_ass_fail() );
Harald Welteea99a002018-01-31 20:46:43 +010012377 execute( TC_unsol_ass_compl() );
Harald Weltefbf9b5e2018-01-31 20:41:23 +010012378 execute( TC_unsol_ho_fail() );
Harald Weltee3bd6582018-01-31 22:51:25 +010012379 execute( TC_err_82_short_msg() );
Harald Weltee9e02e42018-01-31 23:36:25 +010012380 execute( TC_err_84_unknown_msg() );
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012381
Harald Welte261af4b2018-02-12 21:20:39 +010012382 execute( TC_ho_int() );
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +020012383 execute( TC_ho_int_a5_0() );
12384 execute( TC_ho_int_a5_1() );
12385 execute( TC_ho_int_a5_3() );
12386 execute( TC_ho_int_a5_4() );
Neels Hofmeyr5f144212020-11-03 15:41:58 +000012387 execute( TC_ho_int_radio_link_failure() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012388
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012389 /* TC_ho_out_of_this_bsc is run last, see comment below */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +020012390 execute( TC_ho_out_fail_no_msc_response() );
12391 execute( TC_ho_out_fail_rr_ho_failure() );
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +020012392 execute( TC_ho_out_fail_no_result_after_ho_cmd() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012393
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012394 execute( TC_ho_into_this_bsc() );
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +020012395 execute( TC_ho_into_this_bsc_a5_0() );
12396 execute( TC_ho_into_this_bsc_a5_1() );
12397 execute( TC_ho_into_this_bsc_a5_3() );
12398 execute( TC_ho_into_this_bsc_a5_4() );
Neels Hofmeyr93182e02022-02-17 21:59:07 +010012399 execute( TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() );
12400 execute( TC_ho_into_this_bsc_a5_1_3() );
Neels Hofmeyr907b23b2022-02-17 21:58:47 +010012401 execute( TC_ho_into_this_bsc_a5_mismatch() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020012402 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12403 execute( TC_ho_into_this_bsc_tla_v6() );
12404 }
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +020012405 execute( TC_srvcc_eutran_to_geran() );
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +030012406 execute( TC_srvcc_eutran_to_geran_a5_3() );
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +010012407 execute( TC_srvcc_eutran_to_geran_src_sai() );
Pau Espin Pedrol35801c32021-04-19 13:03:20 +020012408 execute( TC_srvcc_eutran_to_geran_ho_out() );
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +020012409 execute( TC_srvcc_eutran_to_geran_forbid_fast_return() );
12410 execute( TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012411 execute( TC_ho_in_fail_msc_clears() );
12412 execute( TC_ho_in_fail_msc_clears_after_ho_detect() );
12413 execute( TC_ho_in_fail_no_detect() );
12414 execute( TC_ho_in_fail_no_detect2() );
Oliver Smith7a8594a2023-02-13 14:30:49 +010012415 execute( TC_ho_in_fail_mgw_mdcx_timeout() );
Oliver Smith4eed06f2023-02-15 15:43:19 +010012416 execute( TC_ho_in_fail_ipa_crcx_timeout() );
Neels Hofmeyra23f3b12022-03-02 19:57:12 +010012417 execute( TC_ho_into_this_bsc_sccp_cr_without_bssap() );
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012418
Neels Hofmeyr91401012019-07-11 00:42:35 +020012419 execute( TC_ho_neighbor_config_1() );
12420 execute( TC_ho_neighbor_config_2() );
12421 execute( TC_ho_neighbor_config_3() );
12422 execute( TC_ho_neighbor_config_4() );
12423 execute( TC_ho_neighbor_config_5() );
12424 execute( TC_ho_neighbor_config_6() );
12425 execute( TC_ho_neighbor_config_7() );
12426
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012427 execute( TC_bssap_rlsd_does_not_cause_bssmap_reset() );
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010012428 execute( TC_bssmap_clear_does_not_cause_bssmap_reset() );
Neels Hofmeyrfd445c32018-03-09 15:39:31 +010012429 execute( TC_ms_rel_ind_does_not_cause_bssmap_reset() );
Harald Welte94e0c342018-04-07 11:33:23 +020012430
12431 execute( TC_dyn_pdch_ipa_act_deact() );
12432 execute( TC_dyn_pdch_ipa_act_nack() );
12433 execute( TC_dyn_pdch_osmo_act_deact() );
12434 execute( TC_dyn_pdch_osmo_act_nack() );
Pau Espin Pedrol37a4c152021-11-16 19:02:23 +010012435 execute( TC_dyn_ts_sdcch8_act_deact() );
12436 execute( TC_dyn_ts_sdcch8_all_subslots_used() );
12437 execute( TC_dyn_ts_sdcch8_tch_call_act_deact() );
12438 execute( TC_dyn_ts_sdcch8_act_nack() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012439
Stefan Sperling0796a822018-10-05 13:01:39 +020012440 execute( TC_chopped_ipa_ping() );
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +020012441 execute( TC_chopped_ipa_payload() );
Stefan Sperling0796a822018-10-05 13:01:39 +020012442
Pau Espin Pedrol8f773632019-11-05 11:46:53 +010012443 /* Power control related */
12444 execute( TC_assignment_verify_ms_power_params_ie() );
Vadim Yanitskiy4b233042021-06-30 00:58:43 +020012445 execute( TC_c0_power_red_mode() );
Neels Hofmeyr4f118412020-06-04 15:25:10 +020012446
12447 /* MSC pooling */
12448 /* FIXME: in SCCPlite, indicating how many MSCs should be connected does currently not work. Since
12449 * RESET->RESET-ACK is unconditionally negotiated for all configured MSCs, they always all appear as connected
12450 * to osmo-bsc. The MSC pooling tests however require disconnecting selected MSCs, and hence don't work out as
12451 * intended on SCCPlite. So for now, run these only for SCCP/M3UA. */
12452 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12453 execute( TC_mscpool_L3Compl_on_1_msc() );
12454 execute( TC_mscpool_L3Complete_by_imsi_round_robin() );
12455 execute( TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() );
12456 execute( TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() );
12457 execute( TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() );
12458 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() );
12459 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_1() );
12460 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_2() );
12461 execute( TC_mscpool_LU_by_tmsi_from_other_PLMN() );
12462 execute( TC_mscpool_paging_and_response_imsi() );
12463 execute( TC_mscpool_paging_and_response_tmsi() );
12464 execute( TC_mscpool_no_allow_attach_round_robin() );
12465 execute( TC_mscpool_no_allow_attach_valid_nri() );
12466 }
12467
Harald Welte99f3ca02018-06-14 13:40:29 +020012468 execute( TC_early_conn_fail() );
12469 execute( TC_late_conn_fail() );
Oliver Smithaf03bef2021-08-24 15:34:51 +020012470 execute( TC_stats_conn_fail() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012471
Philipp Maier783681c2020-07-16 16:47:06 +020012472 /* Emergency call handling (deny / allow) */
12473 execute( TC_assignment_emerg_setup_allow() );
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +010012474 execute( TC_assignment_emerg_setup_allow_imei() );
Philipp Maier783681c2020-07-16 16:47:06 +020012475 execute( TC_assignment_emerg_setup_deny_msc() );
12476 execute( TC_assignment_emerg_setup_deny_bts() );
Philipp Maier82812002020-08-13 18:48:27 +020012477 execute( TC_emerg_premption() );
12478
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +070012479 /* Frequency hopping parameters handling */
12480 execute( TC_fh_params_chan_activ() );
12481 execute( TC_fh_params_imm_ass() );
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070012482 execute( TC_fh_params_assignment_cmd() );
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070012483 execute( TC_fh_params_handover_cmd() );
Vadim Yanitskiyca974032020-09-01 07:20:39 +070012484 execute( TC_fh_params_si4_cbch() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012485
12486 if (mp_enable_lcs_tests) {
12487 execute( TC_lcs_loc_req_for_active_ms() );
12488 execute( TC_lcs_loc_req_for_active_ms_ta_req() );
12489 execute( TC_lcs_loc_req_for_idle_ms() );
12490 execute( TC_lcs_loc_req_no_subscriber() );
12491 execute( TC_lcs_loc_req_for_active_ms_le_timeout() );
12492 execute( TC_lcs_loc_req_for_active_ms_le_timeout2() );
12493 execute( TC_lcs_loc_req_for_idle_ms_no_pag_resp() );
12494 execute( TC_cm_service_during_lcs_loc_req() );
12495 execute( TC_ho_during_lcs_loc_req() );
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020012496 execute( TC_emerg_call_and_lcs_loc_req() );
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020012497 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() );
12498 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012499 }
Neels Hofmeyrbf037052020-10-28 22:52:02 +000012500
12501 execute( TC_no_msc() );
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000012502
12503 execute( TC_refuse_chan_act_to_vamos() );
12504 execute( TC_refuse_mode_modif_to_vamos() );
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000012505
12506 execute( TC_reassignment_fr() );
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020012507
12508 execute( TC_cm_reestablishment() );
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020012509
12510 execute( TC_imm_ass_post_chan_ack() );
12511 execute( TC_imm_ass_pre_chan_ack() );
Neels Hofmeyr23158742021-09-07 19:08:07 +020012512 execute( TC_imm_ass_pre_ts_ack() );
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020012513 execute( TC_imm_ass_pre_chan_ack_dyn_ts() );
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020012514 execute( TC_imm_ass_pre_ts_ack_dyn_ts() );
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020012515
12516 execute( TC_ctrl_trx_rf_locked() );
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012517
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020012518 execute( TC_ratectr_all_available_allocated() );
12519 execute( TC_ratectr_all_available_allocated_dyn() );
12520
Neels Hofmeyrb7581872021-11-07 14:02:49 +010012521 execute( TC_cm_serv_rej() );
12522
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012523 execute( TC_lost_sdcch_during_assignment() );
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012524
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012525 /* Channel allocator */
12526 execute( TC_chan_alloc_algo_ascending() );
12527 execute( TC_chan_alloc_algo_descending() );
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012528 execute( TC_chan_alloc_algo_ass_dynamic() );
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012529
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012530 /* MGW pool */
Pau Espin Pedrol4e431832023-02-08 12:43:47 +010012531 execute( TC_mgwpool_all_used() );
12532 execute( TC_mgwpool_blocked_not_used() );
12533 execute( TC_mgwpool_pin_bts() );
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012534
Oliver Smithc9a5f532022-10-21 11:32:23 +020012535 execute( TC_ho_meas_rep_multi_band() );
12536
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012537 /* Run TC_ho_out_of_this_bsc last, because it may trigger a segfault before osmo-bsc's patch
12538 * with change-id I5a3345ab0005a73597f5c27207480912a2f5aae6 */
12539 execute( TC_ho_out_of_this_bsc() );
Harald Welte28d943e2017-11-25 15:00:50 +010012540}
12541
12542}